Ticket #3011: squashed.patch

File squashed.patch, 357.4 KB (added by Philip Taylor, 9 years ago)
  • build/premake/premake4.lua

    From b934df2a59a4fb6fd56a36018349c948c1105e9e Mon Sep 17 00:00:00 2001
    From: Philip Taylor <philip@zaynar.co.uk>
    Date: Tue, 20 Jan 2015 23:15:28 +0000
    Subject: [PATCH] Everything squashed together.
    
    ---
     build/premake/premake4.lua                         |    3 +-
     source/graphics/ColladaManager.cpp                 |   32 +-
     source/graphics/FontManager.cpp                    |    6 +-
     source/graphics/LOSTexture.cpp                     |    4 +-
     source/graphics/MapGenerator.cpp                   |   22 +-
     source/graphics/MapReader.cpp                      |   14 +-
     source/graphics/MapWriter.cpp                      |    4 +-
     source/graphics/MeshManager.cpp                    |    4 +-
     source/graphics/Model.cpp                          |    2 +-
     source/graphics/ModelAbstract.cpp                  |    4 +-
     source/graphics/ObjectBase.cpp                     |    4 +-
     source/graphics/ObjectEntry.cpp                    |   12 +-
     source/graphics/ObjectManager.cpp                  |    2 +-
     source/graphics/ParticleEmitterType.cpp            |    2 +-
     source/graphics/ShaderManager.cpp                  |    8 +-
     source/graphics/ShaderProgram.cpp                  |   18 +-
     source/graphics/ShaderProgramFFP.cpp               |    2 +-
     source/graphics/SkeletonAnimManager.cpp            |    8 +-
     source/graphics/TerrainProperties.cpp              |   14 +-
     source/graphics/TerrainTextureEntry.cpp            |    8 +-
     source/graphics/TerrainTextureManager.cpp          |    6 +-
     source/graphics/TextRenderer.cpp                   |    8 +
     source/graphics/TextRenderer.h                     |    7 +
     source/graphics/TextureConverter.cpp               |   26 +-
     source/graphics/TextureManager.cpp                 |   10 +-
     source/graphics/scripting/JSInterface_GameView.cpp |    4 +-
     source/graphics/tests/test_MeshManager.h           |    4 +-
     source/gui/CGUI.cpp                                |   82 +-
     source/gui/CGUIScrollBarVertical.cpp               |    2 +-
     source/gui/COList.cpp                              |    6 +-
     source/gui/GUIManager.cpp                          |   20 +-
     source/gui/GUIRenderer.cpp                         |    4 +-
     source/gui/GUITooltip.cpp                          |   10 +-
     source/gui/GUIbase.cpp                             |    6 +-
     source/gui/GUItext.cpp                             |   34 +-
     source/gui/GUIutil.cpp                             |   22 +-
     source/gui/IGUIObject.cpp                          |    2 +-
     source/gui/scripting/ScriptFunctions.cpp           |   12 +-
     source/i18n/L10n.cpp                               |   14 +-
     source/lib/path.h                                  |    7 +
     source/lib/secure_crt.cpp                          |    2 +-
     source/lib/self_test.h                             |    3 +
     source/lib/sysdep/os/linux/dir_watch_inotify.cpp   |    4 +-
     source/lib/sysdep/os/unix/printf.cpp               |   39 -
     source/lib/sysdep/os/win/wprintf.cpp               |  526 -----
     source/lib/sysdep/sysdep.h                         |   11 -
     source/lib/sysdep/tests/test_printf.h              |   99 -
     source/lib/tests/test_secure_crt.h                 |   29 +-
     source/lobby/XmppClient.cpp                        |    8 +-
     source/main.cpp                                    |    2 +-
     source/network/NetClient.cpp                       |    8 +-
     source/network/NetFileTransfer.cpp                 |   18 +-
     source/network/NetHost.cpp                         |    6 +-
     source/network/NetMessage.cpp                      |    6 +-
     source/network/NetServer.cpp                       |   42 +-
     source/network/NetSession.cpp                      |    6 +-
     source/network/NetTurnManager.cpp                  |   31 +-
     source/ps/CLogger.cpp                              |  119 +-
     source/ps/CLogger.h                                |   29 +-
     source/ps/CStrIntern.cpp                           |    2 +-
     source/ps/ConfigDB.cpp                             |   26 +-
     source/ps/DllLoader.cpp                            |    6 +-
     source/ps/FileIo.cpp                               |    2 +-
     source/ps/Filesystem.cpp                           |    2 +-
     source/ps/GameSetup/Config.cpp                     |    4 +-
     source/ps/GameSetup/GameSetup.cpp                  |   26 +-
     source/ps/GameSetup/HWDetect.cpp                   |    2 +-
     source/ps/GameSetup/Paths.cpp                      |    2 +-
     source/ps/Hotkey.cpp                               |    2 +-
     source/ps/Joystick.cpp                             |   10 +-
     source/ps/Overlay.cpp                              |    8 +-
     source/ps/Preprocessor.cpp                         |    4 +-
     source/ps/PreprocessorWrapper.cpp                  |    4 +-
     source/ps/ProfileViewer.cpp                        |    4 +-
     source/ps/Profiler2.cpp                            |   10 +-
     source/ps/SavedGame.cpp                            |    4 +-
     source/ps/TemplateLoader.cpp                       |   26 +-
     source/ps/Util.cpp                                 |    8 +-
     source/ps/VideoMode.cpp                            |   22 +-
     source/ps/World.cpp                                |    2 +-
     source/ps/XML/RelaxNG.cpp                          |   10 +-
     source/ps/XML/XMLWriter.cpp                        |    2 +-
     source/ps/XML/Xeromyces.cpp                        |   14 +-
     source/ps/XML/tests/test_RelaxNG.h                 |    6 +-
     source/ps/scripting/JSInterface_ConfigDB.cpp       |    2 +-
     source/ps/scripting/JSInterface_Console.cpp        |    2 +-
     source/ps/scripting/JSInterface_VFS.cpp            |    2 +-
     source/ps/tests/test_CLogger.h                     |   71 +-
     source/renderer/DecalRData.cpp                     |    4 +-
     source/renderer/ModelRenderer.cpp                  |    2 +-
     source/renderer/PatchRData.cpp                     |    2 +-
     source/renderer/PostprocManager.cpp                |    8 +-
     source/renderer/Renderer.cpp                       |   12 +-
     source/renderer/ShadowMap.cpp                      |    4 +-
     source/renderer/SkyManager.cpp                     |    4 +-
     source/renderer/TerrainRenderer.cpp                |    2 +-
     source/renderer/VertexBufferManager.cpp            |    2 +-
     source/renderer/WaterManager.cpp                   |    6 +-
     source/scriptinterface/DebuggingServer.cpp         |    4 +-
     source/scriptinterface/ScriptInterface.cpp         |   36 +-
     source/scriptinterface/ThreadDebugger.cpp          |    8 +-
     .../scriptinterface/tests/test_ScriptInterface.h   |   10 +-
     source/simulation2/Simulation2.cpp                 |   14 +-
     source/simulation2/components/CCmpAIManager.cpp    |   36 +-
     source/simulation2/components/CCmpCommandQueue.cpp |    4 +-
     source/simulation2/components/CCmpObstruction.cpp  |    6 +-
     source/simulation2/components/CCmpPathfinder.cpp   |    4 +-
     source/simulation2/components/CCmpPosition.cpp     |   24 +-
     .../components/CCmpProjectileManager.cpp           |    2 +-
     .../components/CCmpRallyPointRenderer.cpp          |    2 +-
     source/simulation2/components/CCmpRangeManager.cpp |   16 +-
     .../simulation2/components/CCmpTemplateManager.cpp |    4 +-
     source/simulation2/components/CCmpUnitMotion.cpp   |    2 +-
     source/simulation2/components/CCmpVisualActor.cpp  |    6 +-
     source/simulation2/components/ICmpVisibility.cpp   |    2 +-
     .../scripting/EngineScriptConversions.cpp          |    2 +-
     .../scripting/MessageTypeConversions.cpp           |   22 +-
     source/simulation2/scripting/ScriptComponent.cpp   |    6 +-
     source/simulation2/scripting/ScriptComponent.h     |    4 +-
     .../simulation2/serialization/BinarySerializer.cpp |    6 +-
     source/simulation2/system/ComponentManager.cpp     |   18 +-
     .../system/ComponentManagerSerialization.cpp       |    8 +-
     source/simulation2/system/ParamNode.cpp            |    4 +-
     source/simulation2/tests/test_ComponentManager.h   |    6 +-
     source/soundmanager/SoundManager.cpp               |   10 +-
     source/soundmanager/data/OggData.cpp               |    2 +-
     source/soundmanager/data/SoundData.cpp             |    2 +-
     source/soundmanager/items/CSoundBase.cpp           |    2 +-
     source/soundmanager/scripting/SoundGroup.cpp       |    6 +-
     source/test_setup.cpp                              |    5 +
     source/third_party/cppformat/format.cpp            | 1312 +++++++++++++
     source/third_party/cppformat/format.h              | 2077 ++++++++++++++++++++
     source/tools/atlas/GameInterface/GameLoop.cpp      |    2 +-
     .../atlas/GameInterface/Handlers/MapHandlers.cpp   |    8 +-
     .../GameInterface/Handlers/ObjectHandlers.cpp      |    2 +-
     135 files changed, 4062 insertions(+), 1400 deletions(-)
     delete mode 100644 source/lib/sysdep/os/unix/printf.cpp
     delete mode 100644 source/lib/sysdep/os/win/wprintf.cpp
     delete mode 100644 source/lib/sysdep/tests/test_printf.h
     create mode 100644 source/third_party/cppformat/format.cpp
     create mode 100644 source/third_party/cppformat/format.h
    
    diff --git a/build/premake/premake4.lua b/build/premake/premake4.lua
    index 44dbd76..cfb6980 100644
    a b function setup_all_libs ()  
    741741        "maths",
    742742        "maths/scripting",
    743743        "i18n",
    744         "i18n/scripting"
     744        "i18n/scripting",
     745        "third_party/cppformat",
    745746    }
    746747    extern_libs = {
    747748        "spidermonkey",
  • source/graphics/ColladaManager.cpp

    diff --git a/source/graphics/ColladaManager.cpp b/source/graphics/ColladaManager.cpp
    index 35552e1..c7b806a 100644
    a b namespace  
    4242        VfsPath* path = static_cast<VfsPath*>(cb_data);
    4343
    4444        if (severity == LOG_INFO)
    45             LOGMESSAGE(L"%ls: %hs", path->string().c_str(), text);
     45            LOGMESSAGE("%s: %s", path->string8(), text);
    4646        else if (severity == LOG_WARNING)
    47             LOGWARNING(L"%ls: %hs", path->string().c_str(), text);
     47            LOGWARNING("%s: %s", path->string8(), text);
    4848        else
    49             LOGERROR(L"%ls: %hs", path->string().c_str(), text);
     49            LOGERROR("%s: %s", path->string8(), text);
    5050    }
    5151
    5252    void ColladaOutput(void* cb_data, const char* data, unsigned int length)
    public:  
    9999        if (!dll.IsLoaded() && !TryLoadDLL())
    100100            return ERR::FAIL;   
    101101
    102         LOGMESSAGE(L"Hotloading skeleton definitions from '%ls'", path.string().c_str());
     102        LOGMESSAGE("Hotloading skeleton definitions from '%s'", path.string8());
    103103        // Set the filename for the logger to report
    104104        set_logger(ColladaLog, const_cast<void*>(static_cast<const void*>(&path)));
    105105
    106106        CVFSFile skeletonFile;
    107107        if (skeletonFile.Load(m_VFS, path) != PSRETURN_OK)
    108108        {
    109             LOGERROR(L"Failed to read skeleton defintions from '%ls'", path.string().c_str());
     109            LOGERROR("Failed to read skeleton defintions from '%s'", path.string8());
    110110            return ERR::FAIL;
    111111        }
    112112
    113113        int ok = set_skeleton_definitions((const char*)skeletonFile.GetBuffer(), (int)skeletonFile.GetBufferSize());
    114114        if (ok < 0)
    115115        {
    116             LOGERROR(L"Failed to load skeleton definitions from '%ls'", path.string().c_str());
     116            LOGERROR("Failed to load skeleton definitions from '%s'", path.string8());
    117117            return ERR::FAIL;
    118118        }
    119119
    public:  
    189189    {
    190190        if (!dll.LoadDLL())
    191191        {
    192             LOGERROR(L"Failed to load COLLADA conversion DLL");
     192            LOGERROR("Failed to load COLLADA conversion DLL");
    193193            return false;
    194194        }
    195195
    public:  
    202202        }
    203203        catch (PSERROR_DllLoader&)
    204204        {
    205             LOGERROR(L"Failed to load symbols from COLLADA conversion DLL");
     205            LOGERROR("Failed to load symbols from COLLADA conversion DLL");
    206206            dll.Unload();
    207207            return false;
    208208        }
    public:  
    214214        VfsPaths pathnames;
    215215        if (vfs::GetPathnames(m_VFS, L"art/skeletons/", L"*.xml", pathnames) < 0)
    216216        {
    217             LOGERROR(L"No skeleton definition files present");
     217            LOGERROR("No skeleton definition files present");
    218218            return false;
    219219        }
    220220
    221221        bool loaded = false;
    222222        for (VfsPaths::const_iterator it = pathnames.begin(); it != pathnames.end(); ++it)
    223223        {
    224             LOGMESSAGE(L"Loading skeleton definitions from '%ls'", it->string().c_str());
     224            LOGMESSAGE("Loading skeleton definitions from '%s'", it->string8());
    225225            // Set the filename for the logger to report
    226226            set_logger(ColladaLog, const_cast<void*>(static_cast<const void*>(&(*it))));
    227227
    228228            CVFSFile skeletonFile;
    229229            if (skeletonFile.Load(m_VFS, *it) != PSRETURN_OK)
    230230            {
    231                 LOGERROR(L"Failed to read skeleton defintions from '%ls'", it->string().c_str());
     231                LOGERROR("Failed to read skeleton defintions from '%s'", it->string8());
    232232                continue;
    233233            }
    234234
    235235            int ok = set_skeleton_definitions((const char*)skeletonFile.GetBuffer(), (int)skeletonFile.GetBufferSize());
    236236            if (ok < 0)
    237237            {
    238                 LOGERROR(L"Failed to load skeleton definitions from '%ls'", it->string().c_str());
     238                LOGERROR("Failed to load skeleton definitions from '%s'", it->string8());
    239239                continue;
    240240            }
    241241
    public:  
    243243        }
    244244
    245245        if (!loaded)
    246             LOGERROR(L"Failed to load any skeleton definitions");
     246            LOGERROR("Failed to load any skeleton definitions");
    247247
    248248        return loaded;
    249249    }
    public:  
    267267            VfsPaths paths;
    268268            if (vfs::GetPathnames(m_VFS, L"art/skeletons/", L"*.xml", paths) != INFO::OK)
    269269            {
    270                 LOGWARNING(L"Failed to load skeleton definitions");
     270                LOGWARNING("Failed to load skeleton definitions");
    271271                return;
    272272            }
    273273
    public:  
    287287                //  should never happen, unless there really is a problem
    288288                if (m_VFS->GetFileInfo(*it, &fileInfo) != INFO::OK)
    289289                {
    290                     LOGERROR(L"Failed to stat '%ls' for DAE caching", it->string().c_str());
     290                    LOGERROR("Failed to stat '%s' for DAE caching", it->string8());
    291291                }
    292292                else
    293293                {
    public:  
    298298
    299299            // Check if we were able to load any skeleton files
    300300            if (m_skeletonHashes.empty())
    301                 LOGERROR(L"Failed to stat any skeleton definitions for DAE caching");
     301                LOGERROR("Failed to stat any skeleton definitions for DAE caching");
    302302                // We can continue, something else will break if we try loading a skeletal model
    303303
    304304            m_skeletonHashInvalidated = false;
  • source/graphics/FontManager.cpp

    diff --git a/source/graphics/FontManager.cpp b/source/graphics/FontManager.cpp
    index c7180ce..f7038c0 100644
    a b bool CFontManager::ReadFont(CFont* font, CStrIntern fontName)  
    5959    const VfsPath fntName(fontName.string() + ".fnt");
    6060    if (g_VFS->LoadFile(path / fntName, buf, size) < 0)
    6161    {
    62         LOGERROR(L"Failed to open font file %ls", (path / fntName).string().c_str());
     62        LOGERROR("Failed to open font file %s", (path / fntName).string8());
    6363        return false;
    6464    }
    6565    std::istringstream FNTStream(std::string((const char*)buf.get(), size));
    bool CFontManager::ReadFont(CFont* font, CStrIntern fontName)  
    6868    FNTStream >> Version;
    6969    if (Version != 101) // Make sure this is from a recent version of the font builder
    7070    {
    71         LOGERROR(L"Font %hs has invalid version", fontName.c_str());
     71        LOGERROR("Font %s has invalid version", fontName.c_str());
    7272        return 0;
    7373    }
    7474
    bool CFontManager::ReadFont(CFont* font, CStrIntern fontName)  
    102102
    103103        if (Codepoint < 0 || Codepoint > 0xFFFF)
    104104        {
    105             LOGWARNING(L"Font %hs has invalid codepoint 0x%x", fontName.c_str(), Codepoint);
     105            LOGWARNING("Font %s has invalid codepoint 0x%x", fontName.c_str(), Codepoint);
    106106            continue;
    107107        }
    108108
  • source/graphics/LOSTexture.cpp

    diff --git a/source/graphics/LOSTexture.cpp b/source/graphics/LOSTexture.cpp
    index 2bde7bb..ce6e136 100644
    a b bool CLOSTexture::CreateShader()  
    8282   
    8383    if (!m_ShaderInitialized)
    8484    {
    85         LOGERROR(L"Failed to load SmoothLOS shader, disabling.");
     85        LOGERROR("Failed to load SmoothLOS shader, disabling.");
    8686        g_Renderer.m_Options.m_SmoothLOS = false;
    8787        return false;
    8888    }
    void CLOSTexture::InterpolateLOS()  
    163163    GLenum status = pglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
    164164    if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
    165165    {
    166         LOGWARNING(L"LOS framebuffer object incomplete: 0x%04X", status);
     166        LOGWARNING("LOS framebuffer object incomplete: 0x%04X", status);
    167167    }
    168168
    169169    m_smoothShader->BeginPass();
  • source/graphics/MapGenerator.cpp

    diff --git a/source/graphics/MapGenerator.cpp b/source/graphics/MapGenerator.cpp
    index 780ca79..ed9a8d0 100644
    a b bool CMapGeneratorWorker::Run()  
    111111    JS::RootedValue settingsVal(cx);
    112112    if (!m_ScriptInterface->ParseJSON(m_Settings, &settingsVal) && settingsVal.isUndefined())
    113113    {
    114         LOGERROR(L"CMapGeneratorWorker::Run: Failed to parse settings");
     114        LOGERROR("CMapGeneratorWorker::Run: Failed to parse settings");
    115115        return false;
    116116    }
    117117   
    bool CMapGeneratorWorker::Run()  
    119119    u32 seed;
    120120    if (!m_ScriptInterface->GetProperty(settingsVal, "Seed", seed))
    121121    {   // No seed specified
    122         LOGWARNING(L"CMapGeneratorWorker::Run: No seed value specified - using 0");
     122        LOGWARNING("CMapGeneratorWorker::Run: No seed value specified - using 0");
    123123        seed = 0;
    124124    }
    125125
    bool CMapGeneratorWorker::Run()  
    129129    JS::RootedValue global(cx, m_ScriptInterface->GetGlobalObject());
    130130    if (!m_ScriptInterface->SetProperty(global, "g_MapSettings", settingsVal))
    131131    {
    132         LOGERROR(L"CMapGeneratorWorker::Run: Failed to define g_MapSettings");
     132        LOGERROR("CMapGeneratorWorker::Run: Failed to define g_MapSettings");
    133133        return false;
    134134    }
    135135
    136136    // Load RMS
    137     LOGMESSAGE(L"Loading RMS '%ls'", m_ScriptPath.string().c_str());
     137    LOGMESSAGE("Loading RMS '%s'", m_ScriptPath.string8());
    138138    if (!m_ScriptInterface->LoadGlobalScriptFile(m_ScriptPath))
    139139    {
    140         LOGERROR(L"CMapGeneratorWorker::Run: Failed to load RMS '%ls'", m_ScriptPath.string().c_str());
     140        LOGERROR("CMapGeneratorWorker::Run: Failed to load RMS '%s'", m_ScriptPath.string8());
    141141        return false;
    142142    }
    143143
    std::vector<std::string> CMapGeneratorWorker::GetCivData(ScriptInterface::CxPriv  
    210210            PSRETURN ret = file.Load(g_VFS, *it);
    211211            if (ret != PSRETURN_OK)
    212212            {
    213                 LOGERROR(L"CMapGeneratorWorker::GetCivData: Failed to load file '%ls': %hs", path.string().c_str(), GetErrorString(ret));
     213                LOGERROR("CMapGeneratorWorker::GetCivData: Failed to load file '%s': %s", path.string8(), GetErrorString(ret));
    214214            }
    215215            else
    216216            {
    std::vector<std::string> CMapGeneratorWorker::GetCivData(ScriptInterface::CxPriv  
    222222    {
    223223        // Some error reading directory
    224224        wchar_t error[200];
    225         LOGERROR(L"CMapGeneratorWorker::GetCivData: Error reading directory '%ls': %ls", path.string().c_str(), StatusDescription(ret, error, ARRAY_SIZE(error)));
     225        LOGERROR("CMapGeneratorWorker::GetCivData: Error reading directory '%s': %s", path.string8(), utf8_from_wstring(StatusDescription(ret, error, ARRAY_SIZE(error))));
    226226    }
    227227
    228228    return data;
    CParamNode CMapGeneratorWorker::GetTemplate(ScriptInterface::CxPrivate* pCxPriva  
    234234    CMapGeneratorWorker* self = static_cast<CMapGeneratorWorker*>(pCxPrivate->pCBData);
    235235    const CParamNode& templateRoot = self->m_TemplateLoader.GetTemplateFileData(templateName).GetChild("Entity");
    236236    if (!templateRoot.IsOk())
    237         LOGERROR(L"Invalid template found for '%hs'", templateName.c_str());
     237        LOGERROR("Invalid template found for '%s'", templateName.c_str());
    238238   
    239239    return templateRoot;
    240240}
    bool CMapGeneratorWorker::LoadScripts(const std::wstring& libraryName)  
    271271    {
    272272        for (VfsPaths::iterator it = pathnames.begin(); it != pathnames.end(); ++it)
    273273        {
    274             LOGMESSAGE(L"Loading map generator script '%ls'", it->string().c_str());
     274            LOGMESSAGE("Loading map generator script '%s'", it->string8());
    275275
    276276            if (!m_ScriptInterface->LoadGlobalScriptFile(*it))
    277277            {
    278                 LOGERROR(L"CMapGeneratorWorker::LoadScripts: Failed to load script '%ls'", it->string().c_str());
     278                LOGERROR("CMapGeneratorWorker::LoadScripts: Failed to load script '%s'", it->string8());
    279279                return false;
    280280            }
    281281        }
    bool CMapGeneratorWorker::LoadScripts(const std::wstring& libraryName)  
    284284    {
    285285        // Some error reading directory
    286286        wchar_t error[200];
    287         LOGERROR(L"CMapGeneratorWorker::LoadScripts: Error reading scripts in directory '%ls': %ls", path.string().c_str(), StatusDescription(ret, error, ARRAY_SIZE(error)));
     287        LOGERROR("CMapGeneratorWorker::LoadScripts: Error reading scripts in directory '%s': %s", path.string8(), utf8_from_wstring(StatusDescription(ret, error, ARRAY_SIZE(error))));
    288288        return false;
    289289    }
    290290
  • source/graphics/MapReader.cpp

    diff --git a/source/graphics/MapReader.cpp b/source/graphics/MapReader.cpp
    index 090b70e..9683323 100644
    a b int CXMLReader::ReadEntities(XMBElement parent, double end_time)  
    10521052        entity_id_t player = cmpPlayerManager->GetPlayerByID(PlayerID);
    10531053        if (ent == INVALID_ENTITY || player == INVALID_ENTITY)
    10541054        {   // Don't add entities with invalid player IDs
    1055             LOGERROR(L"Failed to load entity template '%ls'", TemplateName.c_str());
     1055            LOGERROR("Failed to load entity template '%s'", utf8_from_wstring(TemplateName));
    10561056        }
    10571057        else
    10581058        {
    int CMapReader::ParseTerrain()  
    13321332    //  an error here should stop the loading process
    13331333#define GET_TERRAIN_PROPERTY(val, prop, out)\
    13341334    if (!pSimulation2->GetScriptInterface().GetProperty(val, #prop, out))\
    1335         {   LOGERROR(L"CMapReader::ParseTerrain() failed to get '%hs' property", #prop);\
     1335        {   LOGERROR("CMapReader::ParseTerrain() failed to get '%s' property", #prop);\
    13361336            throw PSERROR_Game_World_MapLoadFailed("Error parsing terrain data.\nCheck application log for details"); }
    13371337
    13381338    JS::RootedValue tmpMapData(cx, m_MapData.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
    int CMapReader::ParseEntities()  
    14111411    std::vector<Entity> entities;
    14121412
    14131413    if (!pSimulation2->GetScriptInterface().GetProperty(tmpMapData, "entities", entities))
    1414         LOGWARNING(L"CMapReader::ParseEntities() failed to get 'entities' property");
     1414        LOGWARNING("CMapReader::ParseEntities() failed to get 'entities' property");
    14151415
    14161416    CSimulation2& sim = *pSimulation2;
    14171417    CmpPtr<ICmpPlayerManager> cmpPlayerManager(sim, SYSTEM_ENTITY);
    int CMapReader::ParseEntities()  
    14301430        entity_id_t player = cmpPlayerManager->GetPlayerByID(currEnt.playerID);
    14311431        if (ent == INVALID_ENTITY || player == INVALID_ENTITY)
    14321432        {   // Don't add entities with invalid player IDs
    1433             LOGERROR(L"Failed to load entity template '%ls'", currEnt.templateName.c_str());
     1433            LOGERROR("Failed to load entity template '%s'", utf8_from_wstring(currEnt.templateName));
    14341434        }
    14351435        else
    14361436        {
    int CMapReader::ParseEnvironment()  
    14761476
    14771477#define GET_ENVIRONMENT_PROPERTY(val, prop, out)\
    14781478    if (!pSimulation2->GetScriptInterface().GetProperty(val, #prop, out))\
    1479         LOGWARNING(L"CMapReader::ParseEnvironment() failed to get '%hs' property", #prop);
     1479        LOGWARNING("CMapReader::ParseEnvironment() failed to get '%s' property", #prop);
    14801480
    14811481    JS::RootedValue envObj(cx);
    14821482    GET_ENVIRONMENT_PROPERTY(tmpMapData, Environment, &envObj)
    14831483
    14841484    if (envObj.isUndefined())
    14851485    {
    1486         LOGWARNING(L"CMapReader::ParseEnvironment(): Environment settings not found");
     1486        LOGWARNING("CMapReader::ParseEnvironment(): Environment settings not found");
    14871487        return 0;
    14881488    }
    14891489
    int CMapReader::ParseCamera()  
    15811581
    15821582#define GET_CAMERA_PROPERTY(val, prop, out)\
    15831583    if (!pSimulation2->GetScriptInterface().GetProperty(val, #prop, out))\
    1584         LOGWARNING(L"CMapReader::ParseCamera() failed to get '%hs' property", #prop);
     1584        LOGWARNING("CMapReader::ParseCamera() failed to get '%s' property", #prop);
    15851585
    15861586    JS::RootedValue tmpMapData(cx, m_MapData.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
    15871587    JS::RootedValue cameraObj(cx);
  • source/graphics/MapWriter.cpp

    diff --git a/source/graphics/MapWriter.cpp b/source/graphics/MapWriter.cpp
    index 6b00443..4259f3f 100644
    a b void CMapWriter::SaveMap(const VfsPath& pathname, CTerrain* pTerrain,  
    7171    }
    7272    catch (PSERROR_File_WriteFailed&)
    7373    {
    74         LOGERROR(L"Failed to write map '%ls'", pathname.string().c_str());
     74        LOGERROR("Failed to write map '%s'", pathname.string8());
    7575        return;
    7676    }
    7777
    void CMapWriter::WriteXML(const VfsPath& filename,  
    447447        }
    448448    }
    449449    if (!XML_StoreVFS(g_VFS, filename))
    450         LOGERROR(L"Failed to write map '%ls'", filename.string().c_str());
     450        LOGERROR("Failed to write map '%s'", filename.string8());
    451451}
  • source/graphics/MeshManager.cpp

    diff --git a/source/graphics/MeshManager.cpp b/source/graphics/MeshManager.cpp
    index 0a827d0..103c401 100644
    a b CModelDefPtr CMeshManager::GetMesh(const VfsPath& pathname)  
    5353
    5454    if (pmdFilename.empty())
    5555    {
    56         LOGERROR(L"Could not load mesh '%ls'", pathname.string().c_str());
     56        LOGERROR("Could not load mesh '%s'", pathname.string8());
    5757        return CModelDefPtr();
    5858    }
    5959
    CModelDefPtr CMeshManager::GetMesh(const VfsPath& pathname)  
    6565    }
    6666    catch (PSERROR_File&)
    6767    {
    68         LOGERROR(L"Could not load mesh '%ls'", pmdFilename.string().c_str());
     68        LOGERROR("Could not load mesh '%s'", pmdFilename.string8());
    6969        return CModelDefPtr();
    7070    }
    7171}
  • source/graphics/Model.cpp

    diff --git a/source/graphics/Model.cpp b/source/graphics/Model.cpp
    index 127bbd5..c4bb532 100644
    a b bool CModel::SetAnimation(CSkeletonAnim* anim, bool once)  
    473473        if (anim->m_AnimDef && anim->m_AnimDef->GetNumKeys() != m_pModelDef->GetNumBones())
    474474        {
    475475            // mismatch between model's skeleton and animation's skeleton
    476             LOGERROR(L"Mismatch between model's skeleton and animation's skeleton (%lu model bones != %lu animation keys)",
     476            LOGERROR("Mismatch between model's skeleton and animation's skeleton (%lu model bones != %lu animation keys)",
    477477                    (unsigned long)m_pModelDef->GetNumBones(), (unsigned long)anim->m_AnimDef->GetNumKeys());
    478478            return false;
    479479        }
  • source/graphics/ModelAbstract.cpp

    diff --git a/source/graphics/ModelAbstract.cpp b/source/graphics/ModelAbstract.cpp
    index aa56125..769de5d 100644
    a b void CModelAbstract::CalcSelectionBox()  
    5757            {
    5858                // TODO: unimplemented
    5959                m_SelectionBox.SetEmpty();
    60                 LOGWARNING(L"[ModelAbstract] TODO: Cylinder selection boxes are not yet implemented. Use BOX or BOUNDS selection shapes instead.");
     60                LOGWARNING("[ModelAbstract] TODO: Cylinder selection boxes are not yet implemented. Use BOX or BOUNDS selection shapes instead.");
    6161            }
    6262            break;
    6363        default:
    6464            {
    6565                m_SelectionBox.SetEmpty();
    66                 //LOGWARNING(L"[ModelAbstract] Unrecognized selection shape type: %ld", m_CustomSelectionShape->m_Type);
     66                //LOGWARNING("[ModelAbstract] Unrecognized selection shape type: %ld", m_CustomSelectionShape->m_Type);
    6767                debug_warn("[ModelAbstract] Unrecognized selection shape type");
    6868            }
    6969            break;
  • source/graphics/ObjectBase.cpp

    diff --git a/source/graphics/ObjectBase.cpp b/source/graphics/ObjectBase.cpp
    index f55ff9a..c32e285 100644
    a b bool CObjectBase::Load(const VfsPath& pathname)  
    9090
    9191    if (root.GetNodeName() != el_actor)
    9292    {
    93         LOGERROR(L"Invalid actor format (unrecognised root element '%hs')", XeroFile.GetElementString(root.GetNodeName()).c_str());
     93        LOGERROR("Invalid actor format (unrecognised root element '%s')", XeroFile.GetElementString(root.GetNodeName()).c_str());
    9494        return false;
    9595    }
    9696
    bool CObjectBase::Load(const VfsPath& pathname)  
    266266
    267267            if (currentGroup->size() == 0)
    268268            {
    269                 LOGERROR(L"Actor group has zero variants ('%ls')", pathname.string().c_str());
     269                LOGERROR("Actor group has zero variants ('%s')", pathname.string8());
    270270            }
    271271
    272272            ++currentGroup;
  • source/graphics/ObjectEntry.cpp

    diff --git a/source/graphics/ObjectEntry.cpp b/source/graphics/ObjectEntry.cpp
    index 16b4e48..fcd5113 100644
    a b bool CObjectEntry::BuildVariation(const std::vector<std::set<CStr> >& selections  
    7373        str << variation.color;
    7474        int r, g, b;
    7575        if (! (str >> r >> g >> b)) // Any trailing data is ignored
    76             LOGERROR(L"Actor '%ls' has invalid RGB colour '%hs'", m_Base->m_ShortName.c_str(), variation.color.c_str());
     76            LOGERROR("Actor '%s' has invalid RGB colour '%s'", utf8_from_wstring(m_Base->m_ShortName), variation.color);
    7777        else
    7878            m_Color = CColor(r/255.0f, g/255.0f, b/255.0f, 1.0f);
    7979    }
    bool CObjectEntry::BuildVariation(const std::vector<std::set<CStr> >& selections  
    119119    CModelDefPtr modeldef (objectManager.GetMeshManager().GetMesh(m_ModelName));
    120120    if (!modeldef)
    121121    {
    122         LOGERROR(L"CObjectEntry::BuildVariation(): Model %ls failed to load", m_ModelName.string().c_str());
     122        LOGERROR("CObjectEntry::BuildVariation(): Model %s failed to load", m_ModelName.string8());
    123123        return false;
    124124    }
    125125
    bool CObjectEntry::BuildVariation(const std::vector<std::set<CStr> >& selections  
    133133   
    134134    if (m_Samplers.size() == 0)
    135135    {
    136         LOGERROR(L"Actor '%ls' has no textures.", m_Base->m_ShortName.c_str());
     136        LOGERROR("Actor '%s' has no textures.", utf8_from_wstring(m_Base->m_ShortName));
    137137    }
    138138   
    139139    std::vector<CObjectBase::Samp>::iterator samp;
    bool CObjectEntry::BuildVariation(const std::vector<std::set<CStr> >& selections  
    190190    {
    191191        // start up idling
    192192        if (!model->SetAnimation(GetRandomAnimation("idle")))
    193             LOGERROR(L"Failed to set idle animation in model \"%ls\"", m_ModelName.string().c_str());
     193            LOGERROR("Failed to set idle animation in model \"%s\"", m_ModelName.string8());
    194194    }
    195195
    196196    // build props - TODO, RC - need to fix up bounds here
    bool CObjectEntry::BuildVariation(const std::vector<std::set<CStr> >& selections  
    209209        CObjectEntry* oe = objectManager.FindObjectVariation(prop.m_ModelName.c_str(), selections);
    210210        if (!oe)
    211211        {
    212             LOGERROR(L"Failed to build prop model \"%ls\" on actor \"%ls\"", prop.m_ModelName.c_str(), m_Base->m_ShortName.c_str());
     212            LOGERROR("Failed to build prop model \"%s\" on actor \"%s\"", utf8_from_wstring(prop.m_ModelName), utf8_from_wstring(m_Base->m_ShortName));
    213213            continue;
    214214        }
    215215
    bool CObjectEntry::BuildVariation(const std::vector<std::set<CStr> >& selections  
    240240                propmodel->ToCModel()->SetAnimation(oe->GetRandomAnimation("idle"));
    241241        }
    242242        else
    243             LOGERROR(L"Failed to find matching prop point called \"%hs\" in model \"%ls\" for actor \"%ls\"", ppn.c_str(), m_ModelName.string().c_str(), m_Base->m_ShortName.c_str());
     243            LOGERROR("Failed to find matching prop point called \"%s\" in model \"%s\" for actor \"%s\"", ppn, m_ModelName.string8(), utf8_from_wstring(m_Base->m_ShortName));
    244244    }
    245245
    246246    // setup flags
  • source/graphics/ObjectManager.cpp

    diff --git a/source/graphics/ObjectManager.cpp b/source/graphics/ObjectManager.cpp
    index b8bd6b8..9d23072 100644
    a b CObjectBase* CObjectManager::FindObjectBase(const CStrW& objectname)  
    9696    else
    9797        delete obj;
    9898
    99     LOGERROR(L"CObjectManager::FindObjectBase(): Cannot find object '%ls'", objectname.c_str());
     99    LOGERROR("CObjectManager::FindObjectBase(): Cannot find object '%s'", utf8_from_wstring(objectname));
    100100
    101101    return 0;
    102102}
  • source/graphics/ParticleEmitterType.cpp

    diff --git a/source/graphics/ParticleEmitterType.cpp b/source/graphics/ParticleEmitterType.cpp
    index 657feed..46cc663 100644
    a b int CParticleEmitterType::GetVariableID(const std::string& name)  
    329329    if (name == "color.r")          return VAR_COLOR_R;
    330330    if (name == "color.g")          return VAR_COLOR_G;
    331331    if (name == "color.b")          return VAR_COLOR_B;
    332     LOGWARNING(L"Particle sets unknown variable '%hs'", name.c_str());
     332    LOGWARNING("Particle sets unknown variable '%s'", name.c_str());
    333333    return -1;
    334334}
    335335
  • source/graphics/ShaderManager.cpp

    diff --git a/source/graphics/ShaderManager.cpp b/source/graphics/ShaderManager.cpp
    index 929123c..a65071d 100644
    a b CShaderManager::CShaderManager()  
    4949        TIMER_ACCRUE(tc_ShaderValidation);
    5050        CVFSFile grammar;
    5151        if (grammar.Load(g_VFS, L"shaders/program.rng") != PSRETURN_OK)
    52             LOGERROR(L"Failed to read grammar shaders/program.rng");
     52            LOGERROR("Failed to read grammar shaders/program.rng");
    5353        else
    5454        {
    5555            if (!m_Validator.LoadGrammar(grammar.GetAsString()))
    56                 LOGERROR(L"Failed to load grammar shaders/program.rng");
     56                LOGERROR("Failed to load grammar shaders/program.rng");
    5757        }
    5858    }
    5959#endif
    CShaderProgramPtr CShaderManager::LoadProgram(const char* name, const CShaderDef  
    7777    CShaderProgramPtr program;
    7878    if (!NewProgram(name, defines, program))
    7979    {
    80         LOGERROR(L"Failed to load shader '%hs'", name);
     80        LOGERROR("Failed to load shader '%s'", name);
    8181        program = CShaderProgramPtr();
    8282    }
    8383
    CShaderTechniquePtr CShaderManager::LoadEffect(CStrIntern name, const CShaderDef  
    378378    CShaderTechniquePtr tech(new CShaderTechnique());
    379379    if (!NewEffect(name.c_str(), defines, tech))
    380380    {
    381         LOGERROR(L"Failed to load effect '%hs'", name.c_str());
     381        LOGERROR("Failed to load effect '%s'", name.c_str());
    382382        tech = CShaderTechniquePtr();
    383383    }
    384384
  • source/graphics/ShaderProgram.cpp

    diff --git a/source/graphics/ShaderProgram.cpp b/source/graphics/ShaderProgram.cpp
    index 817ff41..55ffe5a 100644
    a b public:  
    7171            glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
    7272            int errLine = std::count(code.begin(), code.begin() + std::min((int)code.length(), errPos + 1), '\n') + 1;
    7373            char* errStr = (char*)glGetString(GL_PROGRAM_ERROR_STRING_ARB);
    74             LOGERROR(L"Failed to compile %hs program '%ls' (line %d):\n%hs", targetName, file.string().c_str(), errLine, errStr);
     74            LOGERROR("Failed to compile %s program '%s' (line %d):\n%s", targetName, file.string8(), errLine, errStr);
    7575            return false;
    7676        }
    7777
    public:  
    310310            pglGetShaderInfoLog(shader, length, NULL, infolog);
    311311
    312312            if (ok)
    313                 LOGMESSAGE(L"Info when compiling shader '%ls':\n%hs", file.string().c_str(), infolog);
     313                LOGMESSAGE("Info when compiling shader '%s':\n%s", file.string8(), infolog);
    314314            else
    315                 LOGERROR(L"Failed to compile shader '%ls':\n%hs", file.string().c_str(), infolog);
     315                LOGERROR("Failed to compile shader '%s':\n%s", file.string8(), infolog);
    316316
    317317            delete[] infolog;
    318318        }
    public:  
    357357            pglGetProgramInfoLog(m_Program, length, NULL, infolog);
    358358
    359359            if (ok)
    360                 LOGMESSAGE(L"Info when linking program '%ls'+'%ls':\n%hs", m_VertexFile.string().c_str(), m_FragmentFile.string().c_str(), infolog);
     360                LOGMESSAGE("Info when linking program '%s'+'%s':\n%s", m_VertexFile.string8(), m_FragmentFile.string8(), infolog);
    361361            else
    362                 LOGERROR(L"Failed to link program '%ls'+'%ls':\n%hs", m_VertexFile.string().c_str(), m_FragmentFile.string().c_str(), infolog);
     362                LOGERROR("Failed to link program '%s'+'%s':\n%s", m_VertexFile.string8(), m_FragmentFile.string8(), infolog);
    363363           
    364364            delete[] infolog;
    365365        }
    public:  
    561561            else if (id.second == GL_FLOAT_VEC4)
    562562                pglUniform4fARB(id.first, v0, v1, v2, v3);
    563563            else
    564                 LOGERROR(L"CShaderProgramGLSL::Uniform(): Invalid uniform type (expected float, vec2, vec3, vec4)");
     564                LOGERROR("CShaderProgramGLSL::Uniform(): Invalid uniform type (expected float, vec2, vec3, vec4)");
    565565        }
    566566    }
    567567
    public:  
    572572            if (id.second == GL_FLOAT_MAT4)
    573573                pglUniformMatrix4fvARB(id.first, 1, GL_FALSE, &v._11);
    574574            else
    575                 LOGERROR(L"CShaderProgramGLSL::Uniform(): Invalid uniform type (expected mat4)");
     575                LOGERROR("CShaderProgramGLSL::Uniform(): Invalid uniform type (expected mat4)");
    576576        }
    577577    }
    578578
    public:  
    583583            if (id.second == GL_FLOAT_MAT4)
    584584                pglUniformMatrix4fvARB(id.first, count, GL_FALSE, &v->_11);
    585585            else
    586                 LOGERROR(L"CShaderProgramGLSL::Uniform(): Invalid uniform type (expected mat4)");
     586                LOGERROR("CShaderProgramGLSL::Uniform(): Invalid uniform type (expected mat4)");
    587587        }
    588588    }
    589589
    CShaderProgram::CShaderProgram(int streamflags)  
    663663    const std::map<CStrIntern, int>& UNUSED(vertexIndexes), const std::map<CStrIntern, frag_index_pair_t>& UNUSED(fragmentIndexes),
    664664    int UNUSED(streamflags))
    665665{
    666     LOGERROR(L"CShaderProgram::ConstructARB: '%ls'+'%ls': ARB shaders not supported on this device",
     666    LOGERROR("CShaderProgram::ConstructARB: '%s'+'%s': ARB shaders not supported on this device",
    667667        vertexFile.string().c_str(), fragmentFile.string().c_str());
    668668    return NULL;
    669669}
  • source/graphics/ShaderProgramFFP.cpp

    diff --git a/source/graphics/ShaderProgramFFP.cpp b/source/graphics/ShaderProgramFFP.cpp
    index a3ec42b..f46e629 100644
    a b public:  
    11591159    if (id == "model_solid_tex")
    11601160        return new CShaderProgramFFP_ModelSolidTex(defines);
    11611161
    1162     LOGERROR(L"CShaderProgram::ConstructFFP: '%hs': Invalid id", id.c_str());
     1162    LOGERROR("CShaderProgram::ConstructFFP: '%s': Invalid id", id.c_str());
    11631163    debug_warn(L"CShaderProgram::ConstructFFP: Invalid id");
    11641164    return NULL;
    11651165}
  • source/graphics/SkeletonAnimManager.cpp

    diff --git a/source/graphics/SkeletonAnimManager.cpp b/source/graphics/SkeletonAnimManager.cpp
    index 80bb336..fa4f121 100644
    a b CSkeletonAnimDef* CSkeletonAnimManager::GetAnimation(const VfsPath& pathname)  
    6565
    6666    if (psaFilename.empty())
    6767    {
    68         LOGERROR(L"Could not load animation '%ls'", pathname.string().c_str());
     68        LOGERROR("Could not load animation '%s'", pathname.string8());
    6969        def = NULL;
    7070    }
    7171    else
    CSkeletonAnimDef* CSkeletonAnimManager::GetAnimation(const VfsPath& pathname)  
    7676        }
    7777        catch (PSERROR_File&)
    7878        {
    79             LOGERROR(L"Could not load animation '%ls'", psaFilename.string().c_str());
     79            LOGERROR("Could not load animation '%s'", psaFilename.string8());
    8080        }
    8181    }
    8282
    8383    if (def)
    84         LOGMESSAGE(L"CSkeletonAnimManager::GetAnimation(%ls): Loaded successfully", pathname.string().c_str());
     84        LOGMESSAGE("CSkeletonAnimManager::GetAnimation(%s): Loaded successfully", pathname.string8());
    8585    else
    86         LOGERROR(L"CSkeletonAnimManager::GetAnimation(%ls): Failed loading, marked file as bad", pathname.string().c_str());
     86        LOGERROR("CSkeletonAnimManager::GetAnimation(%s): Failed loading, marked file as bad", pathname.string8());
    8787
    8888    // Add to map
    8989    m_Animations[name] = def; // NULL if failed to load - we won't try loading it again
  • source/graphics/TerrainProperties.cpp

    diff --git a/source/graphics/TerrainProperties.cpp b/source/graphics/TerrainProperties.cpp
    index e4bb788..3be85b7 100644
    a b CTerrainPropertiesPtr CTerrainProperties::FromXML(const CTerrainPropertiesPtr& p  
    5555    // Check that we've got the right kind of xml document
    5656    if (rootName != "Terrains")
    5757    {
    58         LOGERROR(
    59             L"TerrainProperties: Loading %ls: Root node is not terrains (found \"%hs\")",
    60             pathname.string().c_str(),
    61             rootName.c_str());
     58        LOGERROR("TerrainProperties: Loading %s: Root node is not terrains (found \"%s\")",
     59            pathname.string8(),
     60            rootName);
    6261        return CTerrainPropertiesPtr();
    6362    }
    6463   
    CTerrainPropertiesPtr CTerrainProperties::FromXML(const CTerrainPropertiesPtr& p  
    8079        }
    8180        else
    8281        {
    83             LOGWARNING(
    84                 L"TerrainProperties: Loading %ls: Unexpected node %hs\n",
    85                 pathname.string().c_str(),
    86                 XeroFile.GetElementString(child.GetNodeName()).c_str());
     82            LOGWARNING("TerrainProperties: Loading %s: Unexpected node %s\n",
     83                pathname.string8(),
     84                XeroFile.GetElementString(child.GetNodeName()));
    8785            // Keep reading - typos shouldn't be showstoppers
    8886        }
    8987    }
  • source/graphics/TerrainTextureEntry.cpp

    diff --git a/source/graphics/TerrainTextureEntry.cpp b/source/graphics/TerrainTextureEntry.cpp
    index 7429dce..756fb2d 100644
    a b CTerrainTextureEntry::CTerrainTextureEntry(CTerrainPropertiesPtr properties, con  
    4747    CXeromyces XeroFile;
    4848    if (XeroFile.Load(g_VFS, path) != PSRETURN_OK)
    4949    {
    50         LOGERROR(L"Terrain xml not found (%hs)", path.string().c_str());
     50        LOGERROR("Terrain xml not found (%s)", path.string8());
    5151        return;
    5252    }
    5353
    CTerrainTextureEntry::CTerrainTextureEntry(CTerrainPropertiesPtr properties, con  
    7070
    7171    if (root.GetNodeName() != el_terrain)
    7272    {
    73         LOGERROR(L"Invalid terrain format (unrecognised root element '%hs')", XeroFile.GetElementString(root.GetNodeName()).c_str());
     73        LOGERROR("Invalid terrain format (unrecognised root element '%s')", XeroFile.GetElementString(root.GetNodeName()).c_str());
    7474        return;
    7575    }
    7676   
    void CTerrainTextureEntry::LoadAlphaMaps(VfsPath &amtype)  
    253253        if (textures[i] < 0)
    254254        {
    255255            g_TexMan.m_TerrainAlphas.erase(it);
    256             LOGERROR((L"Failed to load alphamap: " + amtype.string()).c_str());
     256            LOGERROR("Failed to load alphamap: %s", amtype.string8());
    257257           
    258258            VfsPath standard("standard");
    259259            if (path != standard)
    void CTerrainTextureEntry::LoadAlphaMaps(VfsPath &amtype)  
    362362    result.m_hCompositeAlphaMap = hCompositeAlphaMap;
    363363   
    364364    m_TerrainAlpha = it;
    365 }
    366  No newline at end of file
     365}
  • source/graphics/TerrainTextureManager.cpp

    diff --git a/source/graphics/TerrainTextureManager.cpp b/source/graphics/TerrainTextureManager.cpp
    index 5913c10..e7e3391 100644
    a b CTerrainTextureEntry* CTerrainTextureManager::FindTexture(const CStr& tag_)  
    8989            return m_TextureEntries[i];
    9090    }
    9191
    92     LOGWARNING(L"CTerrainTextureManager: Couldn't find terrain %hs", tag.c_str());
     92    LOGWARNING("CTerrainTextureManager: Couldn't find terrain %s", tag.c_str());
    9393    return 0;
    9494}
    9595
    void CTerrainTextureManager::LoadTextures(const CTerrainPropertiesPtr& props, co  
    141141
    142142void CTerrainTextureManager::RecurseDirectory(const CTerrainPropertiesPtr& parentProps, const VfsPath& path)
    143143{
    144     //LOGMESSAGE(L"CTextureManager::RecurseDirectory(%ls)", path.string().c_str());
     144    //LOGMESSAGE("CTextureManager::RecurseDirectory(%s)", path.string8());
    145145
    146146    CTerrainPropertiesPtr props;
    147147
    void CTerrainTextureManager::RecurseDirectory(const CTerrainPropertiesPtr& paren  
    153153    // No terrains.xml, or read failures -> use parent props (i.e.
    154154    if (!props)
    155155    {
    156         LOGMESSAGE(L"CTerrainTextureManager::RecurseDirectory(%ls): no terrains.xml (or errors while loading) - using parent properties", path.string().c_str());
     156        LOGMESSAGE("CTerrainTextureManager::RecurseDirectory(%s): no terrains.xml (or errors while loading) - using parent properties", path.string8());
    157157        props = parentProps;
    158158    }
    159159
  • source/graphics/TextRenderer.cpp

    diff --git a/source/graphics/TextRenderer.cpp b/source/graphics/TextRenderer.cpp
    index 3149ed6..ae5ac69 100644
    a b void CTextRenderer::Put(float x, float y, const wchar_t* buf)  
    144144    PutString(x, y, new std::wstring(buf), true);
    145145}
    146146
     147void CTextRenderer::Put(float x, float y, const char* buf)
     148{
     149    if (buf[0] == 0)
     150        return; // empty string; don't bother storing
     151
     152    PutString(x, y, new std::wstring(wstring_from_utf8(buf)), true);
     153}
     154
    147155void CTextRenderer::Put(float x, float y, const std::wstring* buf)
    148156{
    149157    if (buf->empty())
  • source/graphics/TextRenderer.h

    diff --git a/source/graphics/TextRenderer.h b/source/graphics/TextRenderer.h
    index ac4d3b1..0c096f9 100644
    a b public:  
    9191    /**
    9292     * Print text at (x,y) under the current transform.
    9393     * Does not alter the current transform.
     94     * @p buf must be a UTF-8 string.
     95     */
     96    void Put(float x, float y, const char* buf);
     97
     98    /**
     99     * Print text at (x,y) under the current transform.
     100     * Does not alter the current transform.
    94101     * @p buf must remain valid until Render() is called.
    95102     * (This should be used to minimise memory copies when possible.)
    96103     */
  • source/graphics/TextureConverter.cpp

    diff --git a/source/graphics/TextureConverter.cpp b/source/graphics/TextureConverter.cpp
    index aadca03..3f9c7cb 100644
    a b CTextureConverter::SettingsFile* CTextureConverter::LoadSettings(const VfsPath&  
    120120
    121121    if (root.GetNodeName() != el_textures)
    122122    {
    123         LOGERROR(L"Invalid texture settings file \"%ls\" (unrecognised root element)", path.string().c_str());
     123        LOGERROR("Invalid texture settings file \"%s\" (unrecognised root element)", path.string8());
    124124        return NULL;
    125125    }
    126126
    CTextureConverter::SettingsFile* CTextureConverter::LoadSettings(const VfsPath&  
    152152                    else if (v == "alpha")
    153153                        p.settings.format = FMT_ALPHA;
    154154                    else
    155                         LOGERROR(L"Invalid attribute value <file format='%hs'>", v.c_str());
     155                        LOGERROR("Invalid attribute value <file format='%s'>", v.c_str());
    156156                }
    157157                else if (attr.Name == at_mipmap)
    158158                {
    CTextureConverter::SettingsFile* CTextureConverter::LoadSettings(const VfsPath&  
    162162                    else if (v == "false")
    163163                        p.settings.mipmap = MIP_FALSE;
    164164                    else
    165                         LOGERROR(L"Invalid attribute value <file mipmap='%hs'>", v.c_str());
     165                        LOGERROR("Invalid attribute value <file mipmap='%s'>", v.c_str());
    166166                }
    167167                else if (attr.Name == at_normal)
    168168                {
    CTextureConverter::SettingsFile* CTextureConverter::LoadSettings(const VfsPath&  
    172172                    else if (v == "false")
    173173                        p.settings.normal = NORMAL_FALSE;
    174174                    else
    175                         LOGERROR(L"Invalid attribute value <file normal='%hs'>", v.c_str());
     175                        LOGERROR("Invalid attribute value <file normal='%s'>", v.c_str());
    176176                }
    177177                else if (attr.Name == at_alpha)
    178178                {
    CTextureConverter::SettingsFile* CTextureConverter::LoadSettings(const VfsPath&  
    184184                    else if (v == "transparency")
    185185                        p.settings.alpha = ALPHA_TRANSPARENCY;
    186186                    else
    187                         LOGERROR(L"Invalid attribute value <file alpha='%hs'>", v.c_str());
     187                        LOGERROR("Invalid attribute value <file alpha='%s'>", v.c_str());
    188188                }
    189189                else if (attr.Name == at_filter)
    190190                {
    CTextureConverter::SettingsFile* CTextureConverter::LoadSettings(const VfsPath&  
    196196                    else if (v == "kaiser")
    197197                        p.settings.filter = FILTER_KAISER;
    198198                    else
    199                         LOGERROR(L"Invalid attribute value <file filter='%hs'>", v.c_str());
     199                        LOGERROR("Invalid attribute value <file filter='%s'>", v.c_str());
    200200                }
    201201                else if (attr.Name == at_kaiserwidth)
    202202                {
    CTextureConverter::SettingsFile* CTextureConverter::LoadSettings(const VfsPath&  
    212212                }
    213213                else
    214214                {
    215                     LOGERROR(L"Invalid attribute name <file %hs='...'>", XeroFile.GetAttributeString(attr.Name).c_str());
     215                    LOGERROR("Invalid attribute name <file %s='...'>", XeroFile.GetAttributeString(attr.Name).c_str());
    216216                }
    217217            }
    218218
    bool CTextureConverter::ConvertTexture(const CTexturePtr& texture, const VfsPath  
    326326    size_t fileSize;
    327327    if (m_VFS->LoadFile(src, file, fileSize) < 0)
    328328    {
    329         LOGERROR(L"Failed to load texture \"%ls\"", src.string().c_str());
     329        LOGERROR("Failed to load texture \"%s\"", src.string8());
    330330        return false;
    331331    }
    332332
    333333    Tex tex;
    334334    if (tex.decode(file, fileSize) < 0)
    335335    {
    336         LOGERROR(L"Failed to decode texture \"%ls\"", src.string().c_str());
     336        LOGERROR("Failed to decode texture \"%s\"", src.string8());
    337337        return false;
    338338    }
    339339
    bool CTextureConverter::ConvertTexture(const CTexturePtr& texture, const VfsPath  
    345345        // Convert to uncompressed 8-bit with no mipmaps
    346346        if (tex.transform_to((tex.m_Flags | TEX_GREY) & ~(TEX_DXT | TEX_MIPMAPS | TEX_ALPHA)) < 0)
    347347        {
    348             LOGERROR(L"Failed to transform texture \"%ls\"", src.string().c_str());
     348            LOGERROR("Failed to transform texture \"%s\"", src.string8());
    349349            return false;
    350350        }
    351351    }
    bool CTextureConverter::ConvertTexture(const CTexturePtr& texture, const VfsPath  
    356356        // (plain_transform doesn't know how to construct the alpha channel)
    357357        if (tex.m_Flags & TEX_GREY)
    358358        {
    359             LOGERROR(L"Failed to convert grayscale texture \"%ls\" - only RGB textures are currently supported", src.string().c_str());
     359            LOGERROR("Failed to convert grayscale texture \"%s\" - only RGB textures are currently supported", src.string8());
    360360            return false;
    361361        }
    362362
    363363        // Convert to uncompressed BGRA with no mipmaps
    364364        if (tex.transform_to((tex.m_Flags | TEX_BGR | TEX_ALPHA) & ~(TEX_DXT | TEX_MIPMAPS)) < 0)
    365365        {
    366             LOGERROR(L"Failed to transform texture \"%ls\"", src.string().c_str());
     366            LOGERROR("Failed to transform texture \"%s\"", src.string8());
    367367            return false;
    368368        }
    369369    }
    bool CTextureConverter::ConvertTexture(const CTexturePtr& texture, const VfsPath  
    482482    return true;
    483483
    484484#else
    485     LOGERROR(L"Failed to convert texture \"%ls\" (NVTT not available)", src.string().c_str());
     485    LOGERROR("Failed to convert texture \"%s\" (NVTT not available)", src.string8());
    486486    return false;
    487487#endif
    488488}
  • source/graphics/TextureManager.cpp

    diff --git a/source/graphics/TextureManager.cpp b/source/graphics/TextureManager.cpp
    index bfccc8b..2adf7c9 100644
    a b public:  
    178178        Handle h = ogl_tex_load(m_VFS, path, RES_UNIQUE);
    179179        if (h <= 0)
    180180        {
    181             LOGERROR(L"Texture failed to load; \"%ls\"", texture->m_Properties.m_Path.string().c_str());
     181            LOGERROR("Texture failed to load; \"%s\"", texture->m_Properties.m_Path.string8());
    182182
    183183            // Replace with error texture to make it obvious
    184184            texture->SetHandle(m_ErrorHandle);
    public:  
    218218        // Upload to GL
    219219        if (!m_DisableGL && ogl_tex_upload(h, texture->m_Properties.m_Format) < 0)
    220220        {
    221             LOGERROR(L"Texture failed to upload: \"%ls\"", texture->m_Properties.m_Path.string().c_str());
     221            LOGERROR("Texture failed to upload: \"%s\"", texture->m_Properties.m_Path.string8());
    222222
    223223            ogl_tex_free(h);
    224224
    public:  
    277277
    278278            // No source file or archive cache was found, so we can't load the
    279279            // real texture at all - return the error texture instead
    280             LOGERROR(L"CCacheLoader failed to find archived or source file for: \"%ls\"", texture->m_Properties.m_Path.string().c_str());
     280            LOGERROR("CCacheLoader failed to find archived or source file for: \"%s\"", texture->m_Properties.m_Path.string8());
    281281            texture->SetHandle(m_ErrorHandle);
    282282            return true;
    283283        }
    public:  
    299299        PrepareCacheKey(texture, hash, version);
    300300        VfsPath looseCachePath = m_CacheLoader.LooseCachePath(sourcePath, hash, version);
    301301
    302 //      LOGWARNING(L"Converting texture \"%ls\"", srcPath.c_str());
     302//      LOGWARNING("Converting texture \"%s\"", srcPath.c_str());
    303303
    304304        CTextureConverter::Settings settings = GetConverterSettings(texture);
    305305
    public:  
    345345                }
    346346                else
    347347                {
    348                     LOGERROR(L"Texture failed to convert: \"%ls\"", texture->m_Properties.m_Path.string().c_str());
     348                    LOGERROR("Texture failed to convert: \"%s\"", texture->m_Properties.m_Path.string8());
    349349                    texture->SetHandle(m_ErrorHandle);
    350350                }
    351351                texture->m_State = CTexture::LOADED;
  • source/graphics/scripting/JSInterface_GameView.cpp

    diff --git a/source/graphics/scripting/JSInterface_GameView.cpp b/source/graphics/scripting/JSInterface_GameView.cpp
    index b5c0b13..22e1c7f 100644
    a b bool JSI_GameView::Get##NAME##Enabled(ScriptInterface::CxPrivate* UNUSED(pCxPriv  
    2828{ \
    2929    if (!g_Game || !g_Game->GetView()) \
    3030    { \
    31         LOGERROR(L"Trying to get a setting from GameView when it's not initialized!"); \
     31        LOGERROR("Trying to get a setting from GameView when it's not initialized!"); \
    3232        return false; \
    3333    } \
    3434    return g_Game->GetView()->Get##NAME##Enabled(); \
    void JSI_GameView::Set##NAME##Enabled(ScriptInterface::CxPrivate* UNUSED(pCxPriv  
    3838{ \
    3939    if (!g_Game || !g_Game->GetView()) \
    4040    { \
    41         LOGERROR(L"Trying to set a setting of GameView when it's not initialized!"); \
     41        LOGERROR("Trying to set a setting of GameView when it's not initialized!"); \
    4242        return; \
    4343    } \
    4444    g_Game->GetView()->Set##NAME##Enabled(Enabled); \
  • source/graphics/tests/test_MeshManager.h

    diff --git a/source/graphics/tests/test_MeshManager.h b/source/graphics/tests/test_MeshManager.h
    index 4e59ba1..a35d3b3 100644
    a b public:  
    190190
    191191        CModelDefPtr modeldef = meshManager->GetMesh(testDAE);
    192192        TS_ASSERT(! modeldef);
    193         TS_ASSERT_WSTR_CONTAINS(logger.GetOutput(), L"parser error");
     193        TS_ASSERT_STR_CONTAINS(logger.GetOutput(), "parser error");
    194194    }
    195195
    196196    void test_invalid_dae()
    public:  
    205205
    206206        CModelDefPtr modeldef = meshManager->GetMesh(testDAE);
    207207        TS_ASSERT(! modeldef);
    208         TS_ASSERT_WSTR_CONTAINS(logger.GetOutput(), L"parser error");
     208        TS_ASSERT_STR_CONTAINS(logger.GetOutput(), "parser error");
    209209    }
    210210
    211211    void test_load_nonexistent_pmd()
  • source/gui/CGUI.cpp

    diff --git a/source/gui/CGUI.cpp b/source/gui/CGUI.cpp
    index 51e33f8..06e86d8 100644
    a b void CGUI::Draw()  
    380380    }
    381381    catch (PSERROR_GUI& e)
    382382    {
    383         LOGERROR(L"GUI draw error: %hs", e.what());
     383        LOGERROR("GUI draw error: %s", e.what());
    384384    }
    385385}
    386386
    void CGUI::LoadXmlFile(const VfsPath& Filename, boost::unordered_set<VfsPath>& P  
    969969    }
    970970    catch (PSERROR_GUI& e)
    971971    {
    972         LOGERROR(L"Errors loading GUI file %ls (%u)", Filename.string().c_str(), e.getCode());
     972        LOGERROR("Errors loading GUI file %s (%u)", Filename.string8(), e.getCode());
    973973        return;
    974974    }
    975975}
    void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec  
    10911091    if (!object)
    10921092    {
    10931093        // Report error that object was unsuccessfully loaded
    1094         LOGERROR(L"GUI: Unrecognized object type \"%hs\"", type.c_str());
     1094        LOGERROR("GUI: Unrecognized object type \"%s\"", type.c_str());
    10951095        return;
    10961096    }
    10971097
    void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec  
    11331133    {
    11341134        // additional check
    11351135        if (m_Styles.count(argStyle) == 0)
    1136             LOGERROR(L"GUI: Trying to use style '%hs' that doesn't exist.", argStyle.c_str());
     1136            LOGERROR("GUI: Trying to use style '%s' that doesn't exist.", argStyle.c_str());
    11371137        else
    11381138            object->LoadStyle(*this, argStyle);
    11391139    }
    void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec  
    11851185        // Try setting the value
    11861186        if (object->SetSetting(pFile->GetAttributeString(attr.Name), attr.Value.FromUTF8(), true) != PSRETURN_OK)
    11871187        {
    1188             LOGERROR(L"GUI: (object: %hs) Can't set \"%hs\" to \"%ls\"", object->GetPresentableName().c_str(), pFile->GetAttributeString(attr.Name).c_str(), attr.Value.FromUTF8().c_str());
     1188            LOGERROR("GUI: (object: %s) Can't set \"%s\" to \"%s\"", object->GetPresentableName(), pFile->GetAttributeString(attr.Name), attr.Value);
    11891189
    11901190            // This is not a fatal error
    11911191        }
    void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec  
    12481248                CVFSFile scriptfile;
    12491249                if (scriptfile.Load(g_VFS, filename) != PSRETURN_OK)
    12501250                {
    1251                     LOGERROR(L"Error opening GUI script action file '%ls'", filename.c_str());
     1251                    LOGERROR("Error opening GUI script action file '%s'", utf8_from_wstring(filename));
    12521252                    throw PSERROR_GUI_JSOpenFailed();
    12531253                }
    12541254
    void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec  
    12931293            CStr attributeName(child.GetAttributes().GetNamedItem(attr_id)); // Read the attribute name.
    12941294            if (attributeName.empty())
    12951295            {
    1296                 LOGERROR(L"GUI: ‘translatableAttribute’ XML element with empty ‘id’ XML attribute found. (object: %hs)", object->GetPresentableName().c_str());
     1296                LOGERROR("GUI: ‘translatableAttribute’ XML element with empty ‘id’ XML attribute found. (object: %s)", object->GetPresentableName().c_str());
    12971297                continue;
    12981298            }
    12991299
    void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec  
    13201320            CStr attributeName(child.GetAttributes().GetNamedItem(attr_id)); // Read the attribute name.
    13211321            if (attributeName.empty())
    13221322            {
    1323                 LOGERROR(L"GUI: ‘attribute’ XML element with empty ‘id’ XML attribute found. (object: %hs)", object->GetPresentableName().c_str());
     1323                LOGERROR("GUI: ‘attribute’ XML element with empty ‘id’ XML attribute found. (object: %s)", object->GetPresentableName().c_str());
    13241324                continue;
    13251325            }
    13261326
    void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec  
    13481348            if (!filename.empty())
    13491349            {
    13501350                if (!directory.empty())
    1351                     LOGWARNING(L"GUI: Include element found with file name (%ls) and directory name (%ls). Only the file will be processed.", filename.c_str(), directory.c_str());
     1351                    LOGWARNING("GUI: Include element found with file name (%s) and directory name (%s). Only the file will be processed.", utf8_from_wstring(filename), utf8_from_wstring(directory));
    13521352
    13531353                Paths.insert(filename);
    13541354
    13551355                CXeromyces XeroIncluded;
    13561356                if (XeroIncluded.Load(g_VFS, filename) != PSRETURN_OK)
    13571357                {
    1358                     LOGERROR(L"GUI: Error reading included XML: '%ls'", filename.c_str());
     1358                    LOGERROR("GUI: Error reading included XML: '%s'", utf8_from_wstring(filename));
    13591359                    continue;
    13601360                }
    13611361
    13621362                XMBElement node = XeroIncluded.GetRoot();
    13631363                if (node.GetNodeName() != XeroIncluded.GetElementID("object"))
    13641364                {
    1365                     LOGERROR(L"GUI: Error reading included XML: '%ls', root element must have be of type 'object'.", filename.c_str());
     1365                    LOGERROR("GUI: Error reading included XML: '%s', root element must have be of type 'object'.", utf8_from_wstring(filename));
    13661366                    continue;
    13671367                }
    13681368                Xeromyces_ReadObject(node, &XeroIncluded, object, NameSubst, Paths, nesting_depth+1);
    void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec  
    13791379                    CXeromyces XeroIncluded;
    13801380                    if (XeroIncluded.Load(g_VFS, *it) != PSRETURN_OK)
    13811381                    {
    1382                         LOGERROR(L"GUI: Error reading included XML: '%ls'", (*it).string().c_str());
     1382                        LOGERROR("GUI: Error reading included XML: '%s'", (*it).string8());
    13831383                        continue;
    13841384                    }
    13851385
    13861386                    XMBElement node = XeroIncluded.GetRoot();
    13871387                    if (node.GetNodeName() != XeroIncluded.GetElementID("object"))
    13881388                    {
    1389                         LOGERROR(L"GUI: Error reading included XML: '%ls', root element must have be of type 'object'.", (*it).string().c_str());
     1389                        LOGERROR("GUI: Error reading included XML: '%s', root element must have be of type 'object'.", (*it).string8());
    13901390                        continue;
    13911391                    }
    13921392                    Xeromyces_ReadObject(node, &XeroIncluded, object, NameSubst, Paths, nesting_depth+1);
    void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec  
    13941394
    13951395            }
    13961396            else
    1397                 LOGERROR(L"GUI: 'include' XML element must have valid 'file' or 'directory' attribute found. (object %hs)", object->GetPresentableName().c_str());
     1397                LOGERROR("GUI: 'include' XML element must have valid 'file' or 'directory' attribute found. (object %s)", object->GetPresentableName().c_str());
    13981398        }
    13991399        else
    14001400        {
    14011401            // Try making the object read the tag.
    14021402            if (!object->HandleAdditionalChildren(child, pFile))
    14031403            {
    1404                 LOGERROR(L"GUI: (object: %hs) Reading unknown children for its type", object->GetPresentableName().c_str());
     1404                LOGERROR("GUI: (object: %s) Reading unknown children for its type", object->GetPresentableName().c_str());
    14051405            }
    14061406        }
    14071407    }
    void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec  
    14421442    }
    14431443    catch (PSERROR_GUI& e)
    14441444    {
    1445         LOGERROR(L"GUI error: %hs", e.what());
     1445        LOGERROR("GUI error: %s", e.what());
    14461446    }
    14471447}
    14481448
    void CGUI::Xeromyces_ReadScript(XMBElement Element, CXeromyces* pFile, boost::un  
    14911491        }
    14921492        catch (PSERROR_Scripting& e)
    14931493        {
    1494             LOGERROR(L"GUI: Error executing script %ls: %hs", file.c_str(), e.what());
     1494            LOGERROR("GUI: Error executing script %s: %s", utf8_from_wstring(file), e.what());
    14951495        }
    14961496    }
    14971497
    void CGUI::Xeromyces_ReadScript(XMBElement Element, CXeromyces* pFile, boost::un  
    15121512                }
    15131513                catch (PSERROR_Scripting& e)
    15141514                {
    1515                     LOGERROR(L"GUI: Error executing script %ls: %hs", (*it).string().c_str(), e.what());
     1515                    LOGERROR("GUI: Error executing script %s: %s", (*it).string8(), e.what());
    15161516                }
    15171517            }
    15181518        }
    void CGUI::Xeromyces_ReadScript(XMBElement Element, CXeromyces* pFile, boost::un  
    15271527    }
    15281528    catch (PSERROR_Scripting& e)
    15291529    {
    1530         LOGERROR(L"GUI: Error executing inline script: %hs", e.what());
     1530        LOGERROR("GUI: Error executing inline script: %s", e.what());
    15311531    }
    15321532}
    15331533
    void CGUI::Xeromyces_ReadSprite(XMBElement Element, CXeromyces* pFile)  
    15471547    name = Element.GetAttributes().GetNamedItem( pFile->GetAttributeID("name") );
    15481548
    15491549    if (m_Sprites.find(name) != m_Sprites.end())
    1550         LOGWARNING(L"GUI sprite name '%hs' used more than once; first definition will be discarded", name.c_str());
     1550        LOGWARNING("GUI sprite name '%s' used more than once; first definition will be discarded", name.c_str());
    15511551
    15521552    //
    15531553    //  Read Children (the images)
    void CGUI::Xeromyces_ReadSprite(XMBElement Element, CXeromyces* pFile)  
    15731573        {
    15741574            if (effects)
    15751575            {
    1576                 LOGERROR(L"GUI <sprite> must not have more than one <effect>");
     1576                LOGERROR("GUI <sprite> must not have more than one <effect>");
    15771577            }
    15781578            else
    15791579            {
    void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite  
    16361636        {
    16371637            CClientArea ca;
    16381638            if (!GUI<CClientArea>::ParseString(attr_value, ca))
    1639                 LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
     1639                LOGERROR("GUI: Error parsing '%s' (\"%s\")", attr_name, utf8_from_wstring(attr_value));
    16401640            else Image->m_Size = ca;
    16411641        }
    16421642        else
    void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite  
    16441644        {
    16451645            CClientArea ca;
    16461646            if (!GUI<CClientArea>::ParseString(attr_value, ca))
    1647                 LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
     1647                LOGERROR("GUI: Error parsing '%s' (\"%s\")", attr_name, utf8_from_wstring(attr_value));
    16481648            else Image->m_TextureSize = ca;
    16491649        }
    16501650        else
    void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite  
    16521652        {
    16531653            CRect rect;
    16541654            if (!GUI<CRect>::ParseString(attr_value, rect))
    1655                 LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
     1655                LOGERROR("GUI: Error parsing '%s' (\"%s\")", attr_name, utf8_from_wstring(attr_value));
    16561656            else Image->m_TexturePlacementInFile = rect;
    16571657        }
    16581658        else
    void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite  
    16601660        {
    16611661            CSize size;
    16621662            if (!GUI<CSize>::ParseString(attr_value, size))
    1663                 LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
     1663                LOGERROR("GUI: Error parsing '%s' (\"%s\")", attr_name, utf8_from_wstring(attr_value));
    16641664            else Image->m_CellSize = size;
    16651665        }
    16661666        else
    void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite  
    16681668        {
    16691669            float val;
    16701670            if (!GUI<float>::ParseString(attr_value, val))
    1671                 LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
     1671                LOGERROR("GUI: Error parsing '%s' (\"%s\")", attr_name, utf8_from_wstring(attr_value));
    16721672            else Image->m_FixedHAspectRatio = val;
    16731673        }
    16741674        else
    void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite  
    16761676        {
    16771677            bool b;
    16781678            if (!GUI<bool>::ParseString(attr_value, b))
    1679                 LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
     1679                LOGERROR("GUI: Error parsing '%s' (\"%s\")", attr_name, utf8_from_wstring(attr_value));
    16801680            else Image->m_RoundCoordinates = b;
    16811681        }
    16821682        else
    void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite  
    16891689            else if (attr_value == L"clamp_to_edge")
    16901690                Image->m_WrapMode = GL_CLAMP_TO_EDGE;
    16911691            else
    1692                 LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
     1692                LOGERROR("GUI: Error parsing '%s' (\"%s\")", attr_name, utf8_from_wstring(attr_value));
    16931693        }
    16941694        else
    16951695        if (attr_name == "z_level")
    16961696        {
    16971697            float z_level;
    16981698            if (!GUI<float>::ParseString(attr_value, z_level))
    1699                 LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
     1699                LOGERROR("GUI: Error parsing '%s' (\"%s\")", attr_name, utf8_from_wstring(attr_value));
    17001700            else Image->m_DeltaZ = z_level/100.f;
    17011701        }
    17021702        else
    void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite  
    17041704        {
    17051705            CColor color;
    17061706            if (!GUI<CColor>::ParseString(attr_value, color))
    1707                 LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
     1707                LOGERROR("GUI: Error parsing '%s' (\"%s\")", attr_name, utf8_from_wstring(attr_value));
    17081708            else Image->m_BackColor = color;
    17091709        }
    17101710        else
    void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite  
    17121712        {
    17131713            CColor color;
    17141714            if (!GUI<CColor>::ParseString(attr_value, color))
    1715                 LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
     1715                LOGERROR("GUI: Error parsing '%s' (\"%s\")", attr_name, utf8_from_wstring(attr_value));
    17161716            else Image->m_BorderColor = color;
    17171717        }
    17181718        else
    void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite  
    17201720        {
    17211721            bool b;
    17221722            if (!GUI<bool>::ParseString(attr_value, b))
    1723                 LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
     1723                LOGERROR("GUI: Error parsing '%s' (\"%s\")", attr_name, utf8_from_wstring(attr_value));
    17241724            else Image->m_Border = b;
    17251725        }
    17261726        else
    void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite  
    17391739        {
    17401740            if (Image->m_Effects)
    17411741            {
    1742                 LOGERROR(L"GUI <image> must not have more than one <effect>");
     1742                LOGERROR("GUI <image> must not have more than one <effect>");
    17431743            }
    17441744            else
    17451745            {
    void CGUI::Xeromyces_ReadEffects(XMBElement Element, CXeromyces* pFile, SGUIImag  
    17731773        {
    17741774            CColor color;
    17751775            if (!GUI<int>::ParseColor(attr_value, color, 0))
    1776                 LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
     1776                LOGERROR("GUI: Error parsing '%s' (\"%s\")", attr_name, utf8_from_wstring(attr_value));
    17771777            else effects.m_AddColor = color;
    17781778        }
    17791779        else if (attr_name == "grayscale")
    void CGUI::Xeromyces_ReadScrollBarStyle(XMBElement Element, CXeromyces* pFile)  
    18531853        {
    18541854            bool b;
    18551855            if (!GUI<bool>::ParseString(attr_value.FromUTF8(), b))
    1856                 LOGERROR(L"GUI: Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
     1856                LOGERROR("GUI: Error parsing '%s' (\"%s\")", attr_name, attr_value);
    18571857            else
    18581858                scrollbar.m_UseEdgeButtons = b;
    18591859        }
    void CGUI::Xeromyces_ReadScrollBarStyle(XMBElement Element, CXeromyces* pFile)  
    18611861        {
    18621862            float f;
    18631863            if (!GUI<float>::ParseString(attr_value.FromUTF8(), f))
    1864                 LOGERROR(L"GUI: Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
     1864                LOGERROR("GUI: Error parsing '%s' (\"%s\")", attr_name, attr_value);
    18651865            else
    18661866                scrollbar.m_Width = f;
    18671867        }
    void CGUI::Xeromyces_ReadScrollBarStyle(XMBElement Element, CXeromyces* pFile)  
    18701870        {
    18711871            float f;
    18721872            if (!GUI<float>::ParseString(attr_value.FromUTF8(), f))
    1873                 LOGERROR(L"GUI: Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
     1873                LOGERROR("GUI: Error parsing '%s' (\"%s\")", attr_name, attr_value);
    18741874            else
    18751875                scrollbar.m_MinimumBarSize = f;
    18761876        }
    void CGUI::Xeromyces_ReadScrollBarStyle(XMBElement Element, CXeromyces* pFile)  
    18791879        {
    18801880            float f;
    18811881            if (!GUI<float>::ParseString(attr_value.FromUTF8(), f))
    1882                 LOGERROR(L"GUI: Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
     1882                LOGERROR("GUI: Error parsing '%s' (\"%s\")", attr_name, attr_value);
    18831883            else
    18841884                scrollbar.m_MaximumBarSize = f;
    18851885        }
    void CGUI::Xeromyces_ReadIcon(XMBElement Element, CXeromyces* pFile)  
    19521952        {
    19531953            CSize size;
    19541954            if (!GUI<CSize>::ParseString(attr_value.FromUTF8(), size))
    1955                 LOGERROR(L"Error parsing '%hs' (\"%hs\") inside <icon>.", attr_name.c_str(), attr_value.c_str());
     1955                LOGERROR("Error parsing '%s' (\"%s\") inside <icon>.", attr_name, attr_value);
    19561956            else
    19571957                icon.m_Size = size;
    19581958        }
    void CGUI::Xeromyces_ReadIcon(XMBElement Element, CXeromyces* pFile)  
    19601960        {
    19611961            int cell_id;
    19621962            if (!GUI<int>::ParseString(attr_value.FromUTF8(), cell_id))
    1963                 LOGERROR(L"GUI: Error parsing '%hs' (\"%hs\") inside <icon>.", attr_name.c_str(), attr_value.c_str());
     1963                LOGERROR("GUI: Error parsing '%s' (\"%s\") inside <icon>.", attr_name, attr_value);
    19641964            else
    19651965                icon.m_CellID = cell_id;
    19661966        }
    void CGUI::Xeromyces_ReadColor(XMBElement Element, CXeromyces* pFile)  
    20132013        // Try setting color to value
    20142014        if (!color.ParseString(value))
    20152015        {
    2016             LOGERROR(L"GUI: Unable to create custom color '%hs'. Invalid color syntax.", name.c_str());
     2016            LOGERROR("GUI: Unable to create custom color '%s'. Invalid color syntax.", name.c_str());
    20172017        }
    20182018        else
    20192019        {
  • source/gui/CGUIScrollBarVertical.cpp

    diff --git a/source/gui/CGUIScrollBarVertical.cpp b/source/gui/CGUIScrollBarVertical.cpp
    index 4e0efe6..4c5c6eb 100644
    a b void CGUIScrollBarVertical::Draw()  
    5151{
    5252    if (!GetStyle())
    5353    {
    54         LOGWARNING(L"Attempt to draw scrollbar without a style.");
     54        LOGWARNING("Attempt to draw scrollbar without a style.");
    5555        return;
    5656    }
    5757
  • source/gui/COList.cpp

    diff --git a/source/gui/COList.cpp b/source/gui/COList.cpp
    index 09ff828..d42ed1f 100644
    a b bool COList::HandleAdditionalChildren(const XMBElement& child, CXeromyces* pFile  
    158158            {
    159159                CColor color;
    160160                if (!GUI<CColor>::ParseString(attr_value.FromUTF8(), color))
    161                     LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
     161                    LOGERROR("GUI: Error parsing '%s' (\"%s\")", attr_name.c_str(), attr_value.c_str());
    162162                else oDef.m_TextColor = color;
    163163            }
    164164            else if (attr_name == "id")
    bool COList::HandleAdditionalChildren(const XMBElement& child, CXeromyces* pFile  
    169169            {
    170170                float width;
    171171                if (!GUI<float>::ParseString(attr_value.FromUTF8(), width))
    172                     LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
     172                    LOGERROR("GUI: Error parsing '%s' (\"%s\")", attr_name.c_str(), attr_value.c_str());
    173173                else
    174174                {
    175175                    // Check if it's a relative value, and save as decimal if so.
    bool COList::HandleAdditionalChildren(const XMBElement& child, CXeromyces* pFile  
    215215                }
    216216                else // Ignore.
    217217                {
    218                     LOGERROR(L"GUI: translatable attribute in olist def that isn't a heading. (object: %hs)", this->GetPresentableName().c_str());
     218                    LOGERROR("GUI: translatable attribute in olist def that isn't a heading. (object: %s)", this->GetPresentableName().c_str());
    219219                }
    220220            }
    221221        }
  • source/gui/GUIManager.cpp

    diff --git a/source/gui/GUIManager.cpp b/source/gui/GUIManager.cpp
    index d0999c7..4656f37 100644
    a b void CGUIManager::PopPageCB(shared_ptr<ScriptInterface::StructuredClone> args)  
    117117        scriptInterface->ReadStructuredClone(initDataClone, &initDataVal);
    118118    else
    119119    {
    120         LOGERROR(L"Called PopPageCB when initData (which should contain the callback function name) isn't set!");
     120        LOGERROR("Called PopPageCB when initData (which should contain the callback function name) isn't set!");
    121121        return;
    122122    }
    123123   
    124124    if (!scriptInterface->HasProperty(initDataVal, "callback"))
    125125    {
    126         LOGERROR(L"Called PopPageCB when the callback function name isn't set!");
     126        LOGERROR("Called PopPageCB when the callback function name isn't set!");
    127127        return;
    128128    }
    129129   
    130130    std::string callback;
    131131    if (!scriptInterface->GetProperty(initDataVal, "callback", callback))
    132132    {
    133         LOGERROR(L"Failed to get the callback property as a string from initData in PopPageCB!");
     133        LOGERROR("Failed to get the callback property as a string from initData in PopPageCB!");
    134134        return;
    135135    }
    136136   
    137137    JS::RootedValue global(cx, scriptInterface->GetGlobalObject());
    138138    if (!scriptInterface->HasProperty(global, callback.c_str()))
    139139    {
    140         LOGERROR(L"The specified callback function %hs does not exist in the page %ls", callback.c_str(), m_PageStack.back().name.c_str());
     140        LOGERROR("The specified callback function %s does not exist in the page %s", callback, utf8_from_wstring(m_PageStack.back().name));
    141141        return;
    142142    }
    143143
    void CGUIManager::PopPageCB(shared_ptr<ScriptInterface::StructuredClone> args)  
    146146        scriptInterface->ReadStructuredClone(args, &argVal);
    147147    if (!scriptInterface->CallFunctionVoid(global, callback.c_str(), argVal))
    148148    {
    149         LOGERROR(L"Failed to call the callback function %hs in the page %ls", callback.c_str(), m_PageStack.back().name.c_str());
     149        LOGERROR("Failed to call the callback function %s in the page %s", callback, utf8_from_wstring(m_PageStack.back().name));
    150150        return;
    151151    }
    152152}
    void CGUIManager::LoadPage(SGUIPage& page)  
    204204
    205205    if (root.GetNodeName() != elmt_page)
    206206    {
    207         LOGERROR(L"GUI page '%ls' must have root element <page>", page.name.c_str());
     207        LOGERROR("GUI page '%s' must have root element <page>", utf8_from_wstring(page.name));
    208208        return;
    209209    }
    210210
    void CGUIManager::LoadPage(SGUIPage& page)  
    212212    {
    213213        if (node.GetNodeName() != elmt_include)
    214214        {
    215             LOGERROR(L"GUI page '%ls' must only have <include> elements inside <page>", page.name.c_str());
     215            LOGERROR("GUI page '%s' must only have <include> elements inside <page>", utf8_from_wstring(page.name));
    216216            continue;
    217217        }
    218218
    void CGUIManager::LoadPage(SGUIPage& page)  
    252252            hotloadDataVal)
    253253        )
    254254    {
    255         LOGERROR(L"GUI page '%ls': Failed to call init() function", page.name.c_str());
     255        LOGERROR("GUI page '%s': Failed to call init() function", utf8_from_wstring(page.name));
    256256    }
    257257
    258258    m_CurrentGUI = oldGUI;
    Status CGUIManager::ReloadChangedFile(const VfsPath& path)  
    264264    {
    265265        if (it->inputs.count(path))
    266266        {
    267             LOGMESSAGE(L"GUI file '%ls' changed - reloading page '%ls'", path.string().c_str(), it->name.c_str());
     267            LOGMESSAGE("GUI file '%s' changed - reloading page '%s'", path.string8(), utf8_from_wstring(it->name));
    268268            LoadPage(*it);
    269269            // TODO: this can crash if LoadPage runs an init script which modifies the page stack and breaks our iterators
    270270        }
    const CParamNode& CGUIManager::GetTemplate(const std::string& templateName)  
    407407{
    408408    const CParamNode& templateRoot = m_TemplateLoader.GetTemplateFileData(templateName).GetChild("Entity");
    409409    if (!templateRoot.IsOk())
    410         LOGERROR(L"Invalid template found for '%hs'", templateName.c_str());
     410        LOGERROR("Invalid template found for '%s'", templateName.c_str());
    411411
    412412    return templateRoot;
    413413}
  • source/gui/GUIRenderer.cpp

    diff --git a/source/gui/GUIRenderer.cpp b/source/gui/GUIRenderer.cpp
    index 75b133a..88f3115 100644
    a b void GUIRenderer::UpdateDrawCallCache(DrawCalls &Calls, const CStr& SpriteName,  
    144144            // Check colour is valid
    145145            if (!GUI<CColor>::ParseString(value, color))
    146146            {
    147                 LOGERROR(L"GUI: Error parsing sprite 'colour' (\"%ls\")", value.c_str());
     147                LOGERROR("GUI: Error parsing sprite 'colour' (\"%s\")", utf8_from_wstring(value));
    148148                return;
    149149            }
    150150
    void GUIRenderer::UpdateDrawCallCache(DrawCalls &Calls, const CStr& SpriteName,  
    167167        else
    168168        {
    169169            // Otherwise, just complain and give up:
    170             LOGERROR(L"Trying to use a sprite that doesn't exist (\"%hs\").", SpriteName.c_str());
     170            LOGERROR("Trying to use a sprite that doesn't exist (\"%s\").", SpriteName.c_str());
    171171            return;
    172172        }
    173173    }
  • source/gui/GUITooltip.cpp

    diff --git a/source/gui/GUITooltip.cpp b/source/gui/GUITooltip.cpp
    index c560885..55907bc 100644
    a b void GUITooltip::ShowTooltip(IGUIObject* obj, CPos pos, const CStr& style, CGUI*  
    149149    IGUIObject* tooltipobj = gui->FindObjectByName("__tooltip_"+style);
    150150    if (! tooltipobj)
    151151    {
    152         LOGERROR(L"Cannot find tooltip named '%hs'", style.c_str());
     152        LOGERROR("Cannot find tooltip named '%s'", style.c_str());
    153153        return;
    154154    }
    155155
    void GUITooltip::ShowTooltip(IGUIObject* obj, CPos pos, const CStr& style, CGUI*  
    162162        usedobj = gui->FindObjectByName(usedObjectName);
    163163        if (! usedobj)
    164164        {
    165             LOGERROR(L"Cannot find object named '%hs' used by tooltip '%hs'", usedObjectName.c_str(), style.c_str());
     165            LOGERROR("Cannot find object named '%s' used by tooltip '%s'", usedObjectName.c_str(), style.c_str());
    166166            return;
    167167        }
    168168
    void GUITooltip::HideTooltip(const CStr& style, CGUI* gui)  
    213213    IGUIObject* tooltipobj = gui->FindObjectByName("__tooltip_"+style);
    214214    if (! tooltipobj)
    215215    {
    216         LOGERROR(L"Cannot find tooltip named '%hs'", style.c_str());
     216        LOGERROR("Cannot find tooltip named '%s'", style.c_str());
    217217        return;
    218218    }
    219219
    void GUITooltip::HideTooltip(const CStr& style, CGUI* gui)  
    224224        IGUIObject* usedobj = gui->FindObjectByName(usedObjectName);
    225225        if (! usedobj)
    226226        {
    227             LOGERROR(L"Cannot find object named '%hs' used by tooltip '%hs'", usedObjectName.c_str(), style.c_str());
     227            LOGERROR("Cannot find object named '%s' used by tooltip '%s'", usedObjectName.c_str(), style.c_str());
    228228            return;
    229229        }
    230230
    static int GetTooltipDelay(CStr& style, CGUI* gui)  
    254254    IGUIObject* tooltipobj = gui->FindObjectByName("__tooltip_"+style);
    255255    if (! tooltipobj)
    256256    {
    257         LOGERROR(L"Cannot find tooltip object named '%hs'", style.c_str());
     257        LOGERROR("Cannot find tooltip object named '%s'", style.c_str());
    258258        return delay;
    259259    }
    260260    GUI<int>::GetSetting(tooltipobj, "delay", delay);
  • source/gui/GUIbase.cpp

    diff --git a/source/gui/GUIbase.cpp b/source/gui/GUIbase.cpp
    index 491c2ec..4d730a0 100644
    a b bool CClientArea::SetClientArea(const CStr& Value)  
    113113            coord++;
    114114            break;
    115115        default:
    116             LOGWARNING(L"ClientArea definitions may only contain numerics. Your input: '%hs'", Value.c_str());
     116            LOGWARNING("ClientArea definitions may only contain numerics. Your input: '%s'", Value.c_str());
    117117            return false;
    118118        }
    119119        if (coord > 3)
    120120        {
    121             LOGWARNING(L"Too many CClientArea parameters (4 max). Your input: '%hs'", Value.c_str());
     121            LOGWARNING("Too many CClientArea parameters (4 max). Your input: '%s'", Value.c_str());
    122122            return false;
    123123        }
    124124    }
    125125
    126126    if (coord < 3)
    127127    {
    128         LOGWARNING(L"Too few CClientArea parameters (4 min). Your input: '%hs'", Value.c_str());
     128        LOGWARNING("Too few CClientArea parameters (4 min). Your input: '%s'", Value.c_str());
    129129        return false;
    130130    }
    131131
  • source/gui/GUItext.cpp

    diff --git a/source/gui/GUItext.cpp b/source/gui/GUItext.cpp
    index 69d9f47..783bb30 100644
    a b void CGUIString::GenerateTextCall(const CGUI *pGUI,  
    109109            if (!pGUI->IconExists(path))
    110110            {
    111111                if (pObject)
    112                     LOGERROR(L"Trying to use an icon, imgleft or imgright-tag with an undefined icon (\"%hs\").", path.c_str());
     112                    LOGERROR("Trying to use an icon, imgleft or imgright-tag with an undefined icon (\"%s\").", path.c_str());
    113113                continue;
    114114            }
    115115
    void CGUIString::GenerateTextCall(const CGUI *pGUI,  
    158158                            CSize displacement;
    159159                            // Parse the value
    160160                            if (!GUI<CSize>::ParseString(tagAttrib.value, displacement))
    161                                 LOGERROR(L"Error parsing 'displace' value for tag [ICON]");
     161                                LOGERROR("Error parsing 'displace' value for tag [ICON]");
    162162                            else
    163163                                SpriteCall.m_Area += displacement;
    164164                        }
    void CGUIString::GenerateTextCall(const CGUI *pGUI,  
    182182                }
    183183                break;
    184184            default:
    185                 LOGERROR(L"Encountered unexpected tag applied to text");
     185                LOGERROR("Encountered unexpected tag applied to text");
    186186                break;
    187187            }
    188188        }
    void CGUIString::GenerateTextCall(const CGUI *pGUI,  
    207207
    208208                    if (!GUI<CColor>::ParseString(it2->m_TagValue, TextCall.m_Color)
    209209                        && pObject)
    210                         LOGERROR(L"Error parsing the value of a [color]-tag in GUI text when reading object \"%hs\".", pObject->GetPresentableName().c_str());
     210                        LOGERROR("Error parsing the value of a [color]-tag in GUI text when reading object \"%s\".", pObject->GetPresentableName().c_str());
    211211                    break;
    212212                case CGUIString::TextChunk::Tag::TAG_FONT:
    213213                    // TODO Gee: (2004-08-15) Check if Font exists?
    214214                    TextCall.m_Font = CStrIntern(utf8_from_wstring(it2->m_TagValue));
    215215                    break;
    216216                default:
    217                     LOGERROR(L"Encountered unexpected tag applied to text");
     217                    LOGERROR("Encountered unexpected tag applied to text");
    218218                    break;
    219219                }
    220220            }
    void CGUIString::SetValue(const CStrW& str)  
    306306            closing = false;
    307307            if (++p == l)
    308308            {
    309                 LOGERROR(L"Partial tag at end of string '%ls'", str.c_str());
     309                LOGERROR("Partial tag at end of string '%s'", utf8_from_wstring(str));
    310310                break;
    311311            }
    312312            if (str[p] == L'/')
    void CGUIString::SetValue(const CStrW& str)  
    314314                closing = true;
    315315                if (tags.empty())
    316316                {
    317                     LOGERROR(L"Encountered closing tag without having any open tags. At %d in '%ls'", p, str.c_str());
     317                    LOGERROR("Encountered closing tag without having any open tags. At %d in '%s'", p, utf8_from_wstring(str));
    318318                    break;
    319319                }
    320320                if (++p == l)
    321321                {
    322                     LOGERROR(L"Partial closing tag at end of string '%ls'", str.c_str());
     322                    LOGERROR("Partial closing tag at end of string '%s'", utf8_from_wstring(str));
    323323                    break;
    324324                }
    325325            }
    void CGUIString::SetValue(const CStrW& str)  
    332332                {
    333333                case L' ':
    334334                    if (closing) // We still parse them to make error handling cleaner
    335                         LOGERROR(L"Closing tags do not support parameters (at pos %d '%ls')", p, str.c_str());
     335                        LOGERROR("Closing tags do not support parameters (at pos %d '%s')", p, utf8_from_wstring(str));
    336336
    337337                    // parse something="something else"
    338338                    for (++p; p < l && str[p] != L'='; ++p)
    void CGUIString::SetValue(const CStrW& str)  
    340340
    341341                    if (p == l)
    342342                    {
    343                         LOGERROR(L"Parameter without value at pos %d '%ls'", p, str.c_str());
     343                        LOGERROR("Parameter without value at pos %d '%s'", p, utf8_from_wstring(str));
    344344                        break;
    345345                    }
    346346                    // fall-through
    347347                case L'=':
    348348                    // parse a quoted parameter
    349349                    if (closing) // We still parse them to make error handling cleaner
    350                         LOGERROR(L"Closing tags do not support parameters (at pos %d '%ls')", p, str.c_str());
     350                        LOGERROR("Closing tags do not support parameters (at pos %d '%s')", p, utf8_from_wstring(str));
    351351
    352352                    if (++p == l)
    353353                    {
    354                         LOGERROR(L"Expected parameter, got end of string '%ls'", str.c_str());
     354                        LOGERROR("Expected parameter, got end of string '%s'", utf8_from_wstring(str));
    355355                        break;
    356356                    }
    357357                    if (str[p] != L'"')
    358358                    {
    359                         LOGERROR(L"Unquoted parameters are not supported (at pos %d '%ls')", p, str.c_str());
     359                        LOGERROR("Unquoted parameters are not supported (at pos %d '%s')", p, utf8_from_wstring(str));
    360360                        break;
    361361                    }
    362362                    for (++p; p < l && str[p] != L'"'; ++p)
    void CGUIString::SetValue(const CStrW& str)  
    366366                        case L'\\':
    367367                            if (++p == l)
    368368                            {
    369                                 LOGERROR(L"Escape character at end of string '%ls'", str.c_str());
     369                                LOGERROR("Escape character at end of string '%s'", utf8_from_wstring(str));
    370370                                break;
    371371                            }
    372372                            // NOTE: We do not support \n in tag parameters
    void CGUIString::SetValue(const CStrW& str)  
    392392
    393393            if (!tag_.SetTagType(tag))
    394394            {
    395                 LOGERROR(L"Invalid tag '%ls' at %d in '%ls'", tag.c_str(), p, str.c_str());
     395                LOGERROR("Invalid tag '%s' at %d in '%s'", utf8_from_wstring(tag), p, utf8_from_wstring(str));
    396396                break;
    397397            }
    398398            if (!closing)
    void CGUIString::SetValue(const CStrW& str)  
    415415            {
    416416                if (tag != tags.back())
    417417                {
    418                     LOGERROR(L"Closing tag '%ls' does not match last opened tag '%ls' at %d in '%ls'", tag.c_str(), tags.back().c_str(), p, str.c_str());
     418                    LOGERROR("Closing tag '%s' does not match last opened tag '%s' at %d in '%s'", utf8_from_wstring(tag), utf8_from_wstring(tags.back()), p, utf8_from_wstring(str));
    419419                    break;
    420420                }
    421421
    void CGUIString::SetValue(const CStrW& str)  
    426426        case L'\\':
    427427            if (++p == l)
    428428            {
    429                 LOGERROR(L"Escape character at end of string '%ls'", str.c_str());
     429                LOGERROR("Escape character at end of string '%s'", utf8_from_wstring(str));
    430430                break;
    431431            }
    432432            if (str[p] == L'n')
  • source/gui/GUIutil.cpp

    diff --git a/source/gui/GUIutil.cpp b/source/gui/GUIutil.cpp
    index 009c702..95ff0fd 100644
    a b bool __ParseString<CRect>(const CStrW& Value, CRect &Output)  
    6969    {
    7070        if (stream.eof())
    7171        {
    72             LOGWARNING(L"Too few CRect parameters (min %i). Your input: '%hs'", NUM_COORDS, Value.ToUTF8().c_str());
     72            LOGWARNING("Too few CRect parameters (min %i). Your input: '%s'", NUM_COORDS, Value.ToUTF8().c_str());
    7373            return false;
    7474        }
    7575        stream >> coords[i];
    7676        if ((stream.rdstate() & std::wstringstream::failbit) != 0)
    7777        {
    78             LOGWARNING(L"Unable to parse CRect parameters. Your input: '%hs'", Value.ToUTF8().c_str());
     78            LOGWARNING("Unable to parse CRect parameters. Your input: '%s'", Value.ToUTF8().c_str());
    7979            return false;
    8080        }
    8181    }
    8282
    8383    if (!stream.eof())
    8484    {
    85         LOGWARNING(L"Too many CRect parameters (max %i). Your input: '%hs'", NUM_COORDS, Value.ToUTF8().c_str());
     85        LOGWARNING("Too many CRect parameters (max %i). Your input: '%s'", NUM_COORDS, Value.ToUTF8().c_str());
    8686        return false;
    8787    }
    8888
    bool __ParseString<CSize>(const CStrW& Value, CSize &Output)  
    134134    {
    135135        if (stream.eof())
    136136        {
    137             LOGWARNING(L"Too few CSize parameters (min %i). Your input: '%hs'", NUM_COORDS, Value.ToUTF8().c_str());
     137            LOGWARNING("Too few CSize parameters (min %i). Your input: '%s'", NUM_COORDS, Value.ToUTF8().c_str());
    138138            return false;
    139139        }
    140140        stream >> coords[i];
    141141        if ((stream.rdstate() & std::wstringstream::failbit) != 0)
    142142        {
    143             LOGWARNING(L"Unable to parse CSize parameters. Your input: '%hs'", Value.ToUTF8().c_str());
     143            LOGWARNING("Unable to parse CSize parameters. Your input: '%s'", Value.ToUTF8().c_str());
    144144            return false;
    145145        }
    146146    }
    bool __ParseString<CSize>(const CStrW& Value, CSize &Output)  
    150150
    151151    if (!stream.eof())
    152152    {
    153         LOGWARNING(L"Too many CSize parameters (max %i). Your input: '%hs'", NUM_COORDS, Value.ToUTF8().c_str());
     153        LOGWARNING("Too many CSize parameters (max %i). Your input: '%s'", NUM_COORDS, Value.ToUTF8().c_str());
    154154        return false;
    155155    }
    156156
    bool __ParseString<CPos>(const CStrW& Value, CPos &Output)  
    169169    {
    170170        if (stream.eof())
    171171        {
    172             LOGWARNING(L"Too few CPos parameters (min %i). Your input: '%hs'", NUM_COORDS, Value.ToUTF8().c_str());
     172            LOGWARNING("Too few CPos parameters (min %i). Your input: '%s'", NUM_COORDS, Value.ToUTF8().c_str());
    173173            return false;
    174174        }
    175175        stream >> coords[i];
    176176        if ((stream.rdstate() & std::wstringstream::failbit) != 0)
    177177        {
    178             LOGWARNING(L"Unable to parse CPos parameters. Your input: '%hs'", Value.ToUTF8().c_str());
     178            LOGWARNING("Unable to parse CPos parameters. Your input: '%s'", Value.ToUTF8().c_str());
    179179            return false;
    180180        }
    181181    }
    bool __ParseString<CPos>(const CStrW& Value, CPos &Output)  
    185185
    186186    if (!stream.eof())
    187187    {
    188         LOGWARNING(L"Too many CPos parameters (max %i). Your input: '%hs'", NUM_COORDS, Value.ToUTF8().c_str());
     188        LOGWARNING("Too many CPos parameters (max %i). Your input: '%s'", NUM_COORDS, Value.ToUTF8().c_str());
    189189        return false;
    190190    }
    191191
    PSRETURN GUI<T>::GetSettingPointer(const IGUIObject *pObject, const CStr& Settin  
    339339    std::map<CStr, SGUISetting>::const_iterator it = pObject->m_Settings.find(Setting);
    340340    if (it == pObject->m_Settings.end())
    341341    {
    342         LOGWARNING(L"setting %hs was not found on object %hs",
     342        LOGWARNING("setting %s was not found on object %s",
    343343            Setting.c_str(),
    344344            pObject->GetPresentableName().c_str());
    345345        return PSRETURN_GUI_InvalidSetting;
    PSRETURN GUI<T>::SetSetting(IGUIObject *pObject, const CStr& Setting,  
    388388
    389389    if (!pObject->SettingExists(Setting))
    390390    {
    391         LOGWARNING(L"setting %hs was not found on object %hs",
     391        LOGWARNING("setting %s was not found on object %s",
    392392            Setting.c_str(),
    393393            pObject->GetPresentableName().c_str());
    394394        return PSRETURN_GUI_InvalidSetting;
  • source/gui/IGUIObject.cpp

    diff --git a/source/gui/IGUIObject.cpp b/source/gui/IGUIObject.cpp
    index d32cb28..091cdd3 100644
    a b bool IGUIObject::IsRootObject() const  
    561561
    562562PSRETURN IGUIObject::LogInvalidSettings(const CStr8 &Setting) const
    563563{
    564     LOGWARNING(L"IGUIObject: setting %hs was not found on an object",
     564    LOGWARNING("IGUIObject: setting %s was not found on an object",
    565565        Setting.c_str());
    566566    return PSRETURN_GUI_InvalidSetting;
    567567}
  • source/gui/scripting/ScriptFunctions.cpp

    diff --git a/source/gui/scripting/ScriptFunctions.cpp b/source/gui/scripting/ScriptFunctions.cpp
    index 1f7f309..ad56e91 100644
    a b void SaveGame(ScriptInterface::CxPrivate* pCxPrivate, std::wstring filename, std  
    308308   
    309309    shared_ptr<ScriptInterface::StructuredClone> GUIMetadataClone = pCxPrivate->pScriptInterface->WriteStructuredClone(GUIMetadata);
    310310    if (SavedGames::Save(filename, description, *g_Game->GetSimulation2(), GUIMetadataClone, g_Game->GetPlayerID()) < 0)
    311         LOGERROR(L"Failed to save game");
     311        LOGERROR("Failed to save game");
    312312}
    313313
    314314void SaveGamePrefix(ScriptInterface::CxPrivate* pCxPrivate, std::wstring prefix, std::wstring description, CScriptVal GUIMetadata1)
    void SaveGamePrefix(ScriptInterface::CxPrivate* pCxPrivate, std::wstring prefix,  
    320320   
    321321    shared_ptr<ScriptInterface::StructuredClone> GUIMetadataClone = pCxPrivate->pScriptInterface->WriteStructuredClone(GUIMetadata);
    322322    if (SavedGames::SavePrefix(prefix, description, *g_Game->GetSimulation2(), GUIMetadataClone, g_Game->GetPlayerID()) < 0)
    323         LOGERROR(L"Failed to save game");
     323        LOGERROR("Failed to save game");
    324324}
    325325
    326326void SetNetworkGameAttributes(ScriptInterface::CxPrivate* pCxPrivate, CScriptVal attribs1)
    void SetTurnLength(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), int length)  
    630630    if (g_NetServer)
    631631        g_NetServer->SetTurnLength(length);
    632632    else
    633         LOGERROR(L"Only network host can change turn length");
     633        LOGERROR("Only network host can change turn length");
    634634}
    635635
    636636// Focus the game camera on a given position.
    void DumpTerrainMipmap(ScriptInterface::CxPrivate* UNUSED(pCxPrivate))  
    676676    g_Game->GetWorld()->GetTerrain()->GetHeightMipmap().DumpToDisk(filename);
    677677    OsPath realPath;
    678678    g_VFS->GetRealPath(filename, realPath);
    679     LOGMESSAGERENDER(L"Terrain mipmap written to '%ls'", realPath.string().c_str());
     679    LOGMESSAGERENDER("Terrain mipmap written to '%s'", realPath.string8());
    680680}
    681681
    682682void EnableTimeWarpRecording(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), unsigned int numTurns)
    void StartJsTimer(ScriptInterface::CxPrivate* pCxPrivate, unsigned int slot)  
    906906    ONCE(InitJsTimers(*(pCxPrivate->pScriptInterface)));
    907907   
    908908    if (slot >= MAX_JS_TIMERS)
    909         LOGERROR(L"Exceeded the maximum number of timer slots for scripts!");
     909        LOGERROR("Exceeded the maximum number of timer slots for scripts!");
    910910
    911911    js_start_times[slot].SetFromTimer();
    912912}
    void StartJsTimer(ScriptInterface::CxPrivate* pCxPrivate, unsigned int slot)  
    914914void StopJsTimer(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), unsigned int slot)
    915915{
    916916    if (slot >= MAX_JS_TIMERS)
    917         LOGERROR(L"Exceeded the maximum number of timer slots for scripts!");
     917        LOGERROR("Exceeded the maximum number of timer slots for scripts!");
    918918
    919919    TimerUnit now;
    920920    now.SetFromTimer();
  • source/i18n/L10n.cpp

    diff --git a/source/i18n/L10n.cpp b/source/i18n/L10n.cpp
    index a77c7da..e1eb005 100644
    a b void L10n::GetDictionaryLocale(const std::string& configLocaleString, Locale& ou  
    203203            return;
    204204        }
    205205        else
    206             LOGWARNING(L"The configured locale is not valid or no translations are available. Falling back to another locale.");
     206            LOGWARNING("The configured locale is not valid or no translations are available. Falling back to another locale.");
    207207    }
    208208   
    209209    Locale systemLocale = Locale::getDefault();
    std::string L10n::FormatMillisecondsIntoDateString(const UDate& milliseconds, co  
    408408    UnicodeString unicodeFormat = UnicodeString::fromUTF8(formatString.c_str());
    409409    SimpleDateFormat* dateFormat = new SimpleDateFormat(unicodeFormat, status);
    410410    if (U_FAILURE(status))
    411         LOGERROR(L"Error creating SimpleDateFormat: %hs", u_errorName(status));
     411        LOGERROR("Error creating SimpleDateFormat: %s", u_errorName(status));
    412412
    413413    const TimeZone* timeZone = TimeZone::getGMT();
    414414
    415415    status = U_ZERO_ERROR;
    416416    Calendar* calendar = Calendar::createInstance(*timeZone, currentLocale, status);
    417417    if (U_FAILURE(status))
    418         LOGERROR(L"Error creating calendar: %hs", u_errorName(status));
     418        LOGERROR("Error creating calendar: %s", u_errorName(status));
    419419   
    420420    dateFormat->adoptCalendar(calendar);
    421421    dateFormat->format(milliseconds, dateString);
    Status L10n::ReloadChangedFile(const VfsPath& path)  
    470470    if (path.string().rfind(dictName) == std::string::npos)
    471471        return INFO::OK;
    472472
    473     LOGMESSAGE(L"Hotloading translations from '%ls'", path.string().c_str());
     473    LOGMESSAGE("Hotloading translations from '%s'", path.string8());
    474474
    475475    CVFSFile file;
    476476    if (file.Load(g_VFS, path) != PSRETURN_OK)
    477477    {
    478         LOGERROR(L"Failed to read translations from '%ls'", path.string().c_str());
     478        LOGERROR("Failed to read translations from '%s'", path.string8());
    479479        return ERR::FAIL;
    480480    }
    481481
    void L10n::LoadDictionaryForCurrentLocale()  
    505505        std::wstring dictName = GetFallbackToAvailableDictLocale(currentLocale);
    506506        if (vfs::GetPathnames(g_VFS, L"l10n/", dictName.append(L".*.po").c_str(), filenames) < 0)
    507507        {
    508             LOGERROR(L"No files for the dictionary found, but at this point the input should already be validated!");
     508            LOGERROR("No files for the dictionary found, but at this point the input should already be validated!");
    509509            return;
    510510        }
    511511    }
    void L10n::ReadPoIntoDictionary(const std::string& poContent, tinygettext::Dicti  
    569569    }
    570570    catch(std::exception& e)
    571571    {
    572         LOGERROR(L"[Localization] Exception while reading virtual PO file: %hs", e.what());
     572        LOGERROR("[Localization] Exception while reading virtual PO file: %s", e.what());
    573573    }
    574574}
    575575
  • source/lib/path.h

    diff --git a/source/lib/path.h b/source/lib/path.h
    index 02083ec..7facfb6 100644
    a b  
    4141# include "boost/functional/hash.hpp"
    4242#endif
    4343
     44#include "lib/utf8.h"
     45
    4446#include <cstring>
    4547
    4648namespace ERR
    public:  
    125127        return path;
    126128    }
    127129
     130    std::string string8() const
     131    {
     132        return utf8_from_wstring(path);
     133    }
     134
    128135    bool operator<(const Path& rhs) const
    129136    {
    130137        return path < rhs.path;
  • source/lib/secure_crt.cpp

    diff --git a/source/lib/secure_crt.cpp b/source/lib/secure_crt.cpp
    index 849c76e..40c0771 100644
    a b int tvsprintf_s(tchar* dst, size_t max_dst_chars, const tchar* fmt, va_list ap)  
    237237    }
    238238
    239239    const int ret = tvsnprintf(dst, max_dst_chars, fmt, ap);
    240     if(ret >= int(max_dst_chars))   // not enough space
     240    if(ret < 0 || ret >= int(max_dst_chars))    // not enough space
    241241    {
    242242        dst[0] = '\0';
    243243        return -1;
  • source/lib/self_test.h

    diff --git a/source/lib/self_test.h b/source/lib/self_test.h
    index 27e3870..4b68be0 100644
    a b namespace CxxTest  
    269269#define TS_ASSERT_PATH_EQUALS(path1, path2) TS_ASSERT_EQUALS((path1).string(), (path2).string())
    270270#define TSM_ASSERT_PATH_EQUALS(m, path1, path2) TSM_ASSERT_EQUALS(m, (path1).string(), (path2).string())
    271271
     272bool ts_str_contains(const std::string& str1, const std::string& str2); // defined in test_setup.cpp
    272273bool ts_str_contains(const std::wstring& str1, const std::wstring& str2); // defined in test_setup.cpp
     274#define TS_ASSERT_STR_CONTAINS(str1, str2) TSM_ASSERT(str1, ts_str_contains(str1, str2))
     275#define TS_ASSERT_STR_NOT_CONTAINS(str1, str2) TSM_ASSERT(str1, !ts_str_contains(str1, str2))
    273276#define TS_ASSERT_WSTR_CONTAINS(str1, str2) TSM_ASSERT(str1, ts_str_contains(str1, str2))
    274277#define TS_ASSERT_WSTR_NOT_CONTAINS(str1, str2) TSM_ASSERT(str1, !ts_str_contains(str1, str2))
    275278
  • source/lib/sysdep/os/linux/dir_watch_inotify.cpp

    diff --git a/source/lib/sysdep/os/linux/dir_watch_inotify.cpp b/source/lib/sysdep/os/linux/dir_watch_inotify.cpp
    index 52bd702..93c5ad2 100644
    a b Status dir_watch_Add(const OsPath& path, PDirWatch& dirWatch)  
    188188            // Check for error ?
    189189            int err = errno;
    190190            initialized = -1;
    191             LOGERROR(L"Error initializing inotify file descriptor; hotloading will be disabled, errno=%d", err);
     191            LOGERROR("Error initializing inotify file descriptor; hotloading will be disabled, errno=%d", err);
    192192            errno = err;
    193193            return StatusFromErrno();   // NOWARN
    194194        }
    Status dir_watch_Add(const OsPath& path, PDirWatch& dirWatch)  
    198198        if (ret != 0)
    199199        {
    200200            initialized = -1;
    201             LOGERROR(L"Error creating inotify event loop thread; hotloading will be disabled, err=%d", ret);
     201            LOGERROR("Error creating inotify event loop thread; hotloading will be disabled, err=%d", ret);
    202202            errno = ret;
    203203            return StatusFromErrno();   // NOWARN
    204204        }
  • deleted file source/lib/sysdep/os/unix/printf.cpp

    diff --git a/source/lib/sysdep/os/unix/printf.cpp b/source/lib/sysdep/os/unix/printf.cpp
    deleted file mode 100644
    index 6c5a8be..0000000
    + -  
    1 /* Copyright (c) 2010 Wildfire Games
    2  *
    3  * Permission is hereby granted, free of charge, to any person obtaining
    4  * a copy of this software and associated documentation files (the
    5  * "Software"), to deal in the Software without restriction, including
    6  * without limitation the rights to use, copy, modify, merge, publish,
    7  * distribute, sublicense, and/or sell copies of the Software, and to
    8  * permit persons to whom the Software is furnished to do so, subject to
    9  * the following conditions:
    10  *
    11  * The above copyright notice and this permission notice shall be included
    12  * in all copies or substantial portions of the Software.
    13  *
    14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    19  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    21  */
    22 
    23 #include "precompiled.h"
    24 
    25 #include <cstdio>
    26 #include <cstdarg>
    27 
    28 // See declaration in sysdep.h for explanation of need
    29 
    30 int sys_vswprintf(wchar_t* buffer, size_t count, const wchar_t* format, va_list argptr)
    31 {
    32     int ret = vswprintf(buffer, count, format, argptr);
    33 
    34     // Guarantee the buffer is null terminated on error
    35     if (ret < 0 && count > 0)
    36         buffer[count-1] = '\0';
    37 
    38     return ret;
    39 }
  • deleted file source/lib/sysdep/os/win/wprintf.cpp

    diff --git a/source/lib/sysdep/os/win/wprintf.cpp b/source/lib/sysdep/os/win/wprintf.cpp
    deleted file mode 100644
    index dce843c..0000000
    + -  
    1 /* Copyright (c) 2010 Wildfire Games
    2  *
    3  * Permission is hereby granted, free of charge, to any person obtaining
    4  * a copy of this software and associated documentation files (the
    5  * "Software"), to deal in the Software without restriction, including
    6  * without limitation the rights to use, copy, modify, merge, publish,
    7  * distribute, sublicense, and/or sell copies of the Software, and to
    8  * permit persons to whom the Software is furnished to do so, subject to
    9  * the following conditions:
    10  *
    11  * The above copyright notice and this permission notice shall be included
    12  * in all copies or substantial portions of the Software.
    13  *
    14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    19  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    21  */
    22 
    23 /*
    24  * implementation of sys_vswprintf.
    25  */
    26 
    27 #include "precompiled.h"
    28 
    29 #if ARCH_IA32
    30 
    31 /*
    32     See http://www.opengroup.org/onlinepubs/009695399/functions/fprintf.html
    33     for the specification (apparently an extension to ISO C) that was used
    34     when creating this code.
    35 */
    36 
    37 /*
    38     Added features (compared to MSVC's printf):
    39         Positional parameters (e.g. "%1$d", where '1' means '1st in the parameter list')
    40         %lld (equivalent to %I64d in MSVC7.1, though it's supported natively by MSVC8)
    41 
    42     Unsupported features (compared to a perfect implementation):
    43         '   <-- because MSVC doesn't support it
    44         %S  }
    45         %C  } because they're unnecessary and can cause confusion
    46         *   <-- probably works in some situations, but don't expect it to
    47         *m$ <-- positional precision parameters, because they're not worthwhile
    48         portability <-- just use GCC
    49         efficiency  <-- nothing in the spec says it should be as fast as possible
    50                         (the code could be made a lot faster if speed mattered more
    51                         than non-fixed size buffers)
    52 
    53 */
    54 
    55 #ifndef _UNICODE
    56 #define _UNICODE
    57 #endif
    58 #include <tchar.h>
    59 #ifdef _UNICODE
    60 # define tstring wstring
    61 # define tstringstream wstringstream
    62 #else
    63 # define tstring string
    64 # define tstringstream stringstream
    65 #endif
    66 #include <string>
    67 #include <vector>
    68 
    69 #include <stdio.h>
    70 #include <sstream>
    71 #include <stdarg.h>
    72 
    73 #if MSC_VERSION < 1400
    74 # define USE_I64_FORMAT 1
    75 #else
    76 # define USE_I64_FORMAT 0
    77 #endif
    78 
    79 enum
    80 {
    81     SPECFLAG_THOUSANDS      = 1,    // '
    82     SPECFLAG_LEFTJUSTIFIED  = 2,    // -
    83     SPECFLAG_SIGNED         = 4,    // +
    84     SPECFLAG_SPACEPREFIX    = 8,    // <space>
    85     SPECFLAG_ALTERNATE      = 16,   // #
    86     SPECFLAG_ZEROPAD        = 32    // 0
    87 };
    88 
    89 struct FormatChunk
    90 {
    91     virtual ~FormatChunk() { }
    92     virtual int ChunkType() = 0; // 0 = FormatSpecification, 1 = FormatString
    93 };
    94 
    95 struct FormatVariable : public FormatChunk
    96 {
    97     int ChunkType() { return 0; }
    98     int position;   // undefined if the format includes no positional elements
    99     char flags;     // ['-+ #0]
    100     int width;      // -1 for *, 0 for unspecified 
    101     int precision;  // -1 for *
    102     int length;     // "\0\0\0l", "\0\0hh", etc
    103     char type;      // 'd', etc
    104 };
    105 
    106 struct FormatString : public FormatChunk
    107 {
    108     int ChunkType() { return 1; }
    109     FormatString(std::tstring t) : text(t) {}
    110     std::tstring text;
    111 };
    112 
    113 
    114 int get_flag(TCHAR c)
    115 {
    116     switch (c)
    117     {
    118     case _T('\''): return SPECFLAG_THOUSANDS;
    119     case _T('-'):  return SPECFLAG_LEFTJUSTIFIED;
    120     case _T('+'):  return SPECFLAG_SIGNED;
    121     case _T(' '):  return SPECFLAG_SPACEPREFIX;
    122     case _T('#'):  return SPECFLAG_ALTERNATE;
    123     case _T('0'):  return SPECFLAG_ZEROPAD;
    124     }
    125     return 0;
    126 }
    127 
    128 std::tstring flags_to_string(char flags)
    129 {
    130     std::tstring s;
    131     const char* c = "\'-+ #0";
    132     for (int i=0; i<6; ++i)
    133         if (flags & (1<<i))
    134             s += c[i];
    135     return s;
    136 }
    137 
    138 template<typename T>
    139 std::tstring to_string(T n)
    140 {
    141     std::tstring s;
    142     std::tstringstream str;
    143     str << n;
    144     str >> s;
    145     return s;
    146 }
    147 
    148 int is_lengthmod(TCHAR c)
    149 {
    150     return
    151         c == _T('h') ||
    152         c == _T('l') ||
    153         c == _T('j') ||
    154         c == _T('z') ||
    155         c == _T('t') ||
    156         c == _T('L');
    157 }
    158 
    159 // _T2('l') == 'll'
    160 #define _T2(a) ((a<<8) | a)
    161 
    162 int type_size(TCHAR type, int length)
    163 {
    164     switch (type)
    165     {
    166     case 'd':
    167     case 'i':
    168         switch (length)
    169         {
    170         case _T ('l'):  return sizeof(long);
    171         case _T2('l'):  return sizeof(long long);
    172         case _T ('h'):  return sizeof(short);
    173         case _T2('h'):  return sizeof(char);
    174         default: return sizeof(int);
    175         }
    176     case 'o':
    177     case 'u':
    178     case 'x':
    179     case 'X': return sizeof(unsigned);
    180     case 'f':
    181     case 'F':
    182     case 'e':
    183     case 'E':
    184     case 'g':
    185     case 'G':
    186     case 'a':
    187     case 'A':
    188         if (length == _T('L'))
    189             return sizeof(long double);
    190         else
    191             return sizeof(double);
    192        
    193     case 'c':
    194         // "%lc" is a wide character, passed as a wint_t (ushort)
    195         if (length == _T('l'))
    196             return sizeof(wint_t);
    197         // "%c" is an int, apparently
    198         else
    199             return sizeof(int);
    200 
    201     case 's':
    202         if (length == _T('l'))
    203             return sizeof(wchar_t*);
    204         else
    205             return sizeof(char*);
    206 
    207     case 'p':
    208         return sizeof(void*);
    209 
    210     case 'n':
    211         return sizeof(int*);
    212 
    213     }
    214     return 0;
    215 }
    216 
    217 int sys_vswprintf(TCHAR* buffer, size_t count, const TCHAR* format, va_list argptr)
    218 {
    219     // To help quickly detect incorrect 'count' values, fill the buffer with 0s
    220     memset(buffer, 0, count*sizeof(TCHAR));
    221 
    222     /*
    223    
    224     Format 'variable' specifications are (in pseudo-Perl regexp syntax):
    225 
    226     % (\d+$)? ['-+ #0]? (* | \d+)?  (. (* | \d*) )? (hh|h|l|ll|j|z|t|L)? [diouxXfFeEgGaAcspnCS%]
    227       position  flags     width       precision          length                   type
    228 
    229     */
    230 
    231     /**** Parse the format string into constant/variable chunks ****/
    232 
    233     std::vector<FormatChunk*> specs;
    234     std::tstring stringchunk;
    235 
    236     TCHAR chr;
    237 
    238 #define readchar(x) if ((x = *format++) == '\0') { delete s; goto finished_reading; }
    239 
    240     while ((chr = *format++) != '\0')
    241     {
    242         if (chr == _T('%'))
    243         {
    244             // Handle %% correctly
    245             if (*format == _T('%'))
    246             {
    247                 stringchunk += _T('%');
    248                 continue;
    249             }
    250 
    251             // End the current string and start a new spec chunk
    252             if (stringchunk.length())
    253             {
    254                 specs.push_back(new FormatString(stringchunk));
    255                 stringchunk = _T("");
    256             }
    257 
    258             FormatVariable *s = new FormatVariable;
    259             s->position = -1;
    260             s->flags = 0;
    261             s->width = 0;
    262             s->precision = 0;
    263             s->length = 0;
    264             s->type = 0;
    265 
    266             // Read either the position or the width
    267             int number = 0;
    268 
    269             while (1)
    270             {
    271                 readchar(chr);
    272 
    273                 // Read flags (but not if it's a 0 appearing after other digits)
    274                 if (!number && get_flag(chr))
    275                     s->flags = (char)(s->flags|get_flag(chr));
    276 
    277                 // Read decimal numbers (position or width)
    278                 else if (isdigit(chr))
    279                     number = number*10 + (chr-'0');
    280 
    281                 // If we've reached a $, 'number' was the position,
    282                 // so remember it and start getting the width
    283                 else if (chr == _T('$'))
    284                 {
    285                     s->position = number;
    286                     number = 0;
    287                 }
    288 
    289                 // End of the number section
    290                 else
    291                 {
    292                     // Remember the width
    293                     s->width = number;
    294 
    295                     // Start looking for a precision
    296                     if (chr == _T('.'))
    297                     {
    298                         // Found a precision: read the digits
    299 
    300                         number = 0;
    301 
    302                         while (1)
    303                         {
    304                             readchar(chr);
    305 
    306                             if (isdigit(chr))
    307                                 number = number*10 + (chr-'0');
    308                             else
    309                             {
    310                                 s->precision = number;
    311                                 break;
    312                             }
    313                         }
    314                     }
    315 
    316                     // Finished dealing with any precision.
    317 
    318                     // Now check for length and type codes.
    319 
    320                     if (chr == _T('I'))
    321                     {
    322                         DEBUG_WARN_ERR(ERR::LOGIC); // MSVC-style \"%I64\" is not allowed!
    323                     }
    324 
    325                     if (is_lengthmod(chr))
    326                     {
    327                         s->length = chr;
    328 
    329                         // Check for ll and hh
    330                         if (chr == _T('l') || chr == _T('h'))
    331                         {
    332                             if (*format == chr)
    333                             {
    334                                 s->length |= (chr << 8);
    335                                 ++format;
    336                             }
    337                         }
    338 
    339                         readchar(chr);
    340                     }
    341 
    342                     s->type = (char)chr;
    343 
    344                     specs.push_back(s);
    345 
    346                     break;
    347                 }
    348             }
    349         }
    350         else
    351         {
    352             stringchunk += chr;
    353         }
    354     }
    355 
    356 #undef readchar
    357 
    358 finished_reading:
    359 
    360     if (stringchunk.length())
    361     {
    362         specs.push_back(new FormatString(stringchunk));
    363         stringchunk = _T("");
    364     }
    365 
    366     /**** Build a new format string (to pass to the system printf) ****/
    367 
    368     std::tstring newformat;
    369 
    370     std::vector<int> varsizes; // stores the size of each variable type, to allow stack twiddling
    371 
    372     typedef std::vector<FormatChunk*>::iterator ChunkIt;
    373 
    374     for (ChunkIt it = specs.begin(); it != specs.end(); ++it)
    375     {
    376         if ((*it)->ChunkType() == 0)
    377         {
    378             FormatVariable* s = static_cast<FormatVariable*>(*it);
    379 
    380             if (s->position > 0)
    381             {
    382                 // Grow if necessary
    383                 if (s->position >= (int)varsizes.size())
    384                     varsizes.resize(s->position+1, -1);
    385                 // Store the size of the current type
    386                 varsizes[s->position] = type_size(s->type, s->length);
    387             }
    388 
    389 
    390             newformat += _T("%");
    391 
    392             if (s->flags)
    393                 newformat += flags_to_string(s->flags);
    394            
    395             if (s->width == -1)
    396                 newformat += '*';
    397             else if (s->width)
    398                 newformat += to_string(s->width);
    399 
    400             if (s->precision)
    401             {
    402                 newformat += '.';
    403                 if (s->precision == -1)
    404                     newformat += '*';
    405                 else
    406                     newformat += to_string(s->precision);
    407             }
    408 
    409             if (s->length)
    410             {
    411                 if (s->length > 256)
    412                 {
    413                     if (s->length == 0x00006c6c)
    414                         #if USE_I64_FORMAT
    415                          newformat += "I64";
    416                         #else
    417                          newformat += _T("ll");
    418                         #endif
    419                     else if (s->length == 0x00006868)
    420                         newformat += _T("hh");
    421                 }
    422                 else
    423                 {
    424                     newformat += (char) s->length;
    425                 }
    426             }
    427 
    428             newformat += s->type;
    429         }
    430         else
    431         {
    432             FormatString* s = static_cast<FormatString*>(*it);
    433             newformat += s->text;
    434         }
    435     }
    436 
    437 
    438 /*
    439     varargs on x86:
    440 
    441     All types are padded to 4 bytes, so size-in-stack == _INTSIZEOF(type).
    442     No special alignment is required.
    443 
    444     first+_INTSIZEOF(first) == first item in stack
    445 
    446     Keep adding _INTSIZEOF(item) to get the next item
    447 */
    448 
    449 // Because of those dangerous assumptions about varargs:
    450 #if !ARCH_IA32
    451 #error SLIGHTLY FATAL ERROR: Only x86 is supported!
    452 #endif
    453 
    454     // Highly efficient buffer to store the rearranged copy of the stack
    455     std::string newstack;
    456 
    457     std::vector< std::pair<char*, char*> > stackitems;
    458 
    459     va_list arglist = argptr;
    460     //va_start(arglist, format);
    461 
    462     const u8* newstackptr;
    463 
    464     if (varsizes.size())
    465     {
    466 
    467         for (size_t i = 1; i < varsizes.size(); ++i)
    468         {
    469             if (varsizes[i] <= 0)
    470             {
    471                 DEBUG_WARN_ERR(ERR::LOGIC); // Invalid variable type somewhere - make sure all variable things are positional and defined
    472                 return -1;
    473             }
    474 
    475             // Based on _INTSIZEOF in stdarg.h:
    476             // (Warning - slightly non-portable. But we use gcc's default printf
    477             // when portability matters.)
    478             #define INTSIZE(n)   ( (n + sizeof(int) - 1) & ~(sizeof(int) - 1) )
    479 
    480             size_t size = INTSIZE(varsizes[i]);
    481             stackitems.push_back( std::pair<char*, char*>( arglist, arglist+size ));
    482             arglist += size;
    483         }
    484 
    485 
    486         for (ChunkIt it = specs.begin(); it != specs.end(); ++it)
    487         {
    488             FormatChunk* chunk = *it;
    489             if (chunk->ChunkType() == 0)
    490             {
    491                 FormatVariable* s = static_cast<FormatVariable*>(chunk);
    492                 if (s->position <= 0)
    493                 {
    494                     DEBUG_WARN_ERR(ERR::LOGIC); // Invalid use of positional elements - make sure all variable things are positional and defined
    495                     return -1;
    496                 }
    497                 newstack += std::string( stackitems[s->position-1].first, stackitems[s->position-1].second );
    498             }
    499         }
    500        
    501         newstackptr = (const u8*)newstack.c_str();
    502     }
    503     else
    504     {
    505         newstackptr = (const u8*)arglist;
    506     }
    507 
    508     for (ChunkIt it = specs.begin(); it != specs.end(); ++it)
    509         if ((*it)->ChunkType() == 0)
    510             delete static_cast<FormatVariable*>(*it);
    511         else
    512             delete static_cast<FormatString*>(*it);
    513 
    514     int ret = _vsntprintf(buffer, count, newformat.c_str(), (va_list)newstackptr);
    515 
    516     // For consistency with GCC's vsnprintf, make sure the buffer is null-terminated
    517     // and return an error if that truncates the output
    518     if(count > 0)
    519         buffer[count-1] = '\0';
    520     if (ret == (int)count)
    521         return -1;
    522 
    523     return ret;
    524 }
    525 
    526 #endif
  • source/lib/sysdep/sysdep.h

    diff --git a/source/lib/sysdep/sysdep.h b/source/lib/sysdep/sysdep.h
    index bbb032d..2517309 100644
    a b  
    3030#include "lib/debug.h"  // ErrorReactionInternal
    3131#include "lib/os_path.h"
    3232
    33 #include <cstdarg>  // needed for sys_vswprintf
    34 
    3533
    3634//
    3735// output
    LIB_API bool sys_IsDebuggerPresent();  
    8179LIB_API std::wstring sys_WideFromArgv(const char* argv_i);
    8280
    8381/**
    84  * sys_vswprintf: doesn't quite follow the standard for vswprintf, but works
    85  * better across compilers:
    86  * - handles positional parameters and %lld
    87  * - always null-terminates the buffer, if count > 0
    88  * - returns -1 on overflow (if the output string (including null) does not fit in the buffer)
    89  **/
    90 extern int sys_vswprintf(wchar_t* buffer, size_t count, const wchar_t* format, va_list argptr);
    91 
    92 /**
    9382 * describe the current OS error state.
    9483 *
    9584 * @param err: if not 0, use that as the error code to translate; otherwise,
  • deleted file source/lib/sysdep/tests/test_printf.h

    diff --git a/source/lib/sysdep/tests/test_printf.h b/source/lib/sysdep/tests/test_printf.h
    deleted file mode 100644
    index 341a81f..0000000
    + -  
    1 /* Copyright (c) 2010 Wildfire Games
    2  *
    3  * Permission is hereby granted, free of charge, to any person obtaining
    4  * a copy of this software and associated documentation files (the
    5  * "Software"), to deal in the Software without restriction, including
    6  * without limitation the rights to use, copy, modify, merge, publish,
    7  * distribute, sublicense, and/or sell copies of the Software, and to
    8  * permit persons to whom the Software is furnished to do so, subject to
    9  * the following conditions:
    10  *
    11  * The above copyright notice and this permission notice shall be included
    12  * in all copies or substantial portions of the Software.
    13  *
    14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    19  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    21  */
    22 
    23 #include "lib/self_test.h"
    24 
    25 #include "lib/sysdep/sysdep.h"
    26 
    27 class TestPrintf : public CxxTest::TestSuite
    28 {
    29     // Split some bits into separate functions, so we can get
    30     // a legitimate va_list to pass to sys_vswprintf:
    31 
    32     void _test_truncate(int buffer_size, const wchar_t* expected_output, int expected_return, /* wchar_t* input_string */...)
    33     {
    34         wchar_t buf[17] = L"................"; // fill with dots so null-termination is made obvious
    35 
    36         va_list ap;
    37         va_start(ap, expected_return);
    38 
    39         int ret = sys_vswprintf(buf, buffer_size, L"%ls", ap);
    40 
    41         TS_ASSERT_WSTR_EQUALS(buf, expected_output);
    42         TS_ASSERT_EQUALS(ret, expected_return);
    43 
    44         std::wstring past_buffer(buf + buffer_size);
    45         TS_ASSERT(past_buffer.find_first_not_of('.') == past_buffer.npos);
    46 
    47         va_end(ap);
    48     }
    49 
    50     void _test_sprintf(const wchar_t* expected_output, const wchar_t* format, ...)
    51     {
    52         wchar_t buf[256];
    53 
    54         va_list ap;
    55         va_start(ap, format);
    56 
    57         sys_vswprintf(buf, ARRAY_SIZE(buf), format, ap);
    58         TS_ASSERT_WSTR_EQUALS(buf, expected_output);
    59 
    60         va_end(ap);
    61     }
    62 
    63 public:
    64     void test_truncate()
    65     {
    66         _test_truncate(0, L"................", -1, L"1234");
    67         _test_truncate(1, L"",                 -1, L"1234");
    68 
    69         _test_truncate(8, L"1234",     4, L"1234");
    70         _test_truncate(8, L"1234567",  7, L"1234567");
    71         _test_truncate(8, L"1234567", -1, L"12345678");
    72         _test_truncate(8, L"1234567", -1, L"123456789");
    73         _test_truncate(8, L"1234567", -1, L"123456789abcdef");
    74     }
    75 
    76     void test_lld()
    77     {
    78         i64 z = 0;
    79         i64 n = 65536;
    80         _test_sprintf(L"0", L"%lld", z);
    81         _test_sprintf(L"65536", L"%lld", n);
    82         _test_sprintf(L"4294967296", L"%lld", n*n);
    83         _test_sprintf(L"281474976710656", L"%lld", n*n*n);
    84         _test_sprintf(L"-281474976710656", L"%lld", -n*n*n);
    85         _test_sprintf(L"123 456 281474976710656 789", L"%d %d %lld %d", 123, 456, n*n*n, 789);
    86     }
    87 
    88     void test_pos()
    89     {
    90         _test_sprintf(L"a b", L"%1$c %2$c", 'a', 'b');
    91         _test_sprintf(L"b a", L"%2$c %1$c", 'a', 'b');
    92     }
    93 
    94     void test_pos_lld()
    95     {
    96         _test_sprintf(L"1 2 3", L"%1$d %2$lld %3$d", 1, (i64)2, 3);
    97         _test_sprintf(L"2 1 3", L"%2$lld %1$d %3$d", 1, (i64)2, 3);
    98     }
    99 };
  • source/lib/tests/test_secure_crt.h

    diff --git a/source/lib/tests/test_secure_crt.h b/source/lib/tests/test_secure_crt.h
    index b52480d..422bea1 100644
    a b class TestString_s : public CxxTest::TestSuite  
    8181    const char* const s1;
    8282    const char* const s5;
    8383    const char* const s10;
     84    const wchar_t* const ws10;
    8485
    8586    char d1[1];
    8687    char d2[2];
    class TestString_s : public CxxTest::TestSuite  
    8889    char d5[5];
    8990    char d6[6];
    9091    char d10[10];
     92    wchar_t wd10[10];
    9193    char d11[11];
    9294
    9395    char no_null[7];
    class TestString_s : public CxxTest::TestSuite  
    157159
    158160public:
    159161    TestString_s()
    160         : s0(""), s1("a"), s5("abcde"), s10("abcdefghij")
     162        : s0(""), s1("a"), s5("abcde"), s10("abcdefghij"), ws10(L"abcdefghij")
    161163    {
    162164        const char no_null_tmp[] = { 'n','o','_','n','u','l','l'};
    163165        memcpy(no_null, no_null_tmp, sizeof(no_null));
    public:  
    303305        if (dst) TS_ASSERT_STR_EQUALS(dst, expected_dst);
    304306    }
    305307
     308    static void TEST_WPRINTF(wchar_t* dst, size_t max_dst_chars, const wchar_t* dst_val,
     309        int expected_ret, const wchar_t* expected_dst, const wchar_t* fmt, ...)
     310    {
     311        if (dst) wcscpy(dst, dst_val);
     312        va_list ap;
     313        va_start(ap, fmt);
     314        int ret = vswprintf_s(dst, max_dst_chars, fmt, ap);
     315        va_end(ap);
     316        TS_ASSERT_EQUALS(ret, expected_ret);
     317        if (dst) TS_ASSERT_WSTR_EQUALS(dst, expected_dst);
     318    }
     319
    306320    void test_printf()
    307321    {
    308322        TEST_PRINTF(d10,10, s10, 4, "1234", "%d", 1234);
    public:  
    315329        TEST_PRINTF(NULL,0, NULL, -1, "", "%d", 1234);
    316330        TEST_PRINTF(d10,10, s10, -1, "abcdefghij", NULL);
    317331    }
     332
     333    void test_wprintf()
     334    {
     335        TEST_WPRINTF(wd10,10, ws10, 4, L"1234", L"%d", 1234);
     336        TEST_WPRINTF(wd10,5, ws10, 4, L"1234", L"%d", 1234);
     337
     338        SuppressErrors suppress;
     339        TEST_WPRINTF(wd10,4, ws10, -1, L"", L"%d", 1234);
     340        TEST_WPRINTF(wd10,3, ws10, -1, L"", L"%d", 1234);
     341        TEST_WPRINTF(wd10,0, ws10, -1, L"abcdefghij", L"%d", 1234);
     342        TEST_WPRINTF(NULL,0, NULL, -1, L"", L"%d", 1234);
     343        TEST_WPRINTF(wd10,10, ws10, -1, L"abcdefghij", NULL);
     344    }
    318345};
  • source/lobby/XmppClient.cpp

    diff --git a/source/lobby/XmppClient.cpp b/source/lobby/XmppClient.cpp
    index 4b454e0..26c8c2e 100644
    a b bool XmppClient::handleIq(const glooxwrapper::IQ& iq)  
    749749    {
    750750        CreateSimpleMessage("system", g_L10n.Translate("unknown subtype (see logs)"), "error");
    751751        std::string tag = tag_name(iq);
    752         LOGMESSAGE(L"unknown subtype '%hs'", tag.c_str());
     752        LOGMESSAGE("unknown subtype '%s'", tag.c_str());
    753753    }
    754754
    755755    return true;
    void XmppClient::SetPresence(const std::string& presence)  
    896896    else IF("offline", Unavailable);
    897897    // The others are not to be set
    898898#undef IF
    899     else LOGERROR(L"Unknown presence '%hs'", presence.c_str());
     899    else LOGERROR("Unknown presence '%s'", presence.c_str());
    900900}
    901901
    902902/**
    void XmppClient::GetPresenceString(const gloox::Presence::PresenceType p, std::s  
    952952    CASE(Error, "error");
    953953    CASE(Invalid, "invalid");
    954954    default:
    955         LOGERROR(L"Unknown presence type '%d'", (int)p);
     955        LOGERROR("Unknown presence type '%d'", (int)p);
    956956        break;
    957957#undef CASE
    958958    }
    void XmppClient::GetRoleString(const gloox::MUCRoomRole r, std::string& role) co  
    975975    CASE(RoleModerator, "moderator");
    976976    CASE(RoleInvalid, "invalid");
    977977    default:
    978         LOGERROR(L"Unknown role type '%d'", (int)r);
     978        LOGERROR("Unknown role type '%d'", (int)r);
    979979        break;
    980980#undef CASE
    981981    }
  • source/main.cpp

    diff --git a/source/main.cpp b/source/main.cpp
    index 4d90e76..051e2f9 100644
    a b static InReaction MainInputHandler(const SDL_Event_* ev)  
    159159            // Fullscreen toggling is broken on OS X w/ SDL 1.2, see http://trac.wildfiregames.com/ticket/741
    160160            g_VideoMode.ToggleFullscreen();
    161161#else
    162             LOGWARNING(L"Toggling fullscreen and resizing are disabled on OS X due to a known bug. Please use the config file to change display settings.");
     162            LOGWARNING("Toggling fullscreen and resizing are disabled on OS X due to a known bug. Please use the config file to change display settings.");
    163163#endif
    164164            return IN_HANDLED;
    165165        }
  • source/network/NetClient.cpp

    diff --git a/source/network/NetClient.cpp b/source/network/NetClient.cpp
    index 8062cc8..fec7a80 100644
    a b bool CNetClient::HandleMessage(CNetMessage* message)  
    304304
    305305        std::stringstream stream;
    306306
    307         LOGMESSAGERENDER(L"Serializing game at turn %u for rejoining player", m_ClientTurnManager->GetCurrentTurn());
     307        LOGMESSAGERENDER("Serializing game at turn %u for rejoining player", m_ClientTurnManager->GetCurrentTurn());
    308308        u32 turn = to_le32(m_ClientTurnManager->GetCurrentTurn());
    309309        stream.write((char*)&turn, sizeof(turn));
    310310
    bool CNetClient::HandleMessage(CNetMessage* message)  
    324324    // Update FSM
    325325    bool ok = Update(message->GetType(), message);
    326326    if (!ok)
    327         LOGERROR(L"Net client: Error running FSM update (type=%d state=%d)", (int)message->GetType(), (int)GetCurrState());
     327        LOGERROR("Net client: Error running FSM update (type=%d state=%d)", (int)message->GetType(), (int)GetCurrState());
    328328    return ok;
    329329}
    330330
    void CNetClient::LoadFinished()  
    347347        stream.read((char*)&turn, sizeof(turn));
    348348        turn = to_le32(turn);
    349349
    350         LOGMESSAGE(L"Rejoining client deserializing state at turn %u\n", turn);
     350        LOGMESSAGE("Rejoining client deserializing state at turn %u\n", turn);
    351351
    352352        bool ok = m_Game->GetSimulation2()->DeserializeState(stream);
    353353        ENSURE(ok);
    bool CNetClient::OnAuthenticate(void* context, CFsmEvent* event)  
    428428
    429429    CAuthenticateResultMessage* message = (CAuthenticateResultMessage*)event->GetParamRef();
    430430
    431     LOGMESSAGE(L"Net: Authentication result: host=%u, %ls", message->m_HostID, message->m_Message.c_str());
     431    LOGMESSAGE("Net: Authentication result: host=%u, %s", message->m_HostID, utf8_from_wstring(message->m_Message));
    432432
    433433    bool  isRejoining = (message->m_Code == ARC_OK_REJOINING);
    434434
  • source/network/NetFileTransfer.cpp

    diff --git a/source/network/NetFileTransfer.cpp b/source/network/NetFileTransfer.cpp
    index 02805e3..1bf4da9 100644
    a b Status CNetFileTransferer::HandleMessageReceive(const CNetMessage* message)  
    1515
    1616        if (m_FileReceiveTasks.find(respMessage->m_RequestID) == m_FileReceiveTasks.end())
    1717        {
    18             LOGERROR(L"Net transfer: Unsolicited file transfer response (id=%d)", (int)respMessage->m_RequestID);
     18            LOGERROR("Net transfer: Unsolicited file transfer response (id=%d)", (int)respMessage->m_RequestID);
    1919            return ERR::FAIL;
    2020        }
    2121
    2222        if (respMessage->m_Length == 0 || respMessage->m_Length > MAX_FILE_TRANSFER_SIZE)
    2323        {
    24             LOGERROR(L"Net transfer: Invalid size for file transfer response (length=%d)", (int)respMessage->m_Length);
     24            LOGERROR("Net transfer: Invalid size for file transfer response (length=%d)", (int)respMessage->m_Length);
    2525            return ERR::FAIL;
    2626        }
    2727
    Status CNetFileTransferer::HandleMessageReceive(const CNetMessage* message)  
    3030        task->m_Length = respMessage->m_Length;
    3131        task->m_Buffer.reserve(respMessage->m_Length);
    3232
    33         LOGMESSAGERENDER(L"Downloading data over network (%d KB) - please wait...", (int)(task->m_Length/1024));
     33        LOGMESSAGERENDER("Downloading data over network (%d KB) - please wait...", (int)(task->m_Length/1024));
    3434        m_LastProgressReportTime = timer_Time();
    3535
    3636        return INFO::OK;
    Status CNetFileTransferer::HandleMessageReceive(const CNetMessage* message)  
    4141
    4242        if (m_FileReceiveTasks.find(dataMessage->m_RequestID) == m_FileReceiveTasks.end())
    4343        {
    44             LOGERROR(L"Net transfer: Unsolicited file transfer data (id=%d)", (int)dataMessage->m_RequestID);
     44            LOGERROR("Net transfer: Unsolicited file transfer data (id=%d)", (int)dataMessage->m_RequestID);
    4545            return ERR::FAIL;
    4646        }
    4747
    Status CNetFileTransferer::HandleMessageReceive(const CNetMessage* message)  
    5151
    5252        if (task->m_Buffer.size() > task->m_Length)
    5353        {
    54             LOGERROR(L"Net transfer: Invalid size for file transfer data (length=%d actual=%d)", (int)task->m_Length, (int)task->m_Buffer.size());
     54            LOGERROR("Net transfer: Invalid size for file transfer data (length=%d actual=%d)", (int)task->m_Length, (int)task->m_Buffer.size());
    5555            return ERR::FAIL;
    5656        }
    5757
    Status CNetFileTransferer::HandleMessageReceive(const CNetMessage* message)  
    6262
    6363        if (task->m_Buffer.size() == task->m_Length)
    6464        {
    65             LOGMESSAGERENDER(L"Download completed");
     65            LOGMESSAGERENDER("Download completed");
    6666
    6767            task->OnComplete();
    6868            m_FileReceiveTasks.erase(dataMessage->m_RequestID);
    Status CNetFileTransferer::HandleMessageReceive(const CNetMessage* message)  
    7575        double t = timer_Time();
    7676        if (t > m_LastProgressReportTime + 0.5)
    7777        {
    78             LOGMESSAGERENDER(L"Downloading data: %.1f%% of %d KB", 100.f*task->m_Buffer.size()/task->m_Length, (int)(task->m_Length/1024));
     78            LOGMESSAGERENDER("Downloading data: %.1f%% of %d KB", 100.f*task->m_Buffer.size()/task->m_Length, (int)(task->m_Length/1024));
    7979            m_LastProgressReportTime = t;
    8080        }
    8181
    Status CNetFileTransferer::HandleMessageReceive(const CNetMessage* message)  
    8787
    8888        if (m_FileSendTasks.find(ackMessage->m_RequestID) == m_FileSendTasks.end())
    8989        {
    90             LOGERROR(L"Net transfer: Unsolicited file transfer ack (id=%d)", (int)ackMessage->m_RequestID);
     90            LOGERROR("Net transfer: Unsolicited file transfer ack (id=%d)", (int)ackMessage->m_RequestID);
    9191            return ERR::FAIL;
    9292        }
    9393
    Status CNetFileTransferer::HandleMessageReceive(const CNetMessage* message)  
    9595
    9696        if (ackMessage->m_NumPackets > task.packetsInFlight)
    9797        {
    98             LOGERROR(L"Net transfer: Invalid num packets for file transfer ack (num=%d inflight=%d)",
     98            LOGERROR("Net transfer: Invalid num packets for file transfer ack (num=%d inflight=%d)",
    9999                (int)ackMessage->m_NumPackets, (int)task.packetsInFlight);
    100100            return ERR::FAIL;
    101101        }
  • source/network/NetHost.cpp

    diff --git a/source/network/NetHost.cpp b/source/network/NetHost.cpp
    index 7d0d682..e81a4ce 100644
    a b bool CNetHost::SendMessage(const CNetMessage* message, ENetPeer* peer, const cha  
    2929    if (!packet)
    3030        return false;
    3131
    32     LOGMESSAGE(L"Net: Sending message %hs of size %lu to %hs", message->ToString().c_str(), (unsigned long)packet->dataLength, peerName);
     32    LOGMESSAGE("Net: Sending message %s of size %lu to %s", message->ToString().c_str(), (unsigned long)packet->dataLength, peerName);
    3333
    3434    // Let ENet send the message to peer
    3535    if (enet_peer_send(peer, DEFAULT_CHANNEL, packet) < 0)
    3636    {
    37         LOGERROR(L"Net: Failed to send packet to peer");
     37        LOGERROR("Net: Failed to send packet to peer");
    3838        return false;
    3939    }
    4040
    ENetPacket* CNetHost::CreatePacket(const CNetMessage* message)  
    6262    // Create a reliable packet
    6363    ENetPacket* packet = enet_packet_create(&buffer[0], size, ENET_PACKET_FLAG_RELIABLE);
    6464    if (!packet)
    65         LOGERROR(L"Net: Failed to construct packet");
     65        LOGERROR("Net: Failed to construct packet");
    6666
    6767    return packet;
    6868}
  • source/network/NetMessage.cpp

    diff --git a/source/network/NetMessage.cpp b/source/network/NetMessage.cpp
    index d2c3be2..daa892c 100644
    a b const u8* CNetMessage::Deserialize(const u8* pStart, const u8* pEnd)  
    5454{
    5555    if (pStart + 3 > pEnd)
    5656    {
    57         LOGERROR(L"CNetMessage: Corrupt packet (smaller than header)");
     57        LOGERROR("CNetMessage: Corrupt packet (smaller than header)");
    5858        return NULL;
    5959    }
    6060
    const u8* CNetMessage::Deserialize(const u8* pStart, const u8* pEnd)  
    6868
    6969    if (pStart + size != pEnd)
    7070    {
    71         LOGERROR(L"CNetMessage: Corrupt packet (incorrect size)");
     71        LOGERROR("CNetMessage: Corrupt packet (incorrect size)");
    7272        return NULL;
    7373    }
    7474
    CNetMessage* CNetMessageFactory::CreateMessage(const void* pData,  
    184184        break;
    185185
    186186    default:
    187         LOGERROR(L"CNetMessageFactory::CreateMessage(): Unknown message type '%d' received", header.GetType());
     187        LOGERROR("CNetMessageFactory::CreateMessage(): Unknown message type '%d' received", header.GetType());
    188188        break;
    189189    }
    190190
  • source/network/NetServer.cpp

    diff --git a/source/network/NetServer.cpp b/source/network/NetServer.cpp
    index bcf904d..1a8187a 100644
    a b public:  
    9494
    9595        if (!session)
    9696        {
    97             LOGMESSAGE(L"Net server: rejoining client disconnected before we sent to it");
     97            LOGMESSAGE("Net server: rejoining client disconnected before we sent to it");
    9898            return;
    9999        }
    100100
    bool CNetServerWorker::SetupConnection()  
    177177    m_Host = enet_host_create(&addr, MAX_CLIENTS, CHANNEL_COUNT, 0, 0);
    178178    if (!m_Host)
    179179    {
    180         LOGERROR(L"Net server: enet_host_create failed");
     180        LOGERROR("Net server: enet_host_create failed");
    181181        return false;
    182182    }
    183183
    void* CNetServerWorker::SetupUPnP(void*)  
    224224    std::string rootDescURL;
    225225    CFG_GET_VAL("network.upnprootdescurl", rootDescURL);
    226226    if (!rootDescURL.empty())
    227         LOGMESSAGE(L"Net server: attempting to use cached root descriptor URL: %hs", rootDescURL.c_str());
     227        LOGMESSAGE("Net server: attempting to use cached root descriptor URL: %s", rootDescURL.c_str());
    228228
    229229    int ret = 0;
    230230    bool allocatedUrls = false;
    void* CNetServerWorker::SetupUPnP(void*)  
    232232    // Try a cached URL first
    233233    if (!rootDescURL.empty() && UPNP_GetIGDFromUrl(rootDescURL.c_str(), &urls, &data, internalIPAddress, sizeof(internalIPAddress)))
    234234    {
    235         LOGMESSAGE(L"Net server: using cached IGD = %hs", urls.controlURL);
     235        LOGMESSAGE("Net server: using cached IGD = %s", urls.controlURL);
    236236        ret = 1;
    237237    }
    238238    // No cached URL, or it did not respond. Try getting a valid UPnP device for 10 seconds.
    void* CNetServerWorker::SetupUPnP(void*)  
    243243    }
    244244    else
    245245    {
    246         LOGMESSAGE(L"Net server: upnpDiscover failed and no working cached URL.");
     246        LOGMESSAGE("Net server: upnpDiscover failed and no working cached URL.");
    247247        return NULL;
    248248    }
    249249
    250250    switch (ret)
    251251    {
    252252    case 0:
    253         LOGMESSAGE(L"Net server: No IGD found");
     253        LOGMESSAGE("Net server: No IGD found");
    254254        break;
    255255    case 1:
    256         LOGMESSAGE(L"Net server: found valid IGD = %hs", urls.controlURL);
     256        LOGMESSAGE("Net server: found valid IGD = %s", urls.controlURL);
    257257        break;
    258258    case 2:
    259         LOGMESSAGE(L"Net server: found a valid, not connected IGD = %hs, will try to continue anyway", urls.controlURL);
     259        LOGMESSAGE("Net server: found a valid, not connected IGD = %s, will try to continue anyway", urls.controlURL);
    260260        break;
    261261    case 3:
    262         LOGMESSAGE(L"Net server: found a UPnP device unrecognized as IGD = %hs, will try to continue anyway", urls.controlURL);
     262        LOGMESSAGE("Net server: found a UPnP device unrecognized as IGD = %s, will try to continue anyway", urls.controlURL);
    263263        break;
    264264    default:
    265265        debug_warn(L"Unrecognized return value from UPNP_GetValidIGD");
    void* CNetServerWorker::SetupUPnP(void*)  
    269269    ret = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
    270270    if (ret != UPNPCOMMAND_SUCCESS)
    271271    {
    272         LOGMESSAGE(L"Net server: GetExternalIPAddress failed with code %d (%hs)", ret, strupnperror(ret));
     272        LOGMESSAGE("Net server: GetExternalIPAddress failed with code %d (%s)", ret, strupnperror(ret));
    273273        return NULL;
    274274    }
    275     LOGMESSAGE(L"Net server: ExternalIPAddress = %hs", externalIPAddress);
     275    LOGMESSAGE("Net server: ExternalIPAddress = %s", externalIPAddress);
    276276
    277277    // Try to setup port forwarding.
    278278    ret = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, psPort, psPort,
    279279                            internalIPAddress, description, protocall, 0, leaseDuration);
    280280    if (ret != UPNPCOMMAND_SUCCESS)
    281281    {
    282         LOGMESSAGE(L"Net server: AddPortMapping(%hs, %hs, %hs) failed with code %d (%hs)",
     282        LOGMESSAGE("Net server: AddPortMapping(%s, %s, %s) failed with code %d (%s)",
    283283               psPort, psPort, internalIPAddress, ret, strupnperror(ret));
    284284        return NULL;
    285285    }
    void* CNetServerWorker::SetupUPnP(void*)  
    296296
    297297    if (ret != UPNPCOMMAND_SUCCESS)
    298298    {
    299         LOGMESSAGE(L"Net server: GetSpecificPortMappingEntry() failed with code %d (%hs)", ret, strupnperror(ret));
     299        LOGMESSAGE("Net server: GetSpecificPortMappingEntry() failed with code %d (%s)", ret, strupnperror(ret));
    300300        return NULL;
    301301    }
    302302
    303     LOGMESSAGE(L"Net server: External %hs:%hs %hs is redirected to internal %hs:%hs (duration=%hs)",
     303    LOGMESSAGE("Net server: External %s:%s %s is redirected to internal %s:%s (duration=%s)",
    304304                   externalIPAddress, psPort, protocall, intClient, intPort, duration);
    305305
    306306    // Cache root descriptor URL to try to avoid discovery next time.
    307307    g_ConfigDB.SetValueString(CFG_USER, "network.upnprootdescurl", urls.controlURL);
    308308    g_ConfigDB.WriteFile(CFG_USER);
    309     LOGMESSAGE(L"Net server: cached UPnP root descriptor URL as %hs", urls.controlURL);
     309    LOGMESSAGE("Net server: cached UPnP root descriptor URL as %s", urls.controlURL);
    310310
    311311    // Make sure everything is properly freed.
    312312    if (allocatedUrls)
    bool CNetServerWorker::RunStep()  
    451451    int status = enet_host_service(m_Host, &event, HOST_SERVICE_TIMEOUT);
    452452    if (status < 0)
    453453    {
    454         LOGERROR(L"CNetServerWorker: enet_host_service failed (%d)", status);
     454        LOGERROR("CNetServerWorker: enet_host_service failed (%d)", status);
    455455        // TODO: notify game that the server has shut down
    456456        return false;
    457457    }
    bool CNetServerWorker::RunStep()  
    471471        // Report the client address
    472472        char hostname[256] = "(error)";
    473473        enet_address_get_host_ip(&event.peer->address, hostname, ARRAY_SIZE(hostname));
    474         LOGMESSAGE(L"Net server: Received connection from %hs:%u", hostname, (unsigned int)event.peer->address.port);
     474        LOGMESSAGE("Net server: Received connection from %s:%u", hostname, (unsigned int)event.peer->address.port);
    475475
    476476        // Set up a session object for this peer
    477477
    bool CNetServerWorker::RunStep()  
    496496        CNetServerSession* session = static_cast<CNetServerSession*>(event.peer->data);
    497497        if (session)
    498498        {
    499             LOGMESSAGE(L"Net server: Disconnected %hs", DebugName(session).c_str());
     499            LOGMESSAGE("Net server: Disconnected %s", DebugName(session).c_str());
    500500
    501501            // Remove the session first, so we won't send player-update messages to it
    502502            // when updating the FSM
    bool CNetServerWorker::RunStep()  
    522522            CNetMessage* msg = CNetMessageFactory::CreateMessage(event.packet->data, event.packet->dataLength, GetScriptInterface());
    523523            if (msg)
    524524            {
    525                 LOGMESSAGE(L"Net server: Received message %hs of size %lu from %hs", msg->ToString().c_str(), (unsigned long)msg->GetSerializedLength(), DebugName(session).c_str());
     525                LOGMESSAGE("Net server: Received message %s of size %lu from %s", msg->ToString().c_str(), (unsigned long)msg->GetSerializedLength(), DebugName(session).c_str());
    526526
    527527                HandleMessageReceive(msg, session);
    528528
    void CNetServerWorker::HandleMessageReceive(const CNetMessage* message, CNetServ  
    566566    // Update FSM
    567567    bool ok = session->Update(message->GetType(), (void*)message);
    568568    if (!ok)
    569         LOGERROR(L"Net server: Error running FSM update (type=%d state=%d)", (int)message->GetType(), (int)session->GetCurrState());
     569        LOGERROR("Net server: Error running FSM update (type=%d state=%d)", (int)message->GetType(), (int)session->GetCurrState());
    570570}
    571571
    572572void CNetServerWorker::SetupSession(CNetServerSession* session)
    bool CNetServerWorker::OnAuthenticate(void* context, CFsmEvent* event)  
    810810        // Players who weren't already in the game are not allowed to join now that it's started
    811811        if (!isRejoining)
    812812        {
    813             LOGMESSAGE(L"Refused connection after game start from not-previously-known user \"%ls\"", username.c_str());
     813            LOGMESSAGE("Refused connection after game start from not-previously-known user \"%s\"", utf8_from_wstring(username));
    814814            session->Disconnect(NDR_SERVER_ALREADY_IN_GAME);
    815815            return true;
    816816        }
  • source/network/NetSession.cpp

    diff --git a/source/network/NetSession.cpp b/source/network/NetSession.cpp
    index 6bdaa57..82fa031 100644
    a b void CNetClientSession::Poll()  
    112112            // Report the server address
    113113            char hostname[256] = "(error)";
    114114            enet_address_get_host_ip(&event.peer->address, hostname, ARRAY_SIZE(hostname));
    115             LOGMESSAGE(L"Net client: Connected to %hs:%u", hostname, (unsigned int)event.peer->address.port);
     115            LOGMESSAGE("Net client: Connected to %s:%u", hostname, (unsigned int)event.peer->address.port);
    116116
    117117            m_Client.HandleConnect();
    118118
    void CNetClientSession::Poll()  
    123123        {
    124124            ENSURE(event.peer == m_Server);
    125125
    126             LOGMESSAGE(L"Net client: Disconnected");
     126            LOGMESSAGE("Net client: Disconnected");
    127127            m_Client.HandleDisconnect(event.data);
    128128            return;
    129129        }
    void CNetClientSession::Poll()  
    133133            CNetMessage* msg = CNetMessageFactory::CreateMessage(event.packet->data, event.packet->dataLength, m_Client.GetScriptInterface());
    134134            if (msg)
    135135            {
    136                 LOGMESSAGE(L"Net client: Received message %hs of size %lu from server", msg->ToString().c_str(), (unsigned long)msg->GetSerializedLength());
     136                LOGMESSAGE("Net client: Received message %s of size %lu from server", msg->ToString().c_str(), (unsigned long)msg->GetSerializedLength());
    137137
    138138                m_Client.HandleMessage(msg);
    139139
  • source/network/NetTurnManager.cpp

    diff --git a/source/network/NetTurnManager.cpp b/source/network/NetTurnManager.cpp
    index 70059ec..575dca3 100644
    a b static std::wstring Hexify(const std::string& s)  
    5757    return str.str();
    5858}
    5959
     60static std::string Hexify8(const std::string& s)
     61{
     62    std::stringstream str;
     63    str << std::hex;
     64    for (size_t i = 0; i < s.size(); ++i)
     65        str << std::setfill('0') << std::setw(2) << (int)(unsigned char)s[i];
     66    return str.str();
     67}
     68
    6069CNetTurnManager::CNetTurnManager(CSimulation2& simulation, u32 defaultTurnLength, int clientId, IReplayLogger& replay) :
    6170    m_Simulation2(simulation), m_CurrentTurn(0), m_ReadyTurn(1), m_TurnLength(defaultTurnLength), m_DeltaSimTime(0),
    6271    m_PlayerId(-1), m_ClientId(clientId), m_HasSyncError(false), m_Replay(replay),
    void CNetTurnManager::OnSyncError(u32 turn, const std::string& expectedHash)  
    237246    m_Simulation2.DumpDebugState(file);
    238247    file.close();
    239248
    240     std::wstringstream msg;
    241     msg << L"Out of sync on turn " << turn << L": expected hash " << Hexify(expectedHash) << L"\n\n";
    242     msg << L"Current state: turn " << m_CurrentTurn << L", hash " << Hexify(hash) << L"\n\n";
    243     msg << L"Dumping current state to " << path;
     249    std::stringstream msg;
     250    msg << "Out of sync on turn " << turn << ": expected hash " << Hexify8(expectedHash) << "\n\n";
     251    msg << "Current state: turn " << m_CurrentTurn << ", hash " << Hexify8(hash) << "\n\n";
     252    msg << "Dumping current state to " << utf8_from_wstring(path.string());
    244253    if (g_GUI)
    245         g_GUI->DisplayMessageBox(600, 350, L"Sync error", msg.str());
     254        g_GUI->DisplayMessageBox(600, 350, L"Sync error", wstring_from_utf8(msg.str()));
    246255    else
    247         LOGERROR(L"%ls", msg.str().c_str());
     256        LOGERROR("%s", msg.str());
    248257}
    249258
    250259void CNetTurnManager::Interpolate(float simFrameLength, float realFrameLength)
    void CNetTurnManager::QuickSave()  
    327336    bool ok = m_Simulation2.SerializeState(stream);
    328337    if (!ok)
    329338    {
    330         LOGERROR(L"Failed to quicksave game");
     339        LOGERROR("Failed to quicksave game");
    331340        return;
    332341    }
    333342
    void CNetTurnManager::QuickSave()  
    337346    else
    338347        m_QuickSaveMetadata = std::string();
    339348
    340     LOGMESSAGERENDER(L"Quicksaved game");
     349    LOGMESSAGERENDER("Quicksaved game");
    341350
    342351}
    343352
    void CNetTurnManager::QuickLoad()  
    347356
    348357    if (m_QuickSaveState.empty())
    349358    {
    350         LOGERROR(L"Cannot quickload game - no game was quicksaved");
     359        LOGERROR("Cannot quickload game - no game was quicksaved");
    351360        return;
    352361    }
    353362
    void CNetTurnManager::QuickLoad()  
    355364    bool ok = m_Simulation2.DeserializeState(stream);
    356365    if (!ok)
    357366    {
    358         LOGERROR(L"Failed to quickload game");
     367        LOGERROR("Failed to quickload game");
    359368        return;
    360369    }
    361370
    362371    if (g_GUI && !m_QuickSaveMetadata.empty())
    363372        g_GUI->RestoreSavedGameData(m_QuickSaveMetadata);
    364373
    365     LOGMESSAGERENDER(L"Quickloaded game");
     374    LOGMESSAGERENDER("Quickloaded game");
    366375
    367376    // See RewindTimeWarp
    368377    ResetState(0, 1);
  • source/ps/CLogger.cpp

    diff --git a/source/ps/CLogger.cpp b/source/ps/CLogger.cpp
    index 1a68943..58cf7c2 100644
    a b  
    1 /* Copyright (C) 2012 Wildfire Games.
     1/* Copyright (C) 2015 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    2525#include "lib/ogl.h"
    2626#include "lib/timer.h"
    2727#include "lib/utf8.h"
    28 #include "lib/sysdep/sysdep.h"
    2928#include "ps/Profile.h"
    3029#include "renderer/Renderer.h"
    3130
    CLogger::~CLogger()  
    140139    }
    141140}
    142141
    143 static std::string ToHTML(const wchar_t* message)
     142static std::string ToHTML(const char* message)
    144143{
    145     Status err;
    146     std::string cmessage = utf8_from_wstring(message, &err);
     144    std::string cmessage = message;
    147145    boost::algorithm::replace_all(cmessage, "&", "&amp;");
    148146    boost::algorithm::replace_all(cmessage, "<", "&lt;");
    149147    return cmessage;
    150148}
    151149
    152 void CLogger::WriteMessage(const wchar_t* message, bool doRender = false)
     150void CLogger::WriteMessage(const char* message, bool doRender = false)
    153151{
    154152    std::string cmessage = ToHTML(message);
    155153
    void CLogger::WriteMessage(const wchar_t* message, bool doRender = false)  
    157155
    158156    ++m_NumberOfMessages;
    159157//  if (m_UseDebugPrintf)
    160 //      debug_printf(L"MESSAGE: %ls\n", message);
     158//      debug_printf(L"MESSAGE: %hs\n", message);
    161159
    162160    *m_MainLog << "<p>" << cmessage << "</p>\n";
    163161    m_MainLog->flush();
    164162   
    165163    if (doRender)
    166164    {
    167         if (g_Console) g_Console->InsertMessage(L"INFO: %ls", message);
     165        if (g_Console) g_Console->InsertMessage(L"INFO: %hs", message);
    168166
    169167        PushRenderMessage(Normal, message);
    170168    }
    171169}
    172170
    173 void CLogger::WriteError(const wchar_t* message)
     171void CLogger::WriteError(const char* message)
    174172{
    175173    std::string cmessage = ToHTML(message);
    176174
    void CLogger::WriteError(const wchar_t* message)  
    178176
    179177    ++m_NumberOfErrors;
    180178    if (m_UseDebugPrintf)
    181         debug_printf(L"ERROR: %ls\n", message);
     179        debug_printf(L"ERROR: %hs\n", message);
    182180
    183     if (g_Console) g_Console->InsertMessage(L"ERROR: %ls", message);
     181    if (g_Console) g_Console->InsertMessage(L"ERROR: %hs", message);
    184182    *m_InterestingLog << "<p class=\"error\">ERROR: " << cmessage << "</p>\n";
    185183    m_InterestingLog->flush();
    186184
    void CLogger::WriteError(const wchar_t* message)  
    190188    PushRenderMessage(Error, message);
    191189}
    192190
    193 void CLogger::WriteWarning(const wchar_t* message)
     191void CLogger::WriteWarning(const char* message)
    194192{
    195193    std::string cmessage = ToHTML(message);
    196194
    void CLogger::WriteWarning(const wchar_t* message)  
    198196
    199197    ++m_NumberOfWarnings;
    200198    if (m_UseDebugPrintf)
    201         debug_printf(L"WARNING: %ls\n", message);
     199        debug_printf(L"WARNING: %hs\n", message);
    202200
    203     if (g_Console) g_Console->InsertMessage(L"WARNING: %ls", message);
     201    if (g_Console) g_Console->InsertMessage(L"WARNING: %hs", message);
    204202    *m_InterestingLog << "<p class=\"warning\">WARNING: " << cmessage << "</p>\n";
    205203    m_InterestingLog->flush();
    206204
    void CLogger::WriteWarning(const wchar_t* message)  
    210208    PushRenderMessage(Warning, message);
    211209}
    212210
    213 void CLogger::LogMessage(const wchar_t* fmt, ...)
    214 {
    215     va_list argp;
    216     wchar_t buffer[BUFFER_SIZE] = {0};
    217    
    218     va_start(argp, fmt);
    219     if (sys_vswprintf(buffer, ARRAY_SIZE(buffer), fmt, argp) == -1)
    220     {
    221         // Buffer too small - ensure the string is nicely terminated
    222         wcscpy_s(buffer+ARRAY_SIZE(buffer)-4, 4, L"...");
    223     }
    224     va_end(argp);
    225 
    226     WriteMessage(buffer);
    227 }
    228 
    229 void CLogger::LogMessageRender(const wchar_t* fmt, ...)
    230 {
    231     va_list argp;
    232     wchar_t buffer[BUFFER_SIZE] = {0};
    233    
    234     va_start(argp, fmt);
    235     if (sys_vswprintf(buffer, ARRAY_SIZE(buffer), fmt, argp) == -1)
    236     {
    237         // Buffer too small - ensure the string is nicely terminated
    238         wcscpy_s(buffer+ARRAY_SIZE(buffer)-4, 4, L"...");
    239     }
    240     va_end(argp);
    241 
    242     WriteMessage(buffer, true);
    243 }
    244 
    245 void CLogger::LogWarning(const wchar_t* fmt, ...)
    246 {
    247     va_list argp;
    248     wchar_t buffer[BUFFER_SIZE] = {0};
    249    
    250     va_start(argp, fmt);
    251     if (sys_vswprintf(buffer, ARRAY_SIZE(buffer), fmt, argp) == -1)
    252     {
    253         // Buffer too small - ensure the string is nicely terminated
    254         wcscpy_s(buffer+ARRAY_SIZE(buffer)-4, 4, L"...");
    255     }
    256     va_end(argp);
    257 
    258     WriteWarning(buffer);
    259 }
    260 
    261 void CLogger::LogError(const wchar_t* fmt, ...)
    262 {
    263     va_list argp;
    264     wchar_t buffer[BUFFER_SIZE] = {0};
    265    
    266     va_start(argp, fmt);
    267     if (sys_vswprintf(buffer, ARRAY_SIZE(buffer), fmt, argp) == -1)
    268     {
    269         // Buffer too small - ensure the string is nicely terminated
    270         wcscpy_s(buffer+ARRAY_SIZE(buffer)-4, 4, L"...");
    271     }
    272     va_end(argp);
    273 
    274     WriteError(buffer);
    275 }
    276 
    277211void CLogger::Render()
    278212{
    279213    PROFILE3_GPU("logger");
    void CLogger::Render()  
    300234
    301235    for (std::deque<RenderedMessage>::iterator it = m_RenderMessages.begin(); it != m_RenderMessages.end(); ++it)
    302236    {
    303         const wchar_t* type;
     237        const char* type;
    304238        if (it->method == Normal)
    305239        {
    306             type = L"info";
     240            type = "info";
    307241            textRenderer.Color(0.0f, 0.8f, 0.0f);
    308242        }
    309243        else if (it->method == Warning)
    310244        {
    311             type = L"warning";
     245            type = "warning";
    312246            textRenderer.Color(1.0f, 1.0f, 0.0f);
    313247        }
    314248        else
    315249        {
    316             type = L"error";
     250            type = "error";
    317251            textRenderer.Color(1.0f, 0.0f, 0.0f);
    318252        }
    319253
    320254        CMatrix3D savedTransform = textRenderer.GetTransform();
    321255
    322         textRenderer.PrintfAdvance(L"[%8.3f] %ls: ", it->time, type);
     256        textRenderer.PrintfAdvance(L"[%8.3f] %hs: ", it->time, type);
    323257        // Display the actual message in white so it's more readable
    324258        textRenderer.Color(1.0f, 1.0f, 1.0f);
    325259        textRenderer.Put(0.0f, 0.0f, it->message.c_str());
    void CLogger::Render()  
    334268    textTech->EndPass();
    335269}
    336270
    337 void CLogger::PushRenderMessage(ELogMethod method, const wchar_t* message)
     271void CLogger::PushRenderMessage(ELogMethod method, const char* message)
    338272{
    339273    double now = timer_Time();
    340274
    341275    // Add each message line separately
    342     const wchar_t* pos = message;
    343     const wchar_t* eol;
    344     while ((eol = wcschr(pos, L'\n')) != NULL)
     276    const char* pos = message;
     277    const char* eol;
     278    while ((eol = strchr(pos, '\n')) != NULL)
    345279    {
    346280        if (eol != pos)
    347281        {
    348             RenderedMessage r = { method, now, std::wstring(pos, eol) };
     282            RenderedMessage r = { method, now, std::string(pos, eol) };
    349283            m_RenderMessages.push_back(r);
    350284        }
    351285        pos = eol + 1;
    352286    }
    353287    // Add the last line, if we didn't end on a \n
    354     if (*pos != L'\0')
     288    if (*pos != '\0')
    355289    {
    356         RenderedMessage r = { method, now, std::wstring(pos) };
     290        RenderedMessage r = { method, now, std::string(pos) };
    357291        m_RenderMessages.push_back(r);
    358292    }
    359293}
    TestLogger::~TestLogger()  
    398332    g_Logger = m_OldLogger;
    399333}
    400334
    401 std::wstring TestLogger::GetOutput()
     335std::string TestLogger::GetOutput()
    402336{
    403     Status err;
    404     return wstring_from_utf8(m_Stream.str(), &err);
     337    return m_Stream.str();
    405338}
    406339
    407340TestStdoutLogger::TestStdoutLogger()
  • source/ps/CLogger.h

    diff --git a/source/ps/CLogger.h b/source/ps/CLogger.h
    index 78e9ad8..ba23976 100644
    a b  
    1 /* Copyright (C) 2010 Wildfire Games.
     1/* Copyright (C) 2015 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    2424#include <sstream>
    2525
    2626#include "ps/ThreadUtil.h"
     27#include "third_party/cppformat/format.h"
    2728
    2829class CLogger;
    2930extern CLogger* g_Logger;
    3031
    3132
    32 #define LOGMESSAGE g_Logger->LogMessage
    33 #define LOGMESSAGERENDER g_Logger->LogMessageRender
    34 #define LOGWARNING g_Logger->LogWarning
    35 #define LOGERROR g_Logger->LogError
     33#define LOGMESSAGE(...)       g_Logger->WriteMessage(fmt::sprintf(__VA_ARGS__).c_str(), false)
     34#define LOGMESSAGERENDER(...) g_Logger->WriteMessage(fmt::sprintf(__VA_ARGS__).c_str(), true)
     35#define LOGWARNING(...)       g_Logger->WriteWarning(fmt::sprintf(__VA_ARGS__).c_str())
     36#define LOGERROR(...)         g_Logger->WriteError  (fmt::sprintf(__VA_ARGS__).c_str())
    3637
    3738/**
    3839 * Error/warning/message logging class.
    public:  
    6465
    6566    // Functions to write different message types (Errors and warnings are placed
    6667    // both in mainLog and intrestingLog.)
    67     void WriteMessage(const wchar_t* message, bool doRender);
    68     void WriteError  (const wchar_t* message);
    69     void WriteWarning(const wchar_t* message);
     68    void WriteMessage(const char* message, bool doRender);
     69    void WriteError  (const char* message);
     70    void WriteWarning(const char* message);
    7071   
    71     // Functions to write a message, warning or error to file.
    72     void LogMessage(const wchar_t* fmt, ...) WPRINTF_ARGS(2);
    73     void LogMessageRender(const wchar_t* fmt, ...) WPRINTF_ARGS(2);
    74     void LogWarning(const wchar_t* fmt, ...) WPRINTF_ARGS(2);
    75     void LogError(const wchar_t* fmt, ...) WPRINTF_ARGS(2);
    76 
    7772    // Render recent log messages onto the screen
    7873    void Render();
    7974   
    8075private:
    8176    void Init();
    8277
    83     void PushRenderMessage(ELogMethod method, const wchar_t* message);
     78    void PushRenderMessage(ELogMethod method, const char* message);
    8479
    8580    // Delete old timed-out entries from the list of text to render
    8681    void CleanupRenderQueue();
    private:  
    10499    {
    105100        ELogMethod method;
    106101        double time;
    107         std::wstring message;
     102        std::string message;
    108103    };
    109104    std::deque<RenderedMessage> m_RenderMessages;
    110105    double m_RenderLastEraseTime;
    class TestLogger  
    123118public:
    124119    TestLogger();
    125120    ~TestLogger();
    126     std::wstring GetOutput();
     121    std::string GetOutput();
    127122private:
    128123    CLogger* m_OldLogger;
    129124    std::stringstream m_Stream;
  • source/ps/CStrIntern.cpp

    diff --git a/source/ps/CStrIntern.cpp b/source/ps/CStrIntern.cpp
    index 53a5098..6692b35 100644
    a b public:  
    3030    CStrInternInternals(const char* str, size_t len)
    3131        : data(str, str+len), hash(fnv_hash(str, len))
    3232    {
    33 //      LOGWARNING(L"New interned string '%hs'", data.c_str());
     33//      LOGWARNING("New interned string '%s'", data.c_str());
    3434    }
    3535
    3636    bool operator==(const CStrInternInternals& b) const
  • source/ps/ConfigDB.cpp

    diff --git a/source/ps/ConfigDB.cpp b/source/ps/ConfigDB.cpp
    index 11ce79e..ab4dca3 100644
    a b bool CConfigDB::Reload(EConfigNamespace ns)  
    214214        // Handle missing files quietly
    215215        if (g_VFS->GetFileInfo(m_ConfigFile[ns], NULL) < 0)
    216216        {
    217             LOGMESSAGE(L"Cannot find config file \"%ls\" - ignoring", m_ConfigFile[ns].string().c_str());
     217            LOGMESSAGE("Cannot find config file \"%s\" - ignoring", m_ConfigFile[ns].string8());
    218218            return false;
    219219        }
    220220
    221         LOGMESSAGE(L"Loading config file \"%ls\"", m_ConfigFile[ns].string().c_str());
     221        LOGMESSAGE("Loading config file \"%s\"", m_ConfigFile[ns].string8());
    222222        Status ret = g_VFS->LoadFile(m_ConfigFile[ns], buffer, buflen);
    223223        if (ret != INFO::OK)
    224224        {
    225             LOGERROR(L"CConfigDB::Reload(): vfs_load for \"%ls\" failed: return was %lld", m_ConfigFile[ns].string().c_str(), (long long)ret);
     225            LOGERROR("CConfigDB::Reload(): vfs_load for \"%s\" failed: return was %lld", m_ConfigFile[ns].string8(), (long long)ret);
    226226            return false;
    227227        }
    228228    }
    bool CConfigDB::Reload(EConfigNamespace ns)  
    256256
    257257            if (pos == filebufend || *pos == '\n')
    258258            {
    259                 LOGERROR(L"Config header with missing close tag encountered on line %d in '%ls'", line, m_ConfigFile[ns].string().c_str());
     259                LOGERROR("Config header with missing close tag encountered on line %d in '%s'", line, m_ConfigFile[ns].string8());
    260260                header.clear();
    261261                ++line;
    262262                continue;
    263263            }
    264264
    265             LOGMESSAGE(L"Found config header '%hs'", header.c_str());
     265            LOGMESSAGE("Found config header '%s'", header.c_str());
    266266            header.push_back('.');
    267267            while (++pos < filebufend && *pos != '\n' && *pos != ';')
    268268                if (*pos != ' ' && *pos != '\r')
    269269                {
    270                     LOGERROR(L"Config settings on the same line as a header on line %d in '%ls'", line, m_ConfigFile[ns].string().c_str());
     270                    LOGERROR("Config settings on the same line as a header on line %d in '%s'", line, m_ConfigFile[ns].string8());
    271271                    break;
    272272                }
    273273            while (pos < filebufend && *pos != '\n')
    bool CConfigDB::Reload(EConfigNamespace ns)  
    288288                    {
    289289                        if (*pos == '\\' && ++pos == filebufend)
    290290                        {
    291                             LOGERROR(L"Escape character at end of input (line %d in '%ls')", line, m_ConfigFile[ns].string().c_str());
     291                            LOGERROR("Escape character at end of input (line %d in '%s')", line, m_ConfigFile[ns].string8());
    292292                            break;
    293293                        }
    294294
    bool CConfigDB::Reload(EConfigNamespace ns)  
    316316                }
    317317            }
    318318            if (quoted) // We ignore the invalid parameter
    319                 LOGERROR(L"Unmatched quote while parsing config file '%ls' on line %d", m_ConfigFile[ns].string().c_str(), line);
     319                LOGERROR("Unmatched quote while parsing config file '%s' on line %d", m_ConfigFile[ns].string8(), line);
    320320            else if (!value.empty())
    321321                values.push_back(value);
    322322            value.clear();
    bool CConfigDB::Reload(EConfigNamespace ns)  
    337337            CStr key(header + name);
    338338            newMap[key] = values;
    339339            if (key == "lobby.password")
    340                 LOGMESSAGE(L"Loaded config string \"%hs\"", key.c_str());
     340                LOGMESSAGE("Loaded config string \"%s\"", key);
    341341            else
    342342            {
    343343                std::string vals;
    344344                for (size_t i = 0; i < newMap[key].size() - 1; ++i)
    345345                    vals += "\"" + EscapeString(newMap[key][i]) + "\", ";
    346346                vals += "\"" + EscapeString(newMap[key][values.size()-1]) + "\"";
    347                 LOGMESSAGE(L"Loaded config string \"%hs\" = %hs", key.c_str(), vals.c_str());
     347                LOGMESSAGE("Loaded config string \"%s\" = %s", key, vals);
    348348            }
    349349        }
    350350        else if (!name.empty())
    351             LOGERROR(L"Encountered config setting '%hs' without value while parsing '%ls' on line %d", name.c_str(), m_ConfigFile[ns].string().c_str(), line);
     351            LOGERROR("Encountered config setting '%s' without value while parsing '%s' on line %d", name, m_ConfigFile[ns].string8(), line);
    352352
    353353        name.clear();
    354354        values.clear();
    bool CConfigDB::Reload(EConfigNamespace ns)  
    356356    }
    357357
    358358    if (!name.empty())
    359         LOGERROR(L"Config file does not have a new line after the last config setting '%hs'", name.c_str());
     359        LOGERROR("Config file does not have a new line after the last config setting '%s'", name);
    360360
    361361    m_Map[ns].swap(newMap);
    362362
    bool CConfigDB::WriteFile(EConfigNamespace ns, const VfsPath& path)  
    393393    Status ret = g_VFS->CreateFile(path, buf, len);
    394394    if (ret < 0)
    395395    {
    396         LOGERROR(L"CConfigDB::WriteFile(): CreateFile \"%ls\" failed (error: %d)", path.string().c_str(), (int)ret);
     396        LOGERROR("CConfigDB::WriteFile(): CreateFile \"%s\" failed (error: %d)", path.string8(), (int)ret);
    397397        return false;
    398398    }
    399399
  • source/ps/DllLoader.cpp

    diff --git a/source/ps/DllLoader.cpp b/source/ps/DllLoader.cpp
    index ad120fb..18151ad 100644
    a b void DllLoader::LogLoadError(const char* errors)  
    196196    switch (m_LoadErrorLogMethod)
    197197    {
    198198    case CLogger::Normal:
    199         LOGMESSAGE(L"DllLoader: %hs", errors);
     199        LOGMESSAGE("DllLoader: %s", errors);
    200200        break;
    201201    case CLogger::Warning:
    202         LOGWARNING(L"DllLoader: %hs", errors);
     202        LOGWARNING("DllLoader: %s", errors);
    203203        break;
    204204    case CLogger::Error:
    205         LOGERROR(L"DllLoader: %hs", errors);
     205        LOGERROR("DllLoader: %s", errors);
    206206        break;
    207207    }
    208208}
  • source/ps/FileIo.cpp

    diff --git a/source/ps/FileIo.cpp b/source/ps/FileIo.cpp
    index e06d339..f8c358e 100644
    a b void CFilePacker::Write(const VfsPath& filename)  
    6969    const Status st = g_VFS->CreateFile(filename, m_writeBuffer.Data(), m_writeBuffer.Size());
    7070    if (st < 0)
    7171    {
    72         LOGERROR(L"Failed to write file '%ls' with status '%lld'", filename.string().c_str(), (long long)st);
     72        LOGERROR("Failed to write file '%s' with status '%lld'", filename.string8(), (long long)st);
    7373        throw PSERROR_File_WriteFailed();
    7474    }
    7575}
  • source/ps/Filesystem.cpp

    diff --git a/source/ps/Filesystem.cpp b/source/ps/Filesystem.cpp
    index de0ba9e..be16108 100644
    a b PSRETURN CVFSFile::Load(const PIVFS& vfs, const VfsPath& filename, bool log /* =  
    124124    if (ret != INFO::OK)
    125125    {
    126126        if (log)
    127             LOGERROR(L"CVFSFile: file %ls couldn't be opened (vfs_load: %lld)", filename.string().c_str(), (long long)ret);
     127            LOGERROR("CVFSFile: file %s couldn't be opened (vfs_load: %lld)", filename.string8(), (long long)ret);
    128128        m_Buffer.reset();
    129129        m_BufferSize = 0;
    130130        return PSRETURN_CVFSFile_LoadFailed;
  • source/ps/GameSetup/Config.cpp

    diff --git a/source/ps/GameSetup/Config.cpp b/source/ps/GameSetup/Config.cpp
    index 0f18291..67fc7b2 100644
    a b static void LoadGlobals()  
    131131    CFG_GET_VAL("profiler2.script.enable", g_ScriptProfilingEnabled);
    132132
    133133    if (g_JSDebuggerEnabled)
    134         LOGERROR(L"JS debugger temporarily disabled during the SpiderMonkey upgrade (check trac ticket #2348 for details)");
     134        LOGERROR("JS debugger temporarily disabled during the SpiderMonkey upgrade (check trac ticket #2348 for details)");
    135135    // Script Debugging and profiling does not make sense together because of the hooks
    136136    // that reduce performance a lot - and it wasn't tested if it even works together.
    137137    if (g_JSDebuggerEnabled && g_ScriptProfilingEnabled)
    138         LOGERROR(L"Enabling both script profiling and script debugging is not supported!");
     138        LOGERROR("Enabling both script profiling and script debugging is not supported!");
    139139}
    140140
    141141
  • source/ps/GameSetup/GameSetup.cpp

    diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp
    index 3709648..44b166e 100644
    a b void Render()  
    293293#warning TODO: cursors for Android
    294294#else
    295295            if (cursor_draw(g_VFS, cursorName.c_str(), g_mouse_x, g_yres-g_mouse_y, forceGL) < 0)
    296                 LOGWARNING(L"Failed to draw cursor '%ls'", cursorName.c_str());
     296                LOGWARNING("Failed to draw cursor '%s'", utf8_from_wstring(cursorName));
    297297#endif
    298298
    299299#if CONFIG2_GLES
    static void InitSDL()  
    656656
    657657    if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_NOPARACHUTE) < 0)
    658658    {
    659         LOGERROR(L"SDL library initialization failed: %hs", SDL_GetError());
     659        LOGERROR("SDL library initialization failed: %s", SDL_GetError());
    660660        throw PSERROR_System_SDLInitFailed();
    661661    }
    662662    atexit(SDL_Quit);
    static void FixLocales()  
    814814    }
    815815    catch (std::runtime_error&)
    816816    {
    817         LOGWARNING(L"Invalid locale settings");
     817        LOGWARNING("Invalid locale settings");
    818818
    819819        for (size_t i = 0; i < ARRAY_SIZE(LocaleEnvVars); i++)
    820820        {
    821821            if (char* envval = getenv(LocaleEnvVars[i]))
    822                 LOGWARNING(L"  %hs=\"%hs\"", LocaleEnvVars[i], envval);
     822                LOGWARNING("  %s=\"%s\"", LocaleEnvVars[i], envval);
    823823            else
    824                 LOGWARNING(L"  %hs=\"(unset)\"", LocaleEnvVars[i]);
     824                LOGWARNING("  %s=\"(unset)\"", LocaleEnvVars[i]);
    825825        }
    826826
    827827        // We should set LC_ALL since it overrides LANG
    828828        if (setenv("LC_ALL", std::locale::classic().name().c_str(), 1))
    829829            debug_warn(L"Invalid locale settings, and unable to set LC_ALL env variable.");
    830830        else
    831             LOGWARNING(L"Setting LC_ALL env variable to: %hs", getenv("LC_ALL"));
     831            LOGWARNING("Setting LC_ALL env variable to: %s", getenv("LC_ALL"));
    832832    }
    833833}
    834834#else
    CStr8 LoadSettingsOfScenarioMap(const VfsPath &mapPath)  
    11321132
    11331133    if (INFO::OK != loadResult)
    11341134    {
    1135         LOGERROR(L"LoadSettingsOfScenarioMap: Unable to load map file '%ls'", mapPath.string().c_str());
     1135        LOGERROR("LoadSettingsOfScenarioMap: Unable to load map file '%s'", mapPath.string8());
    11361136        throw PSERROR_Game_World_MapLoadFailed("Unable to load map file, check the path for typos.");
    11371137    }
    11381138    XMBElement mapElement = mapFile.GetRoot();
    bool Autostart(const CmdLineArgs& args)  
    12461246        else
    12471247        {
    12481248            // Problem with JSON file
    1249             LOGERROR(L"Autostart: Error reading random map script '%ls'", scriptPath.c_str());
     1249            LOGERROR("Autostart: Error reading random map script '%s'", utf8_from_wstring(scriptPath));
    12501250            throw PSERROR_Game_World_MapLoadFailed("Error reading random map script.\nCheck application log for details.");
    12511251        }
    12521252
    bool Autostart(const CmdLineArgs& args)  
    13011301    }
    13021302    else
    13031303    {
    1304         LOGERROR(L"Autostart: Unrecognized map type '%ls'", mapDirectory.c_str());
     1304        LOGERROR("Autostart: Unrecognized map type '%s'", utf8_from_wstring(mapDirectory));
    13051305        throw PSERROR_Game_World_MapLoadFailed("Unrecognized map type.\nConsult readme.txt for the currently supported types.");
    13061306    }
    13071307    scriptInterface.SetProperty(attrs, "mapType", mapType);
    bool Autostart(const CmdLineArgs& args)  
    13361336                if (mapDirectory == L"scenarios" || mapDirectory == L"skirmishes")
    13371337                {
    13381338                    // playerID is certainly bigger than this map player number
    1339                     LOGWARNING(L"Autostart: Invalid player %d in autostart-ai option", playerID);
     1339                    LOGWARNING("Autostart: Invalid player %d in autostart-ai option", playerID);
    13401340                    continue;
    13411341                }
    13421342                scriptInterface.Eval("({})", &player);
    bool Autostart(const CmdLineArgs& args)  
    13631363                if (mapDirectory == L"scenarios" || mapDirectory == L"skirmishes")
    13641364                {
    13651365                    // playerID is certainly bigger than this map player number
    1366                     LOGWARNING(L"Autostart: Invalid player %d in autostart-aidiff option", playerID);
     1366                    LOGWARNING("Autostart: Invalid player %d in autostart-aidiff option", playerID);
    13671367                    continue;
    13681368                }
    13691369                scriptInterface.Eval("({})", &player);
    bool Autostart(const CmdLineArgs& args)  
    13911391                    if (mapDirectory == L"skirmishes")
    13921392                    {
    13931393                        // playerID is certainly bigger than this map player number
    1394                         LOGWARNING(L"Autostart: Invalid player %d in autostart-civ option", playerID);
     1394                        LOGWARNING("Autostart: Invalid player %d in autostart-civ option", playerID);
    13951395                        continue;
    13961396                    }
    13971397                    scriptInterface.Eval("({})", &player);
    bool Autostart(const CmdLineArgs& args)  
    14031403            }
    14041404        }
    14051405        else
    1406             LOGWARNING(L"Autostart: Option 'autostart-civ' is invalid for scenarios");
     1406            LOGWARNING("Autostart: Option 'autostart-civ' is invalid for scenarios");
    14071407    }
    14081408
    14091409    // Add player data to map settings
  • source/ps/GameSetup/HWDetect.cpp

    diff --git a/source/ps/GameSetup/HWDetect.cpp b/source/ps/GameSetup/HWDetect.cpp
    index 4d7668a..97276f7 100644
    a b void RunHardwareDetection()  
    203203    CVFSFile file;
    204204    if (file.Load(g_VFS, scriptName) != PSRETURN_OK)
    205205    {
    206         LOGERROR(L"Failed to load hardware detection script");
     206        LOGERROR("Failed to load hardware detection script");
    207207        return;
    208208    }
    209209
  • source/ps/GameSetup/Paths.cpp

    diff --git a/source/ps/GameSetup/Paths.cpp b/source/ps/GameSetup/Paths.cpp
    index 7d9883e..434f02c 100644
    a b Paths::Paths(const CmdLineArgs& args)  
    172172    // make sure it's valid
    173173    if(!FileExists(pathname))
    174174    {
    175         LOGERROR(L"Cannot find executable (expected at '%ls')", pathname.string().c_str());
     175        LOGERROR("Cannot find executable (expected at '%s')", pathname.string8());
    176176        WARN_IF_ERR(StatusFromErrno());
    177177    }
    178178
  • source/ps/Hotkey.cpp

    diff --git a/source/ps/Hotkey.cpp b/source/ps/Hotkey.cpp
    index 22ceeba..42cc72a 100644
    a b static void LoadConfigBindings()  
    8383                int mapping = FindKeyCode(*it);
    8484                if (!mapping)
    8585                {
    86                     LOGWARNING(L"Hotkey mapping used invalid key '%hs'", hotkey.c_str());
     86                    LOGWARNING("Hotkey mapping used invalid key '%s'", hotkey.c_str());
    8787                    continue;
    8888                }
    8989
  • source/ps/Joystick.cpp

    diff --git a/source/ps/Joystick.cpp b/source/ps/Joystick.cpp
    index 2950620..d219f1d 100644
    a b void CJoystick::Initialise()  
    4141
    4242    if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
    4343    {
    44         LOGERROR(L"CJoystick::Initialise failed to initialise joysticks (\"%hs\")", SDL_GetError());
     44        LOGERROR("CJoystick::Initialise failed to initialise joysticks (\"%s\")", SDL_GetError());
    4545        return;
    4646    }
    4747
    4848    int numJoysticks = SDL_NumJoysticks();
    4949
    50     LOGMESSAGE(L"Found %d joystick(s)", numJoysticks);
     50    LOGMESSAGE("Found %d joystick(s)", numJoysticks);
    5151
    5252    for (int i = 0; i < numJoysticks; ++i)
    5353    {
    void CJoystick::Initialise()  
    5555        SDL_Joystick* stick = SDL_JoystickOpen(i);
    5656        if (!stick)
    5757        {
    58             LOGERROR(L"CJoystick::Initialise failed to open joystick %d (\"%hs\")", i, SDL_GetError());
     58            LOGERROR("CJoystick::Initialise failed to open joystick %d (\"%s\")", i, SDL_GetError());
    5959            continue;
    6060        }
    6161        const char* name = SDL_JoystickName(stick);
    6262#else // SDL 1.2
    6363        const char* name = SDL_JoystickName(i);
    6464#endif
    65         LOGMESSAGE(L"Joystick %d: %hs", i, name);
     65        LOGMESSAGE("Joystick %d: %s", i, name);
    6666#if SDL_VERSION_ATLEAST(2, 0, 0)
    6767        SDL_JoystickClose(stick);
    6868#endif
    void CJoystick::Initialise()  
    7575        // Always pick the first joystick, and assume that's the right one
    7676        m_Joystick = SDL_JoystickOpen(0);
    7777        if (!m_Joystick)
    78             LOGERROR(L"CJoystick::Initialise failed to open joystick (\"%hs\")", SDL_GetError());
     78            LOGERROR("CJoystick::Initialise failed to open joystick (\"%s\")", SDL_GetError());
    7979    }
    8080}
    8181
  • source/ps/Overlay.cpp

    diff --git a/source/ps/Overlay.cpp b/source/ps/Overlay.cpp
    index f09d3d2..2bf190c 100644
    a b bool CColor::ParseString(const CStr8& Value, int DefaultAlpha)  
    4848        stream >> values[i];
    4949        if ((stream.rdstate() & std::stringstream::failbit) != 0)
    5050        {
    51             LOGWARNING(L"Unable to parse CColor parameters. Your input: '%hs'", Value.c_str());
     51            LOGWARNING("Unable to parse CColor parameters. Your input: '%s'", Value.c_str());
    5252            return false;
    5353        }
    5454        if (values[i] < 0 || values[i] > 255)
    5555        {
    56             LOGWARNING(L"Invalid value (<0 or >255) when parsing CColor parameters. Your input: '%hs'", Value.c_str());
     56            LOGWARNING("Invalid value (<0 or >255) when parsing CColor parameters. Your input: '%s'", Value.c_str());
    5757            return false;
    5858        }
    5959    }
    6060
    6161    if (i < 3)
    6262    {
    63         LOGWARNING(L"Not enough parameters when parsing as CColor. Your input: '%hs'", Value.c_str());
     63        LOGWARNING("Not enough parameters when parsing as CColor. Your input: '%s'", Value.c_str());
    6464        return false;
    6565    }
    6666    if (!stream.eof())
    6767    {
    68         LOGWARNING(L"Too many parameters when parsing as CColor. Your input: '%hs'", Value.c_str());
     68        LOGWARNING("Too many parameters when parsing as CColor. Your input: '%s'", Value.c_str());
    6969        return false;
    7070    }
    7171
  • source/ps/Preprocessor.cpp

    diff --git a/source/ps/Preprocessor.cpp b/source/ps/Preprocessor.cpp
    index d7c228d..f3a9ede 100644
    a b static void DefaultError (void *iData, int iLine, const char *iError,  
    231231{
    232232    (void)iData;
    233233    if (iToken)
    234         LOGERROR(L"Preprocessor error: line %d: %hs: '%.*hs'\n",
     234        LOGERROR("Preprocessor error: line %d: %s: '%.*hs'\n",
    235235                  iLine, iError, int (iTokenLen), iToken);
    236236    else
    237         LOGERROR(L"Preprocessor error: line %d: %hs\n", iLine, iError);
     237        LOGERROR("Preprocessor error: line %d: %s\n", iLine, iError);
    238238}
    239239
    240240//---------------------------------------------------------------------------//
  • source/ps/PreprocessorWrapper.cpp

    diff --git a/source/ps/PreprocessorWrapper.cpp b/source/ps/PreprocessorWrapper.cpp
    index 720edb1..f4ca4ce 100644
    a b bool CPreprocessorWrapper::TestConditional(const CStr& expr)  
    5151
    5252    if (!output)
    5353    {
    54         LOGERROR(L"Failed to parse conditional expression '%hs'", expr.c_str());
     54        LOGERROR("Failed to parse conditional expression '%s'", expr.c_str());
    5555        return false;
    5656    }
    5757
    CStr CPreprocessorWrapper::Preprocess(const CStr& input)  
    7272
    7373    if (!output)
    7474    {
    75         LOGERROR(L"Shader preprocessing failed");
     75        LOGERROR("Shader preprocessing failed");
    7676        return "";
    7777    }
    7878
  • source/ps/ProfileViewer.cpp

    diff --git a/source/ps/ProfileViewer.cpp b/source/ps/ProfileViewer.cpp
    index e976e90..d1ef938 100644
    a b void CProfileViewer::SaveToFile()  
    570570
    571571        if (m->outputStream.fail())
    572572        {
    573             LOGERROR(L"Failed to open profile log file");
     573            LOGERROR("Failed to open profile log file");
    574574            return;
    575575        }
    576576        else
    577577        {
    578             LOGMESSAGERENDER(L"Profiler snapshot saved to '%ls'", path.string().c_str());
     578            LOGMESSAGERENDER("Profiler snapshot saved to '%s'", path.string8());
    579579        }
    580580    }
    581581
  • source/ps/Profiler2.cpp

    diff --git a/source/ps/Profiler2.cpp b/source/ps/Profiler2.cpp
    index ae49b0c..5f8a505 100644
    a b static void* MgCallback(mg_event event, struct mg_connection *conn, const struct  
    126126
    127127    case MG_EVENT_LOG:
    128128        // Called by Mongoose's cry()
    129         LOGERROR(L"Mongoose error: %hs", request_info->log_message);
     129        LOGERROR("Mongoose error: %s", request_info->log_message);
    130130        return NULL;
    131131
    132132    case MG_INIT_SSL:
    void CProfiler2::InitialiseGPU()  
    157157void CProfiler2::EnableHTTP()
    158158{
    159159    ENSURE(m_Initialised);
    160     LOGMESSAGERENDER(L"Starting profiler2 HTTP server");
     160    LOGMESSAGERENDER("Starting profiler2 HTTP server");
    161161
    162162    // Ignore multiple enablings
    163163    if (m_MgContext)
    void CProfiler2::EnableGPU()  
    177177    ENSURE(m_Initialised);
    178178    if (!m_GPU)
    179179    {
    180         LOGMESSAGERENDER(L"Starting profiler2 GPU mode");
     180        LOGMESSAGERENDER("Starting profiler2 GPU mode");
    181181        InitialiseGPU();
    182182    }
    183183}
    184184
    185185void CProfiler2::ShutdownGPU()
    186186{
    187     LOGMESSAGERENDER(L"Shutting down profiler2 GPU mode");
     187    LOGMESSAGERENDER("Shutting down profiler2 GPU mode");
    188188    SAFE_DELETE(m_GPU);
    189189}
    190190
    191191void CProfiler2::ShutDownHTTP()
    192192{
    193     LOGMESSAGERENDER(L"Shutting down profiler2 HTTP server");
     193    LOGMESSAGERENDER("Shutting down profiler2 HTTP server");
    194194    if (m_MgContext)
    195195    {
    196196        mg_stop(m_MgContext);
  • source/ps/SavedGame.cpp

    diff --git a/source/ps/SavedGame.cpp b/source/ps/SavedGame.cpp
    index 007dcb2..94421b5 100644
    a b Status SavedGames::Save(const std::wstring& name, const std::wstring& descriptio  
    126126
    127127    OsPath realPath;
    128128    WARN_RETURN_STATUS_IF_ERR(g_VFS->GetRealPath(filename, realPath));
    129     LOGMESSAGERENDER(wstring_from_utf8(g_L10n.Translate("Saved game to '%ls'") + "\n").c_str(), realPath.string().c_str());
     129    LOGMESSAGERENDER(g_L10n.Translate("Saved game to '%s'"), realPath.string8());
    130130
    131131    return INFO::OK;
    132132}
    std::vector<CScriptValRooted> SavedGames::GetSavedGames(ScriptInterface& scriptI  
    244244        if (!archiveReader)
    245245        {
    246246            // Triggered by e.g. the file being open in another program
    247             LOGWARNING(L"Failed to read saved game '%ls'", realPath.string().c_str());
     247            LOGWARNING("Failed to read saved game '%s'", realPath.string8());
    248248            continue; // skip this file
    249249        }
    250250
  • source/ps/TemplateLoader.cpp

    diff --git a/source/ps/TemplateLoader.cpp b/source/ps/TemplateLoader.cpp
    index d2e8345..dba610f 100644
    a b bool CTemplateLoader::LoadTemplateFile(const std::string& templateName, int dept  
    3939    // Handle infinite loops more gracefully than running out of stack space and crashing
    4040    if (depth > 100)
    4141    {
    42         LOGERROR(L"Probable infinite inheritance loop in entity template '%hs'", templateName.c_str());
     42        LOGERROR("Probable infinite inheritance loop in entity template '%s'", templateName.c_str());
    4343        return false;
    4444    }
    4545
    bool CTemplateLoader::LoadTemplateFile(const std::string& templateName, int dept  
    5757        std::string baseName = templateName.substr(8);
    5858        if (!LoadTemplateFile(baseName, depth+1))
    5959        {
    60             LOGERROR(L"Failed to load entity template '%hs'", baseName.c_str());
     60            LOGERROR("Failed to load entity template '%s'", baseName.c_str());
    6161            return false;
    6262        }
    6363        // Copy a subset to the requested template
    bool CTemplateLoader::LoadTemplateFile(const std::string& templateName, int dept  
    7272        std::string baseName = templateName.substr(7);
    7373        if (!LoadTemplateFile(baseName, depth+1))
    7474        {
    75             LOGERROR(L"Failed to load entity template '%hs'", baseName.c_str());
     75            LOGERROR("Failed to load entity template '%s'", baseName.c_str());
    7676            return false;
    7777        }
    7878        // Copy a subset to the requested template
    bool CTemplateLoader::LoadTemplateFile(const std::string& templateName, int dept  
    8787        std::string baseName = templateName.substr(7);
    8888        if (!LoadTemplateFile(baseName, depth+1))
    8989        {
    90             LOGERROR(L"Failed to load entity template '%hs'", baseName.c_str());
     90            LOGERROR("Failed to load entity template '%s'", baseName.c_str());
    9191            return false;
    9292        }
    9393        // Copy a subset to the requested template
    bool CTemplateLoader::LoadTemplateFile(const std::string& templateName, int dept  
    102102        std::string baseName = templateName.substr(11);
    103103        if (!LoadTemplateFile(baseName, depth+1))
    104104        {
    105             LOGERROR(L"Failed to load entity template '%hs'", baseName.c_str());
     105            LOGERROR("Failed to load entity template '%s'", baseName.c_str());
    106106            return false;
    107107        }
    108108        // Copy a subset to the requested template
    bool CTemplateLoader::LoadTemplateFile(const std::string& templateName, int dept  
    117117        std::string baseName = templateName.substr(13);
    118118        if (!LoadTemplateFile(baseName, depth+1))
    119119        {
    120             LOGERROR(L"Failed to load entity template '%hs'", baseName.c_str());
     120            LOGERROR("Failed to load entity template '%s'", baseName.c_str());
    121121            return false;
    122122        }
    123123        // Copy a subset to the requested template
    bool CTemplateLoader::LoadTemplateFile(const std::string& templateName, int dept  
    132132        std::string baseName = templateName.substr(9);
    133133        if (!LoadTemplateFile(baseName, depth+1))
    134134        {
    135             LOGERROR(L"Failed to load entity template '%hs'", baseName.c_str());
     135            LOGERROR("Failed to load entity template '%s'", baseName.c_str());
    136136            return false;
    137137        }
    138138        // Copy a subset to the requested template
    bool CTemplateLoader::LoadTemplateFile(const std::string& templateName, int dept  
    155155        // To prevent needless complexity in template design, we don't allow |-separated strings as parents
    156156        if (parentName.find('|') != parentName.npos)
    157157        {
    158             LOGERROR(L"Invalid parent '%hs' in entity template '%hs'", parentName.c_str(), templateName.c_str());
     158            LOGERROR("Invalid parent '%s' in entity template '%s'", parentName.c_str(), templateName.c_str());
    159159            return false;
    160160        }
    161161
    162162        // Ensure the parent is loaded
    163163        if (!LoadTemplateFile(parentName, depth+1))
    164164        {
    165             LOGERROR(L"Failed to load parent '%hs' of entity template '%hs'", parentName.c_str(), templateName.c_str());
     165            LOGERROR("Failed to load parent '%s' of entity template '%s'", parentName.c_str(), templateName.c_str());
    166166            return false;
    167167        }
    168168
    std::vector<std::string> CTemplateLoader::FindPlaceableTemplates(const std::stri  
    272272    }
    273273
    274274    if (templatesType != SIMULATION_TEMPLATES && templatesType != ACTOR_TEMPLATES && templatesType != ALL_TEMPLATES)
    275         LOGERROR(L"Undefined template type (valid: all, simulation, actor)");
     275        LOGERROR("Undefined template type (valid: all, simulation, actor)");
    276276
    277277    return templates;
    278278}
    std::vector<std::string> CTemplateLoader::FindTemplates(const std::string& path,  
    304304    }
    305305
    306306    if (templatesType != SIMULATION_TEMPLATES && templatesType != ACTOR_TEMPLATES && templatesType != ALL_TEMPLATES)
    307         LOGERROR(L"Undefined template type (valid: all, simulation, actor)");
     307        LOGERROR("Undefined template type (valid: all, simulation, actor)");
    308308
    309309    return templates;
    310310}
    const CParamNode& CTemplateLoader::GetTemplateFileData(const std::string& templa  
    314314    // Load the template if necessary
    315315    if (!LoadTemplateFile(templateName, 0))
    316316    {
    317         LOGERROR(L"Failed to load entity template '%hs'", templateName.c_str());
     317        LOGERROR("Failed to load entity template '%s'", templateName.c_str());
    318318        return NULL_NODE;
    319319    }
    320320
    void CTemplateLoader::ConstructTemplateActor(const std::string& actorName, CPara  
    327327    const char* templateName = "special/actor";
    328328    if (!LoadTemplateFile(templateName, 0))
    329329    {
    330         LOGERROR(L"Failed to load entity template '%hs'", templateName);
     330        LOGERROR("Failed to load entity template '%s'", templateName);
    331331        return;
    332332    }
    333333
  • source/ps/Util.cpp

    diff --git a/source/ps/Util.cpp b/source/ps/Util.cpp
    index 3817112..17c58d1 100644
    a b void WriteScreenshot(const VfsPath& extension)  
    241241    {
    242242        OsPath realPath;
    243243        g_VFS->GetRealPath(filename, realPath);
    244         LOGMESSAGERENDER(wstring_from_utf8(g_L10n.Translate("Screenshot written to '%ls'")).c_str(), realPath.string().c_str());
     244        LOGMESSAGERENDER(g_L10n.Translate("Screenshot written to '%s'"), realPath.string8());
    245245    }
    246246    else
    247         LOGERROR(L"Error writing screenshot to '%ls'", filename.string().c_str());
     247        LOGERROR("Error writing screenshot to '%s'", filename.string8());
    248248}
    249249
    250250
    void WriteBigScreenshot(const VfsPath& extension, int tiles)  
    374374    {
    375375        OsPath realPath;
    376376        g_VFS->GetRealPath(filename, realPath);
    377         LOGMESSAGERENDER(wstring_from_utf8(g_L10n.Translate("Screenshot written to '%ls'")).c_str(), realPath.string().c_str());
     377        LOGMESSAGERENDER(g_L10n.Translate("Screenshot written to '%s'"), realPath.string8());
    378378    }
    379379    else
    380         LOGERROR(L"Error writing screenshot to '%ls'", filename.string().c_str());
     380        LOGERROR("Error writing screenshot to '%s'", filename.string8());
    381381
    382382    free(tile_data);
    383383}
  • source/ps/VideoMode.cpp

    diff --git a/source/ps/VideoMode.cpp b/source/ps/VideoMode.cpp
    index 7ff6870..08b6a44 100644
    a b bool CVideoMode::SetVideoMode(int w, int h, int bpp, bool fullscreen)  
    8888            // If fullscreen fails, try windowed mode
    8989            if (fullscreen)
    9090            {
    91                 LOGWARNING(L"Failed to set the video mode to fullscreen for the chosen resolution "
    92                     L"%dx%d:%d (\"%hs\"), falling back to windowed mode",
     91                LOGWARNING("Failed to set the video mode to fullscreen for the chosen resolution "
     92                    "%dx%d:%d (\"%hs\"), falling back to windowed mode",
    9393                    w, h, bpp, SDL_GetError());
    9494                // Using default size for the window for now, as the attempted setting
    9595                // could be as large, or larger than the screen size.
    bool CVideoMode::SetVideoMode(int w, int h, int bpp, bool fullscreen)  
    9797            }
    9898            else
    9999            {
    100                 LOGERROR(L"SetVideoMode failed in SDL_CreateWindow: %dx%d:%d %d (\"%hs\")",
     100                LOGERROR("SetVideoMode failed in SDL_CreateWindow: %dx%d:%d %d (\"%s\")",
    101101                    w, h, bpp, fullscreen ? 1 : 0, SDL_GetError());
    102102                return false;
    103103            }
    bool CVideoMode::SetVideoMode(int w, int h, int bpp, bool fullscreen)  
    105105
    106106        if (SDL_SetWindowDisplayMode(m_Window, NULL) < 0)
    107107        {
    108             LOGERROR(L"SetVideoMode failed in SDL_SetWindowDisplayMode: %dx%d:%d %d (\"%hs\")",
     108            LOGERROR("SetVideoMode failed in SDL_SetWindowDisplayMode: %dx%d:%d %d (\"%s\")",
    109109                w, h, bpp, fullscreen ? 1 : 0, SDL_GetError());
    110110            return false;
    111111        }
    bool CVideoMode::SetVideoMode(int w, int h, int bpp, bool fullscreen)  
    113113        SDL_GLContext context = SDL_GL_CreateContext(m_Window);
    114114        if (!context)
    115115        {
    116             LOGERROR(L"SetVideoMode failed in SDL_GL_CreateContext: %dx%d:%d %d (\"%hs\")",
     116            LOGERROR("SetVideoMode failed in SDL_GL_CreateContext: %dx%d:%d %d (\"%s\")",
    117117                w, h, bpp, fullscreen ? 1 : 0, SDL_GetError());
    118118            return false;
    119119        }
    bool CVideoMode::SetVideoMode(int w, int h, int bpp, bool fullscreen)  
    132132
    133133            if (SDL_SetWindowFullscreen(m_Window, flags) < 0)
    134134            {
    135                 LOGERROR(L"SetVideoMode failed in SDL_SetWindowFullscreen: %dx%d:%d %d (\"%hs\")",
     135                LOGERROR("SetVideoMode failed in SDL_SetWindowFullscreen: %dx%d:%d %d (\"%s\")",
    136136                    w, h, bpp, fullscreen ? 1 : 0, SDL_GetError());
    137137                return false;
    138138            }
    bool CVideoMode::SetVideoMode(int w, int h, int bpp, bool fullscreen)  
    172172        // If fullscreen fails, try windowed mode
    173173        if (fullscreen)
    174174        {
    175             LOGWARNING(L"Failed to set the video mode to fullscreen for the chosen resolution "
    176                 L"%dx%d:%d (\"%hs\"), falling back to windowed mode",
     175            LOGWARNING("Failed to set the video mode to fullscreen for the chosen resolution "
     176                "%dx%d:%d (\"%hs\"), falling back to windowed mode",
    177177                w, h, bpp, SDL_GetError());
    178178            // Using default size for the window for now, as the attempted setting
    179179            // could be as large, or larger than the screen size.
    bool CVideoMode::SetVideoMode(int w, int h, int bpp, bool fullscreen)  
    181181        }
    182182        else
    183183        {
    184             LOGERROR(L"SetVideoMode failed: %dx%d:%d %d (\"%hs\")",
     184            LOGERROR("SetVideoMode failed: %dx%d:%d %d (\"%s\")",
    185185                w, h, bpp, fullscreen ? 1 : 0, SDL_GetError());
    186186            return false;
    187187        }
    bool CVideoMode::InitSDL()  
    294294    u16 ramp[256];
    295295    SDL_CalculateGammaRamp(g_Gamma, ramp);
    296296    if (SDL_SetWindowGammaRamp(m_Window, ramp, ramp, ramp) < 0)
    297         LOGWARNING(L"SDL_SetWindowGammaRamp failed");
     297        LOGWARNING("SDL_SetWindowGammaRamp failed");
    298298#else
    299299# if OS_MACOSX
    300300    // Workaround for crash on Mavericks, see http://trac.wildfiregames.com/ticket/2272
    bool CVideoMode::InitSDL()  
    304304    {
    305305# endif
    306306    if (SDL_SetGamma(g_Gamma, g_Gamma, g_Gamma) < 0)
    307         LOGWARNING(L"SDL_SetGamma failed");
     307        LOGWARNING("SDL_SetGamma failed");
    308308# if OS_MACOSX
    309309    }
    310310# endif
  • source/ps/World.cpp

    diff --git a/source/ps/World.cpp b/source/ps/World.cpp
    index 879825d..5a20b3c 100644
    a b void CWorld::RegisterInit(const CStrW& mapFile, const CScriptValRooted& settings  
    8989        catch (PSERROR_File& err)
    9090        {
    9191            delete reader;
    92             LOGERROR(L"Failed to load map %ls: %hs", mapfilename.string().c_str(), err.what());
     92            LOGERROR("Failed to load map %s: %s", mapfilename.string8(), err.what());
    9393            throw PSERROR_Game_World_MapLoadFailed("Failed to load map.\nCheck application log for details.");
    9494        }
    9595    }
  • source/ps/XML/RelaxNG.cpp

    diff --git a/source/ps/XML/RelaxNG.cpp b/source/ps/XML/RelaxNG.cpp
    index 8a63869..57d6344 100644
    a b public:  
    4646        xmlRelaxNGFreeParserCtxt(ctxt);
    4747
    4848        if (m_Schema == NULL)
    49             LOGERROR(L"RelaxNGValidator: Failed to compile schema");
     49            LOGERROR("RelaxNGValidator: Failed to compile schema");
    5050    }
    5151
    5252    ~RelaxNGSchema()
    bool RelaxNGValidator::ValidateEncoded(const std::wstring& filename, const std::  
    108108
    109109    if (!m_Schema)
    110110    {
    111         LOGERROR(L"RelaxNGValidator: No grammar loaded");
     111        LOGERROR("RelaxNGValidator: No grammar loaded");
    112112        return false;
    113113    }
    114114
    115115    xmlDocPtr doc = xmlReadMemory(document.c_str(), (int)document.size(), utf8_from_wstring(filename).c_str(), NULL, XML_PARSE_NONET);
    116116    if (doc == NULL)
    117117    {
    118         LOGERROR(L"RelaxNGValidator: Failed to parse document");
     118        LOGERROR("RelaxNGValidator: Failed to parse document");
    119119        return false;
    120120    }
    121121
    bool RelaxNGValidator::ValidateEncoded(const std::wstring& filename, const std::  
    130130    }
    131131    else if (ret > 0)
    132132    {
    133         LOGERROR(L"RelaxNGValidator: Validation failed");
     133        LOGERROR("RelaxNGValidator: Validation failed");
    134134        return false;
    135135    }
    136136    else
    137137    {
    138         LOGERROR(L"RelaxNGValidator: Internal error %d", ret);
     138        LOGERROR("RelaxNGValidator: Internal error %d", ret);
    139139        return false;
    140140    }
    141141}
  • source/ps/XML/XMLWriter.cpp

    diff --git a/source/ps/XML/XMLWriter.cpp b/source/ps/XML/XMLWriter.cpp
    index e77ce17..9c3e9a0 100644
    a b bool XMLWriter_File::StoreVFS(const PIVFS& vfs, const VfsPath& pathname)  
    102102    Status ret = vfs->CreateFile(pathname, data, size);
    103103    if (ret < 0)
    104104    {
    105         LOGERROR(L"Error saving XML data through VFS: %lld '%ls'", (long long)ret, pathname.string().c_str());
     105        LOGERROR("Error saving XML data through VFS: %lld '%s'", (long long)ret, pathname.string8());
    106106        return false;
    107107    }
    108108    return true;
  • source/ps/XML/Xeromyces.cpp

    diff --git a/source/ps/XML/Xeromyces.cpp b/source/ps/XML/Xeromyces.cpp
    index e7b2e57..68ba0c6 100644
    a b static void errorHandler(void* UNUSED(userData), xmlErrorPtr error)  
    3838    if (message.length() > 0 && message[message.length()-1] == '\n')
    3939        message.erase(message.length()-1);
    4040
    41     LOGERROR(L"CXeromyces: Parse %ls: %hs:%d: %hs",
    42         error->level == XML_ERR_WARNING ? L"warning" : L"error",
    43         error->file, error->line, message.c_str());
     41    LOGERROR("CXeromyces: Parse %s: %s:%d: %s",
     42        error->level == XML_ERR_WARNING ? "warning" : "error",
     43        error->file, error->line, message);
    4444    // TODO: The (non-fatal) warnings and errors don't get stored in the XMB,
    4545    // so the caching is less transparent than it should be
    4646}
    PSRETURN CXeromyces::Load(const PIVFS& vfs, const VfsPath& filename)  
    8989
    9090        // No source file or archive cache was found, so we can't load the
    9191        // XML file at all
    92         LOGERROR(L"CCacheLoader failed to find archived or source file for: \"%ls\"", filename.string().c_str());
     92        LOGERROR("CCacheLoader failed to find archived or source file for: \"%s\"", filename.string8());
    9393        return PSRETURN_Xeromyces_XMLOpenFailed;
    9494    }
    9595
    PSRETURN CXeromyces::ConvertFile(const PIVFS& vfs, const VfsPath& filename, cons  
    111111    CVFSFile input;
    112112    if (input.Load(vfs, filename))
    113113    {
    114         LOGERROR(L"CXeromyces: Failed to open XML file %ls", filename.string().c_str());
     114        LOGERROR("CXeromyces: Failed to open XML file %s", filename.string8());
    115115        return PSRETURN_Xeromyces_XMLOpenFailed;
    116116    }
    117117
    PSRETURN CXeromyces::ConvertFile(const PIVFS& vfs, const VfsPath& filename, cons  
    120120        filename8.c_str(), NULL, XML_PARSE_NONET|XML_PARSE_NOCDATA);
    121121    if (! doc)
    122122    {
    123         LOGERROR(L"CXeromyces: Failed to parse XML file %ls", filename.string().c_str());
     123        LOGERROR("CXeromyces: Failed to parse XML file %s", filename.string8());
    124124        return PSRETURN_Xeromyces_XMLParseError;
    125125    }
    126126
    PSRETURN CXeromyces::LoadString(const char* xml)  
    167167    xmlDocPtr doc = xmlReadMemory(xml, (int)strlen(xml), "", NULL, XML_PARSE_NONET|XML_PARSE_NOCDATA);
    168168    if (! doc)
    169169    {
    170         LOGERROR(L"CXeromyces: Failed to parse XML string");
     170        LOGERROR("CXeromyces: Failed to parse XML string");
    171171        return PSRETURN_Xeromyces_XMLParseError;
    172172    }
    173173
  • source/ps/XML/tests/test_RelaxNG.h

    diff --git a/source/ps/XML/tests/test_RelaxNG.h b/source/ps/XML/tests/test_RelaxNG.h
    index 0cb11c6..3b10986 100644
    a b public:  
    4444        {
    4545            TestLogger logger;
    4646            TS_ASSERT(!v.Validate(L"doc", L"<bogus/>"));
    47             TS_ASSERT_WSTR_CONTAINS(logger.GetOutput(), L"Parse error: doc:1: Expecting element test, got bogus");
     47            TS_ASSERT_STR_CONTAINS(logger.GetOutput(), "Parse error: doc:1: Expecting element test, got bogus");
    4848        }
    4949
    5050        {
    5151            TestLogger logger;
    5252            TS_ASSERT(!v.Validate(L"doc", L"bogus"));
    53             TS_ASSERT_WSTR_CONTAINS(logger.GetOutput(), L"RelaxNGValidator: Failed to parse document");
     53            TS_ASSERT_STR_CONTAINS(logger.GetOutput(), "RelaxNGValidator: Failed to parse document");
    5454        }
    5555
    5656        TS_ASSERT(v.Validate(L"doc", L"<test/>"));
    public:  
    8282
    8383        TestLogger logger;
    8484        TS_ASSERT(!v.LoadGrammar("whoops"));
    85         TS_ASSERT_WSTR_CONTAINS(logger.GetOutput(), L"RelaxNGValidator: Failed to compile schema");
     85        TS_ASSERT_STR_CONTAINS(logger.GetOutput(), "RelaxNGValidator: Failed to compile schema");
    8686
    8787        TS_ASSERT(!v.Validate(L"doc", L"<test/>"));
    8888    }
  • source/ps/scripting/JSInterface_ConfigDB.cpp

    diff --git a/source/ps/scripting/JSInterface_ConfigDB.cpp b/source/ps/scripting/JSInterface_ConfigDB.cpp
    index 43c6a4d..319db0e 100644
    a b bool JSI_ConfigDB::GetConfigNamespace(std::wstring cfgNsString, EConfigNamespace  
    3535        cfgNs = CFG_MOD;
    3636    else
    3737    {
    38         LOGERROR(L"Invalid namespace name passed to the ConfigDB!");
     38        LOGERROR("Invalid namespace name passed to the ConfigDB!");
    3939        cfgNs = CFG_DEFAULT;
    4040        return false;       
    4141    }
  • source/ps/scripting/JSInterface_Console.cpp

    diff --git a/source/ps/scripting/JSInterface_Console.cpp b/source/ps/scripting/JSInterface_Console.cpp
    index bc7ab85..d65d9a9 100644
    a b bool JSI_Console::CheckGlobalInitialized()  
    2626{   
    2727    if (!g_Console)
    2828    {
    29         LOGERROR(L"Trying to access the console when it's not initialized!");
     29        LOGERROR("Trying to access the console when it's not initialized!");
    3030        return false;
    3131    }
    3232    return true;
  • source/ps/scripting/JSInterface_VFS.cpp

    diff --git a/source/ps/scripting/JSInterface_VFS.cpp b/source/ps/scripting/JSInterface_VFS.cpp
    index ccc804b..bf74daf 100644
    a b  
    3636    }\
    3737    /* unknown failure. We output an error message. */\
    3838    else if (err < 0)\
    39         LOGERROR(L"Unknown failure in VFS %i", err );
     39        LOGERROR("Unknown failure in VFS %i", err );
    4040    /* else: success */
    4141
    4242
  • source/ps/tests/test_CLogger.h

    diff --git a/source/ps/tests/test_CLogger.h b/source/ps/tests/test_CLogger.h
    index 285abd6..8d1dc34 100644
    a b class TestCLogger : public CxxTest::TestSuite  
    2424public:
    2525    void test_basic()
    2626    {
    27         logger->LogMessage(L"Test 1");
    28         logger->LogMessage(L"Test 2");
     27        logger->WriteMessage("Test 1", false);
     28        logger->WriteMessage("Test 2", false);
    2929
    3030        ParseOutput();
    3131
    public:  
    3434        TS_ASSERT_EQUALS(lines[1], "Test 2");
    3535    }
    3636
    37     void test_overflow()
     37    void test_unicode()
    3838    {
    39         const int buflen = 1024;
    40 
    41         std::string msg0 (buflen-2, '*');
    42         std::string msg1 (buflen-1, '*');
    43         std::string msg2 (buflen,   '*');
    44         std::string msg3 (buflen+1, '*');
    45 
    46         std::string clipped (buflen-4, '*');
    47         clipped += "...";
    48 
    49         logger->LogMessage(L"%hs", msg0.c_str());
    50         logger->LogMessage(L"%hs", msg1.c_str());
    51         logger->LogMessage(L"%hs", msg2.c_str());
    52         logger->LogMessage(L"%hs", msg3.c_str());
    53 
    54         logger->LogMessageRender(L"%hs", msg0.c_str());
    55         logger->LogMessageRender(L"%hs", msg1.c_str());
    56         logger->LogMessageRender(L"%hs", msg2.c_str());
    57         logger->LogMessageRender(L"%hs", msg3.c_str());
    58 
    59         logger->LogWarning(L"%hs", msg0.c_str());
    60         logger->LogWarning(L"%hs", msg1.c_str());
    61         logger->LogWarning(L"%hs", msg2.c_str());
    62         logger->LogWarning(L"%hs", msg3.c_str());
    63 
    64         logger->LogError(L"%hs", msg0.c_str());
    65         logger->LogError(L"%hs", msg1.c_str());
    66         logger->LogError(L"%hs", msg2.c_str());
    67         logger->LogError(L"%hs", msg3.c_str());
     39        wchar_t str[] = { 226, 32, 295, 0 };
     40        logger->WriteMessage(utf8_from_wstring(str).c_str(), false);
    6841
    6942        ParseOutput();
    7043
    71         TS_ASSERT_EQUALS((int)lines.size(), 4*4);
    72         TS_ASSERT_EQUALS(lines[0], msg0);
    73         TS_ASSERT_EQUALS(lines[1], msg1);
    74         TS_ASSERT_EQUALS(lines[2], clipped);
    75         TS_ASSERT_EQUALS(lines[3], clipped);
    76 
    77         TS_ASSERT_EQUALS(lines[4], msg0);
    78         TS_ASSERT_EQUALS(lines[5], msg1);
    79         TS_ASSERT_EQUALS(lines[6], clipped);
    80         TS_ASSERT_EQUALS(lines[7], clipped);
    81 
    82         TS_ASSERT_EQUALS(lines[8], "WARNING: "+msg0);
    83         TS_ASSERT_EQUALS(lines[9], "WARNING: "+msg1);
    84         TS_ASSERT_EQUALS(lines[10], "WARNING: "+clipped);
    85         TS_ASSERT_EQUALS(lines[11], "WARNING: "+clipped);
    86 
    87         TS_ASSERT_EQUALS(lines[12], "ERROR: "+msg0);
    88         TS_ASSERT_EQUALS(lines[13], "ERROR: "+msg1);
    89         TS_ASSERT_EQUALS(lines[14], "ERROR: "+clipped);
    90         TS_ASSERT_EQUALS(lines[15], "ERROR: "+clipped);
     44        TS_ASSERT_EQUALS((int)lines.size(), 1);
     45        TS_ASSERT_EQUALS(lines[0], "\xC3\xA2 \xC4\xA7");
    9146    }
    9247
    93     void test_unicode()
     48    void test_html()
    9449    {
    95         logger->LogMessage(L"%lc %lc", 226, 295);
     50        logger->WriteMessage("Test<a&b>c<d&e>", false);
    9651
    9752        ParseOutput();
    9853
    9954        TS_ASSERT_EQUALS((int)lines.size(), 1);
    100         TS_ASSERT_EQUALS(lines[0], "\xC3\xA2 \xC4\xA7");
     55        TS_ASSERT_EQUALS(lines[0], "Test&lt;a&amp;b>c&lt;d&amp;e>");
    10156    }
    10257
    103     void test_html()
     58    void test_null()
    10459    {
    105         logger->LogMessage(L"Test<a&b>c<d&e>");
     60        logger->WriteMessage(fmt::sprintf("a %s b", (const char *)NULL).c_str(), false);
    10661
    10762        ParseOutput();
    10863
    10964        TS_ASSERT_EQUALS((int)lines.size(), 1);
    110         TS_ASSERT_EQUALS(lines[0], "Test&lt;a&amp;b>c&lt;d&amp;e>");
     65        TS_ASSERT_EQUALS(lines[0], "a (null) b");
    11166    }
    11267
    11368    //////////////////////////////////////////////////////////////////////////
  • source/renderer/DecalRData.cpp

    diff --git a/source/renderer/DecalRData.cpp b/source/renderer/DecalRData.cpp
    index 0c85902..363f7b4 100644
    a b void CDecalRData::RenderDecals(std::vector<CDecalRData*>& decals, const CShaderD  
    8484       
    8585        if (material.GetShaderEffect().length() == 0)
    8686        {
    87             LOGERROR(L"Terrain renderer failed to load shader effect.\n");
     87            LOGERROR("Terrain renderer failed to load shader effect.\n");
    8888            continue;
    8989        }
    9090       
    void CDecalRData::RenderDecals(std::vector<CDecalRData*>& decals, const CShaderD  
    9898           
    9999            if (!techBase)
    100100            {
    101                 LOGERROR(L"Terrain renderer failed to load shader effect (%hs)\n",         
     101                LOGERROR("Terrain renderer failed to load shader effect (%s)\n",           
    102102                        material.GetShaderEffect().string().c_str());
    103103                continue;
    104104            }
  • source/renderer/ModelRenderer.cpp

    diff --git a/source/renderer/ModelRenderer.cpp b/source/renderer/ModelRenderer.cpp
    index 3737f61..941b4e2 100644
    a b void ModelRenderer::BuildPositionAndNormals(  
    9898        // some broken situations
    9999        if (numVertices && vertices[0].m_Blend.m_Bone[0] == 0xff)
    100100        {
    101             LOGERROR(L"Model %ls is boned with unboned animation", mdef->GetName().string().c_str());
     101            LOGERROR("Model %s is boned with unboned animation", mdef->GetName().string8());
    102102            return;
    103103        }
    104104
  • source/renderer/PatchRData.cpp

    diff --git a/source/renderer/PatchRData.cpp b/source/renderer/PatchRData.cpp
    index c8c5553..2604567 100644
    a b void CPatchRData::RenderBases(const std::vector<CPatchRData*>& patches, const CS  
    766766        {
    767767            if (itt->first->GetMaterial().GetShaderEffect().length() == 0)
    768768            {
    769                 LOGERROR(L"Terrain renderer failed to load shader effect.\n");
     769                LOGERROR("Terrain renderer failed to load shader effect.\n");
    770770                continue;
    771771            }
    772772                       
  • source/renderer/PostprocManager.cpp

    diff --git a/source/renderer/PostprocManager.cpp b/source/renderer/PostprocManager.cpp
    index 0dadb89..81cc923 100644
    a b void CPostprocManager::RecreateBuffers()  
    159159    GLenum status = pglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
    160160    if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
    161161    {
    162         LOGWARNING(L"Framebuffer object incomplete (A): 0x%04X", status);
     162        LOGWARNING("Framebuffer object incomplete (A): 0x%04X", status);
    163163    }
    164164   
    165165    pglGenFramebuffersEXT(1, &m_PongFbo);
    void CPostprocManager::RecreateBuffers()  
    174174    status = pglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
    175175    if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
    176176    {
    177         LOGWARNING(L"Framebuffer object incomplete (B): 0x%04X", status);
     177        LOGWARNING("Framebuffer object incomplete (B): 0x%04X", status);
    178178    }
    179179   
    180180    pglGenFramebuffersEXT(1, &m_BloomFbo);
    void CPostprocManager::RecreateBuffers()  
    187187    status = pglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
    188188    if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
    189189    {
    190         LOGWARNING(L"Framebuffer object incomplete (B): 0x%04X", status);
     190        LOGWARNING("Framebuffer object incomplete (B): 0x%04X", status);
    191191    }
    192192    */
    193193
    std::vector<CStrW> CPostprocManager::GetPostEffects()  
    519519   
    520520    VfsPaths pathnames;
    521521    if(vfs::GetPathnames(g_VFS, path, 0, pathnames) < 0)
    522         LOGERROR(L"Error finding Post effects in '%ls'", path.string().c_str());
     522        LOGERROR("Error finding Post effects in '%s'", path.string8());
    523523
    524524    for(size_t i = 0; i < pathnames.size(); i++)
    525525    {
  • source/renderer/Renderer.cpp

    diff --git a/source/renderer/Renderer.cpp b/source/renderer/Renderer.cpp
    index 404d90a..3fe81ab 100644
    a b bool CRenderer::Open(int width, int height)  
    636636
    637637    GLint bits;
    638638    glGetIntegerv(GL_DEPTH_BITS,&bits);
    639     LOGMESSAGE(L"CRenderer::Open: depth bits %d",bits);
     639    LOGMESSAGE("CRenderer::Open: depth bits %d",bits);
    640640    glGetIntegerv(GL_STENCIL_BITS,&bits);
    641     LOGMESSAGE(L"CRenderer::Open: stencil bits %d",bits);
     641    LOGMESSAGE("CRenderer::Open: stencil bits %d",bits);
    642642    glGetIntegerv(GL_ALPHA_BITS,&bits);
    643     LOGMESSAGE(L"CRenderer::Open: alpha bits %d",bits);
     643    LOGMESSAGE("CRenderer::Open: alpha bits %d",bits);
    644644
    645645    // Validate the currently selected render path
    646646    SetRenderPath(m_Options.m_RenderPath);
    void CRenderer::SetRenderPath(RenderPath rp)  
    808808    {
    809809        if (!(m_Caps.m_ARBProgram || (m_Caps.m_VertexShader && m_Caps.m_FragmentShader && m_Options.m_PreferGLSL)))
    810810        {
    811             LOGWARNING(L"Falling back to fixed function\n");
     811            LOGWARNING("Falling back to fixed function\n");
    812812            rp = RP_FIXED;
    813813        }
    814814    }
    CRenderer::RenderPath CRenderer::GetRenderPathByName(const CStr& name)  
    843843    if (name == "default")
    844844        return RP_DEFAULT;
    845845
    846     LOGWARNING(L"Unknown render path name '%hs', assuming 'default'", name.c_str());
     846    LOGWARNING("Unknown render path name '%s', assuming 'default'", name.c_str());
    847847    return RP_DEFAULT;
    848848}
    849849
    void CRenderer::EndFrame()  
    16291629        int err = glGetError();
    16301630        if (err)
    16311631        {
    1632             ONCE(LOGERROR(L"CRenderer::EndFrame: GL errors %i occurred", err));
     1632            ONCE(LOGERROR("CRenderer::EndFrame: GL errors %i occurred", err));
    16331633        }
    16341634    }
    16351635}
  • source/renderer/ShadowMap.cpp

    diff --git a/source/renderer/ShadowMap.cpp b/source/renderer/ShadowMap.cpp
    index f776175..934eefd 100644
    a b void ShadowMapInternals::CreateTexture()  
    406406    default: formatname = "DEPTH_COMPONENT"; break;
    407407    }
    408408
    409     LOGMESSAGE(L"Creating shadow texture (size %dx%d) (format = %hs)",
     409    LOGMESSAGE("Creating shadow texture (size %dx%d) (format = %s)",
    410410        Width, Height, formatname);
    411411
    412412
    void ShadowMapInternals::CreateTexture()  
    494494
    495495    if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
    496496    {
    497         LOGWARNING(L"Framebuffer object incomplete: 0x%04X", status);
     497        LOGWARNING("Framebuffer object incomplete: 0x%04X", status);
    498498
    499499        // Disable shadow rendering (but let the user try again if they want)
    500500        g_Renderer.m_Options.m_Shadows = false;
  • source/renderer/SkyManager.cpp

    diff --git a/source/renderer/SkyManager.cpp b/source/renderer/SkyManager.cpp
    index e0368e7..d65c054 100644
    a b void SkyManager::LoadSkyTextures()  
    126126            if (g_VFS->LoadFile(path2, file, fileSize) < 0)
    127127            {
    128128                glDeleteTextures(1, &m_SkyCubeMap);
    129                 LOGERROR(L"Error creating sky cubemap.");
     129                LOGERROR("Error creating sky cubemap.");
    130130                return;
    131131            }
    132132        }
    std::vector<CStrW> SkyManager::GetSkySets() const  
    207207    DirectoryNames subdirectories;
    208208    if(g_VFS->GetDirectoryEntries(path, 0, &subdirectories) < 0)
    209209    {
    210         LOGERROR(L"Error opening directory '%ls'", path.string().c_str());
     210        LOGERROR("Error opening directory '%s'", path.string8());
    211211        return std::vector<CStrW>(1, GetSkySet()); // just return what we currently have
    212212    }
    213213
  • source/renderer/TerrainRenderer.cpp

    diff --git a/source/renderer/TerrainRenderer.cpp b/source/renderer/TerrainRenderer.cpp
    index 4f6d9bc..026f49b 100644
    a b bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, int cullGr  
    653653       
    654654        if (!m->fancyWaterShader)
    655655        {
    656             LOGERROR(L"Failed to load water shader. Falling back to fixed pipeline water.\n");
     656            LOGERROR("Failed to load water shader. Falling back to fixed pipeline water.\n");
    657657            WaterMgr->m_RenderWater = false;
    658658            return false;
    659659        }
  • source/renderer/VertexBufferManager.cpp

    diff --git a/source/renderer/VertexBufferManager.cpp b/source/renderer/VertexBufferManager.cpp
    index d9ada2f..3911efa 100644
    a b CVertexBuffer::VBChunk* CVertexBufferManager::Allocate(size_t vertexSize, size_t  
    8787   
    8888    if (!result)
    8989    {
    90         LOGERROR(L"Failed to create VBOs (%lu*%lu)", (unsigned long)vertexSize, (unsigned long)numVertices);
     90        LOGERROR("Failed to create VBOs (%lu*%lu)", (unsigned long)vertexSize, (unsigned long)numVertices);
    9191    }
    9292
    9393    return result;
  • source/renderer/WaterManager.cpp

    diff --git a/source/renderer/WaterManager.cpp b/source/renderer/WaterManager.cpp
    index aa66016..2e48d34 100644
    a b int WaterManager::LoadWaterTextures()  
    326326    GLenum status = pglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
    327327    if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
    328328    {
    329         LOGWARNING(L"Reflection framebuffer object incomplete: 0x%04X", status);
     329        LOGWARNING("Reflection framebuffer object incomplete: 0x%04X", status);
    330330        g_Renderer.m_Options.m_WaterReflection = false;
    331331    }
    332332
    int WaterManager::LoadWaterTextures()  
    341341    status = pglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
    342342    if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
    343343    {
    344         LOGWARNING(L"Refraction framebuffer object incomplete: 0x%04X", status);
     344        LOGWARNING("Refraction framebuffer object incomplete: 0x%04X", status);
    345345        g_Renderer.m_Options.m_WaterRefraction = false;
    346346    }
    347347   
    int WaterManager::LoadWaterTextures()  
    356356    status = pglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
    357357    if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
    358358    {
    359         LOGWARNING(L"Fancy Effects framebuffer object incomplete: 0x%04X", status);
     359        LOGWARNING("Fancy Effects framebuffer object incomplete: 0x%04X", status);
    360360        g_Renderer.m_Options.m_WaterRefraction = false;
    361361    }
    362362   
  • source/scriptinterface/DebuggingServer.cpp

    diff --git a/source/scriptinterface/DebuggingServer.cpp b/source/scriptinterface/DebuggingServer.cpp
    index fa484b0..366a1c1 100644
    a b CDebuggingServer::CDebuggingServer() :  
    9494    m_SettingBreakOnException = true;
    9595
    9696    EnableHTTP();
    97     LOGWARNING(L"Javascript debugging webserver enabled.");
     97    LOGWARNING("Javascript debugging webserver enabled.");
    9898}
    9999
    100100CDebuggingServer::~CDebuggingServer()
    void* CDebuggingServer::MgDebuggingServerCallback(mg_event event, struct mg_conn  
    396396
    397397    case MG_EVENT_LOG:
    398398        // Called by Mongoose's cry()
    399         LOGERROR(L"Mongoose error: %hs", request_info->log_message);
     399        LOGERROR("Mongoose error: %s", request_info->log_message);
    400400        return NULL;
    401401
    402402    case MG_INIT_SSL:
  • source/scriptinterface/ScriptInterface.cpp

    diff --git a/source/scriptinterface/ScriptInterface.cpp b/source/scriptinterface/ScriptInterface.cpp
    index d87ab68..a86ab5d 100644
    a b void ErrorReporter(JSContext* cx, const char* message, JSErrorReport* report)  
    126126    }
    127127
    128128    if (isWarning)
    129         LOGWARNING(L"%hs", msg.str().c_str());
     129        LOGWARNING("%s", msg.str().c_str());
    130130    else
    131         LOGERROR(L"%hs", msg.str().c_str());
     131        LOGERROR("%s", msg.str().c_str());
    132132
    133133    // When running under Valgrind, print more information in the error message
    134134//  VALGRIND_PRINTF_BACKTRACE("->");
    JSBool logmsg(JSContext* cx, uint argc, jsval* vp)  
    163163    std::wstring str;
    164164    if (!ScriptInterface::FromJSVal(cx, args.handleAt(0), str))
    165165        return JS_FALSE;
    166     LOGMESSAGE(L"%ls", str.c_str());
     166    LOGMESSAGE("%s", utf8_from_wstring(str));
    167167    args.rval().setUndefined();
    168168    return JS_TRUE;
    169169}
    JSBool warn(JSContext* cx, uint argc, jsval* vp)  
    180180    std::wstring str;
    181181    if (!ScriptInterface::FromJSVal(cx, args.handleAt(0), str))
    182182        return JS_FALSE;
    183     LOGWARNING(L"%ls", str.c_str());
     183    LOGWARNING("%s", utf8_from_wstring(str));
    184184    args.rval().setUndefined();
    185185    return JS_TRUE;
    186186}
    JSBool error(JSContext* cx, uint argc, jsval* vp)  
    197197    std::wstring str;
    198198    if (!ScriptInterface::FromJSVal(cx, args.handleAt(0), str))
    199199        return JS_FALSE;
    200     LOGERROR(L"%ls", str.c_str());
     200    LOGERROR("%s", utf8_from_wstring(str));
    201201    args.rval().setUndefined();
    202202    return JS_TRUE;
    203203}
    ScriptInterface::ScriptInterface(const char* nativeScopeName, const char* debugN  
    420420    if (g_JSDebuggerEnabled && g_DebuggingServer != NULL)
    421421    {
    422422        if(!JS_SetDebugMode(GetContext(), true))
    423             LOGERROR(L"Failed to set Spidermonkey to debug mode!");
     423            LOGERROR("Failed to set Spidermonkey to debug mode!");
    424424        else
    425425            g_DebuggingServer->RegisterScriptinterface(debugName, this);
    426426    } */
    bool ScriptInterface::LoadGlobalScripts()  
    478478    {
    479479        if (!LoadGlobalScriptFile(*it))
    480480        {
    481             LOGERROR(L"LoadGlobalScripts: Failed to load script %ls", it->string().c_str());
     481            LOGERROR("LoadGlobalScripts: Failed to load script %s", it->string8());
    482482            return false;
    483483        }
    484484    }
    bool ScriptInterface::ReplaceNondeterministicRNG(boost::rand48& rng)  
    507507        }
    508508    }
    509509
    510     LOGERROR(L"ReplaceNondeterministicRNG: failed to replace Math.random");
     510    LOGERROR("ReplaceNondeterministicRNG: failed to replace Math.random");
    511511    return false;
    512512}
    513513
    void ScriptInterface::CallConstructor(JS::HandleValue ctor, JS::AutoValueVector&  
    543543    JSAutoRequest rq(m->m_cx);
    544544    if (!ctor.isObject())
    545545    {
    546         LOGERROR(L"CallConstructor: ctor is not an object");
     546        LOGERROR("CallConstructor: ctor is not an object");
    547547        out.setNull();
    548548        return;
    549549    }
    bool ScriptInterface::EnumeratePropertyNamesWithPrefix(JS::HandleValue objVal, c  
    750750   
    751751    if (!objVal.isObjectOrNull())
    752752    {
    753         LOGERROR(L"EnumeratePropertyNamesWithPrefix expected object type!");
     753        LOGERROR("EnumeratePropertyNamesWithPrefix expected object type!");
    754754        return false;
    755755    }
    756756       
    bool ScriptInterface::LoadGlobalScriptFile(const VfsPath& path)  
    866866    JSAutoRequest rq(m->m_cx);
    867867    if (!VfsFileExists(path))
    868868    {
    869         LOGERROR(L"File '%ls' does not exist", path.string().c_str());
     869        LOGERROR("File '%s' does not exist", path.string8());
    870870        return false;
    871871    }
    872872
    bool ScriptInterface::LoadGlobalScriptFile(const VfsPath& path)  
    876876
    877877    if (ret != PSRETURN_OK)
    878878    {
    879         LOGERROR(L"Failed to load file '%ls': %hs", path.string().c_str(), GetErrorString(ret));
     879        LOGERROR("Failed to load file '%s': %s", path.string8(), GetErrorString(ret));
    880880        return false;
    881881    }
    882882
    bool ScriptInterface::ParseJSON(const std::string& string_utf8, JS::MutableHandl  
    926926    if (JS_ParseJSON(m->m_cx, reinterpret_cast<const jschar*>(string.c_str()), (u32)string.size(), out))
    927927        return true;
    928928
    929     LOGERROR(L"JS_ParseJSON failed!");
     929    LOGERROR("JS_ParseJSON failed!");
    930930    if (!JS_IsExceptionPending(m->m_cx))
    931931        return false;
    932932
    bool ScriptInterface::ParseJSON(const std::string& string_utf8, JS::MutableHandl  
    946946
    947947    std::wstring error;
    948948    ScriptInterface::FromJSVal(m->m_cx, rval, error);
    949     LOGERROR(L"%ls", error.c_str());
     949    LOGERROR("%s", utf8_from_wstring(error));
    950950    return false;
    951951}
    952952
    void ScriptInterface::ReadJSONFile(const VfsPath& path, JS::MutableHandleValue o  
    954954{
    955955    if (!VfsFileExists(path))
    956956    {
    957         LOGERROR(L"File '%ls' does not exist", path.string().c_str());
     957        LOGERROR("File '%s' does not exist", path.string8());
    958958        return;
    959959    }
    960960
    void ScriptInterface::ReadJSONFile(const VfsPath& path, JS::MutableHandleValue o  
    964964
    965965    if (ret != PSRETURN_OK)
    966966    {
    967         LOGERROR(L"Failed to load file '%ls': %hs", path.string().c_str(), GetErrorString(ret));
     967        LOGERROR("Failed to load file '%s': %s", path.string8(), GetErrorString(ret));
    968968        return;
    969969    }
    970970
    971971    std::string content(file.DecodeUTF8()); // assume it's UTF-8
    972972
    973973    if (!ParseJSON(content, out))
    974         LOGERROR(L"Failed to parse '%ls'", path.string().c_str());
     974        LOGERROR("Failed to parse '%s'", path.string8());
    975975}
    976976
    977977struct Stringifier
    std::string ScriptInterface::StringifyJSON(JS::MutableHandleValue obj, bool inde  
    10111011    if (!JS_Stringify(m->m_cx, obj.address(), NULL, indentVal, &Stringifier::callback, &str))
    10121012    {
    10131013        JS_ClearPendingException(m->m_cx);
    1014         LOGERROR(L"StringifyJSON failed");
     1014        LOGERROR("StringifyJSON failed");
    10151015        return std::string();
    10161016    }
    10171017
  • source/scriptinterface/ThreadDebugger.cpp

    diff --git a/source/scriptinterface/ThreadDebugger.cpp b/source/scriptinterface/ThreadDebugger.cpp
    index e9eebbc..f5d9768 100644
    a b JSTrapStatus CThreadDebugger::BreakHandler(JSContext* cx, JSScript* script, jsby  
    493493            *m->m_pLastBreakFrame = JS_FrameIterator(m->m_pScriptInterface->GetContext(), &iter);
    494494           
    495495            if (!JS_SetSingleStepMode(cx, script, true))
    496                 LOGERROR(L"JS_SetSingleStepMode returned false!"); // TODO: When can this happen?
     496                LOGERROR("JS_SetSingleStepMode returned false!"); // TODO: When can this happen?
    497497            else
    498498            {
    499499                if (nextDbgCmd == DBG_CMD_SINGLESTEP)
    JSTrapStatus CThreadDebugger::BreakHandler(JSContext* cx, JSScript* script, jsby  
    516516        else if (nextDbgCmd == DBG_CMD_CONTINUE)
    517517        {
    518518            if (!JS_SetSingleStepMode(cx, script, true))
    519                 LOGERROR(L"JS_SetSingleStepMode returned false!"); // TODO: When can this happen?
     519                LOGERROR("JS_SetSingleStepMode returned false!"); // TODO: When can this happen?
    520520            else
    521521            {
    522522                // Setup a handler to check for break-requests from the DebuggingServer regularly
    std::string CThreadDebugger::StringifyCyclicJSON(jsval obj, bool indent)  
    846846    JSObject* replacer = JS_GetFunctionObject(fun);
    847847    if (!JS_Stringify(m->m_pScriptInterface->GetContext(), &obj, replacer, indent ? INT_TO_JSVAL(2) : JSVAL_VOID, &CyclicRefWorkaround::Stringifier::callback, &str))
    848848    {
    849         LOGERROR(L"StringifyJSON failed");
     849        LOGERROR("StringifyJSON failed");
    850850        jsval exec;
    851851        jsval execString;
    852852        if (JS_GetPendingException(m->m_pScriptInterface->GetContext(), &exec))
    std::string CThreadDebugger::StringifyCyclicJSON(jsval obj, bool indent)  
    858858                if (JSVAL_IS_STRING(execString))
    859859                {
    860860                    std::string strExec = JS_EncodeString(m->m_pScriptInterface->GetContext(), JSVAL_TO_STRING(execString));
    861                     LOGERROR(L"Error: %hs", strExec.c_str());
     861                    LOGERROR("Error: %s", strExec.c_str());
    862862                }
    863863            }
    864864           
  • source/scriptinterface/tests/test_ScriptInterface.h

    diff --git a/source/scriptinterface/tests/test_ScriptInterface.h b/source/scriptinterface/tests/test_ScriptInterface.h
    index 3089ea6..e966ee4 100644
    a b public:  
    3131        ScriptInterface script("Test", "Test", g_ScriptRuntime);
    3232        TestLogger logger;
    3333        TS_ASSERT(script.LoadScript(L"test.js", "var x = 1+1;"));
    34         TS_ASSERT_WSTR_NOT_CONTAINS(logger.GetOutput(), L"JavaScript error");
    35         TS_ASSERT_WSTR_NOT_CONTAINS(logger.GetOutput(), L"JavaScript warning");
     34        TS_ASSERT_STR_NOT_CONTAINS(logger.GetOutput(), "JavaScript error");
     35        TS_ASSERT_STR_NOT_CONTAINS(logger.GetOutput(), "JavaScript warning");
    3636    }
    3737
    3838    void test_loadscript_error()
    public:  
    4040        ScriptInterface script("Test", "Test", g_ScriptRuntime);
    4141        TestLogger logger;
    4242        TS_ASSERT(!script.LoadScript(L"test.js", "1+"));
    43         TS_ASSERT_WSTR_CONTAINS(logger.GetOutput(), L"JavaScript error: test.js line 1\nSyntaxError: syntax error");
     43        TS_ASSERT_STR_CONTAINS(logger.GetOutput(), "JavaScript error: test.js line 1\nSyntaxError: syntax error");
    4444    }
    4545
    4646    void test_loadscript_strict_warning()
    public:  
    4949        TestLogger logger;
    5050        // in strict mode, this inside a function doesn't point to the global object
    5151        TS_ASSERT(script.LoadScript(L"test.js", "var isStrict = (function() { return !this; })();warn('isStrict is '+isStrict);"));
    52         TS_ASSERT_WSTR_CONTAINS(logger.GetOutput(), L"WARNING: isStrict is true");
     52        TS_ASSERT_STR_CONTAINS(logger.GetOutput(), "WARNING: isStrict is true");
    5353    }
    5454
    5555    void test_loadscript_strict_error()
    public:  
    5757        ScriptInterface script("Test", "Test", g_ScriptRuntime);
    5858        TestLogger logger;
    5959        TS_ASSERT(!script.LoadScript(L"test.js", "with(1){}"));
    60         TS_ASSERT_WSTR_CONTAINS(logger.GetOutput(), L"JavaScript error: test.js line 1\nSyntaxError: strict mode code may not contain \'with\' statements");
     60        TS_ASSERT_STR_CONTAINS(logger.GetOutput(), "JavaScript error: test.js line 1\nSyntaxError: strict mode code may not contain \'with\' statements");
    6161    }
    6262
    6363    void test_clone_basic()
  • source/simulation2/Simulation2.cpp

    diff --git a/source/simulation2/Simulation2.cpp b/source/simulation2/Simulation2.cpp
    index 4e5a366..ac70109 100644
    a b bool CSimulation2Impl::LoadScripts(CComponentManager& componentManager, std::set  
    187187        VfsPath filename = *it;
    188188        if (loadedScripts)
    189189            loadedScripts->insert(filename);
    190         LOGMESSAGE(L"Loading simulation script '%ls'", filename.string().c_str());
     190        LOGMESSAGE("Loading simulation script '%s'", filename.string8());
    191191        if (!componentManager.LoadScript(filename))
    192192            ok = false;
    193193    }
    bool CSimulation2Impl::LoadTriggerScripts(CComponentManager& componentManager, J  
    204204        for (u32 i = 0; i < scriptNames.size(); ++i)
    205205        {
    206206            std::string scriptName = "maps/" + scriptNames[i];
    207             LOGMESSAGE(L"Loading trigger script '%hs'", scriptName.c_str());
     207            LOGMESSAGE("Loading trigger script '%s'", scriptName.c_str());
    208208            if (!componentManager.LoadScript(scriptName.data()))
    209209                ok = false;
    210210        }
    Status CSimulation2Impl::ReloadChangedFile(const VfsPath& path)  
    224224    if (!VfsFileExists(path))
    225225        return INFO::OK;
    226226
    227     LOGMESSAGE(L"Reloading simulation script '%ls'", path.string().c_str());
     227    LOGMESSAGE("Reloading simulation script '%s'", path.string8());
    228228    if (!m_ComponentManager.LoadScript(path, true))
    229229        return ERR::FAIL;
    230230
    static std::vector<std::string> GetJSONData(const VfsPath& path)  
    828828    {
    829829        // Some error reading directory
    830830        wchar_t error[200];
    831         LOGERROR(L"Error reading directory '%ls': %ls", path.string().c_str(), StatusDescription(ret, error, ARRAY_SIZE(error)));
     831        LOGERROR("Error reading directory '%s': %s", path.string8(), utf8_from_wstring(StatusDescription(ret, error, ARRAY_SIZE(error))));
    832832        return std::vector<std::string>();
    833833    }
    834834
    static std::vector<std::string> GetJSONData(const VfsPath& path)  
    840840        PSRETURN ret = file.Load(g_VFS, *it);
    841841        if (ret != PSRETURN_OK)
    842842        {
    843             LOGERROR(L"GetJSONData: Failed to load file '%ls': %hs", path.string().c_str(), GetErrorString(ret));
     843            LOGERROR("GetJSONData: Failed to load file '%s': %s", path.string8(), GetErrorString(ret));
    844844            continue;
    845845        }
    846846
    static std::string ReadJSON(const VfsPath& path)  
    864864{
    865865    if (!VfsFileExists(path))
    866866    {
    867         LOGERROR(L"File '%ls' does not exist", path.string().c_str());
     867        LOGERROR("File '%s' does not exist", path.string8());
    868868        return std::string();
    869869    }
    870870
    static std::string ReadJSON(const VfsPath& path)  
    873873    PSRETURN ret = file.Load(g_VFS, path);
    874874    if (ret != PSRETURN_OK)
    875875    {
    876         LOGERROR(L"Failed to load file '%ls': %hs", path.string().c_str(), GetErrorString(ret));
     876        LOGERROR("Failed to load file '%s': %s", path.string8(), GetErrorString(ret));
    877877        return std::string();
    878878    }
    879879
  • source/simulation2/components/CCmpAIManager.cpp

    diff --git a/source/simulation2/components/CCmpAIManager.cpp b/source/simulation2/components/CCmpAIManager.cpp
    index ac1c542..e2a067a 100644
    a b private:  
    104104            m_Worker.LoadMetadata(path, &metadata);
    105105            if (metadata.isUndefined())
    106106            {
    107                 LOGERROR(L"Failed to create AI player: can't find %ls", path.string().c_str());
     107                LOGERROR("Failed to create AI player: can't find %s", path.string8());
    108108                return false;
    109109            }
    110110
    private:  
    116116            JS::RootedValue ctor(cx);
    117117            if (!m_ScriptInterface->HasProperty(metadata, "moduleName"))
    118118            {
    119                 LOGERROR(L"Failed to create AI player: %ls: missing 'moduleName'", path.string().c_str());
     119                LOGERROR("Failed to create AI player: %s: missing 'moduleName'", path.string8());
    120120                return false;
    121121            }
    122122
    private:  
    124124            if (!m_ScriptInterface->GetProperty(global, moduleName.c_str(), &objectWithConstructor)
    125125                || objectWithConstructor.isUndefined())
    126126            {
    127                 LOGERROR(L"Failed to create AI player: %ls: can't find the module that should contain the constructor: '%hs'", path.string().c_str(), moduleName.c_str());
     127                LOGERROR("Failed to create AI player: %s: can't find the module that should contain the constructor: '%s'", path.string8(), moduleName);
    128128                return false;
    129129            }
    130130
    131131            if (!m_ScriptInterface->GetProperty(metadata, "constructor", constructor))
    132132            {
    133                 LOGERROR(L"Failed to create AI player: %ls: missing 'constructor'", path.string().c_str());
     133                LOGERROR("Failed to create AI player: %s: missing 'constructor'", path.string8());
    134134                return false;
    135135            }
    136136
    private:  
    138138            if (!m_ScriptInterface->GetProperty(objectWithConstructor, constructor.c_str(), &ctor)
    139139                || ctor.isNull())
    140140            {
    141                 LOGERROR(L"Failed to create AI player: %ls: can't find constructor '%hs'", path.string().c_str(), constructor.c_str());
     141                LOGERROR("Failed to create AI player: %s: can't find constructor '%s'", path.string8(), constructor);
    142142                return false;
    143143            }
    144144
    private:  
    160160
    161161            if (obj.isNull())
    162162            {
    163                 LOGERROR(L"Failed to create AI player: %ls: error calling constructor '%hs'", path.string().c_str(), constructor.c_str());
     163                LOGERROR("Failed to create AI player: %s: error calling constructor '%s'", path.string8(), constructor);
    164164                return false;
    165165            }
    166166
    public:  
    261261        VfsPaths pathnames;
    262262        if (vfs::GetPathnames(g_VFS, L"simulation/ai/" + moduleName + L"/", L"*.js", pathnames) < 0)
    263263        {
    264             LOGERROR(L"Failed to load AI scripts for module %ls", moduleName.c_str());
     264            LOGERROR("Failed to load AI scripts for module %s", utf8_from_wstring(moduleName));
    265265            return false;
    266266        }
    267267
    public:  
    269269        {
    270270            if (!m_ScriptInterface->LoadGlobalScriptFile(*it))
    271271            {
    272                 LOGERROR(L"Failed to load script %ls", it->string().c_str());
     272                LOGERROR("Failed to load script %s", it->string8());
    273273                return false;
    274274            }
    275275        }
    public:  
    308308            }
    309309        }
    310310       
    311         LOGERROR(L"Invalid playerid in PostCommand!"); 
     311        LOGERROR("Invalid playerid in PostCommand!");   
    312312    }
    313313    // The next two ought to be implmeneted someday but for now as it returns "null" it can't
    314314    static void DumpHeap(ScriptInterface::CxPrivate* pCxPrivate)
    public:  
    391391        JS::RootedValue ctor(cx);
    392392        if (!m_ScriptInterface->GetProperty(global, "API3", &AIModule) || AIModule.isUndefined())
    393393        {
    394             LOGERROR(L"Failed to create shared AI component: %ls: can't find module '%hs'", path.string().c_str(), "API3");
     394            LOGERROR("Failed to create shared AI component: %s: can't find module '%s'", path.string8(), "API3");
    395395            return false;
    396396        }
    397397       
    398398        if (!m_ScriptInterface->GetProperty(AIModule, "SharedScript", &ctor)
    399399            || ctor.isUndefined())
    400400        {
    401             LOGERROR(L"Failed to create shared AI component: %ls: can't find constructor '%hs'", path.string().c_str(), "SharedScript");
     401            LOGERROR("Failed to create shared AI component: %s: can't find constructor '%s'", path.string8(), "SharedScript");
    402402            return false;
    403403        }
    404404       
    public:  
    440440       
    441441        if (tmpSharedAIObj.isNull())
    442442        {
    443             LOGERROR(L"Failed to create shared AI component: %ls: error calling constructor '%hs'", path.string().c_str(), "SharedScript");
     443            LOGERROR("Failed to create shared AI component: %s: error calling constructor '%s'", path.string8(), "SharedScript");
    444444            return false;
    445445        }
    446446       
    public:  
    617617            JS::RootedValue sharedData(cx);
    618618            JS::RootedValue tmpSharedAIObj(cx, m_SharedAIObj.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
    619619            if (!m_ScriptInterface->CallFunction(tmpSharedAIObj, "Serialize", &sharedData))
    620                 LOGERROR(L"AI shared script Serialize call failed");
     620                LOGERROR("AI shared script Serialize call failed");
    621621            serializer.ScriptVal("sharedData", &sharedData);
    622622        }
    623623        for (size_t i = 0; i < m_Players.size(); ++i)
    public:  
    640640            {
    641641                JS::RootedValue scriptData(cx);
    642642                if (!m_ScriptInterface->CallFunction(tmpPlayerObj, "Serialize", &scriptData))
    643                     LOGERROR(L"AI script Serialize call failed");
     643                    LOGERROR("AI script Serialize call failed");
    644644                serializer.ScriptVal("data", &scriptData);
    645645            }
    646646            else
    public:  
    681681            JS::RootedValue tmpSharedAIObj(cx, m_SharedAIObj.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31
    682682            deserializer.ScriptVal("sharedData", &sharedData);
    683683            if (!m_ScriptInterface->CallFunctionVoid(tmpSharedAIObj, "Deserialize", sharedData))
    684                 LOGERROR(L"AI shared script Deserialize call failed");
     684                LOGERROR("AI shared script Deserialize call failed");
    685685        }
    686686
    687687        for (size_t i = 0; i < numAis; ++i)
    public:  
    720720                if (m_Players[i]->m_UseSharedComponent)
    721721                {
    722722                    if (!m_ScriptInterface->CallFunctionVoid(tmpPlayerObj, "Deserialize", scriptData, m_SharedAIObj))
    723                         LOGERROR(L"AI script Deserialize call failed");
     723                        LOGERROR("AI script Deserialize call failed");
    724724                }
    725725                else if (!m_ScriptInterface->CallFunctionVoid(tmpPlayerObj, "Deserialize", scriptData))
    726726                {
    727                     LOGERROR(L"AI script deserialize() call failed");
     727                    LOGERROR("AI script deserialize() call failed");
    728728                }
    729729            }
    730730            else
    public:  
    748748        std::pair<std::map<JSObject*, std::wstring>::iterator, bool> ret1 = m_SerializablePrototypes.insert(std::make_pair(obj, name));
    749749        std::pair<std::map<std::wstring, JSObject*>::iterator, bool> ret2 = m_DeserializablePrototypes.insert(std::make_pair(name, obj));
    750750        if (!ret1.second || !ret2.second)
    751             LOGERROR(L"RegisterSerializablePrototype called with same prototype multiple times: p=%p n='%ls'", obj, name.c_str());
     751            LOGERROR("RegisterSerializablePrototype called with same prototype multiple times: p=%p n='%s'", (void *)obj, utf8_from_wstring(name));
    752752    }
    753753
    754754private:
  • source/simulation2/components/CCmpCommandQueue.cpp

    diff --git a/source/simulation2/components/CCmpCommandQueue.cpp b/source/simulation2/components/CCmpCommandQueue.cpp
    index 3b3b0c6..c66ef5d 100644
    a b public:  
    119119        {
    120120            bool ok = scriptInterface.CallFunctionVoid(global, "ProcessCommand", localCommands[i].player, localCommands[i].data);
    121121            if (!ok)
    122                 LOGERROR(L"Failed to call ProcessCommand() global script function");
     122                LOGERROR("Failed to call ProcessCommand() global script function");
    123123        }
    124124
    125125        for (size_t i = 0; i < commands.size(); ++i)
    126126        {
    127127            bool ok = scriptInterface.CallFunctionVoid(global, "ProcessCommand", commands[i].player, commands[i].data);
    128128            if (!ok)
    129                 LOGERROR(L"Failed to call ProcessCommand() global script function");
     129                LOGERROR("Failed to call ProcessCommand() global script function");
    130130        }
    131131    }
    132132};
  • source/simulation2/components/CCmpObstruction.cpp

    diff --git a/source/simulation2/components/CCmpObstruction.cpp b/source/simulation2/components/CCmpObstruction.cpp
    index 638d804..37afbcd 100644
    a b public:  
    515515        // required precondition to use SkipControlGroupsRequireFlagObstructionFilter
    516516        if (m_ControlGroup == INVALID_ENTITY)
    517517        {
    518             LOGERROR(L"[CmpObstruction] Cannot test for foundation obstructions; primary control group must be valid");
     518            LOGERROR("[CmpObstruction] Cannot test for foundation obstructions; primary control group must be valid");
    519519            return FOUNDATION_CHECK_FAIL_ERROR;
    520520        }
    521521
    public:  
    552552        // required precondition to use SkipControlGroupsRequireFlagObstructionFilter
    553553        if (m_ControlGroup == INVALID_ENTITY)
    554554        {
    555             LOGERROR(L"[CmpObstruction] Cannot test for foundation obstructions; primary control group must be valid");
     555            LOGERROR("[CmpObstruction] Cannot test for foundation obstructions; primary control group must be valid");
    556556            return false;
    557557        }
    558558
    public:  
    586586        // required precondition to use SkipControlGroupsRequireFlagObstructionFilter
    587587        if (m_ControlGroup == INVALID_ENTITY)
    588588        {
    589             LOGERROR(L"[CmpObstruction] Cannot test for unit or structure obstructions; primary control group must be valid");
     589            LOGERROR("[CmpObstruction] Cannot test for unit or structure obstructions; primary control group must be valid");
    590590            return ret;
    591591        }
    592592
  • source/simulation2/components/CCmpPathfinder.cpp

    diff --git a/source/simulation2/components/CCmpPathfinder.cpp b/source/simulation2/components/CCmpPathfinder.cpp
    index b2a321c..59c700a 100644
    a b ICmpPathfinder::pass_class_t CCmpPathfinder::GetPassabilityClass(const std::stri  
    254254{
    255255    if (m_PassClassMasks.find(name) == m_PassClassMasks.end())
    256256    {
    257         LOGERROR(L"Invalid passability class name '%hs'", name.c_str());
     257        LOGERROR("Invalid passability class name '%s'", name.c_str());
    258258        return 0;
    259259    }
    260260
    ICmpPathfinder::cost_class_t CCmpPathfinder::GetCostClass(const std::string& nam  
    270270{
    271271    if (m_UnitCostClassTags.find(name) == m_UnitCostClassTags.end())
    272272    {
    273         LOGERROR(L"Invalid unit cost class name '%hs'", name.c_str());
     273        LOGERROR("Invalid unit cost class name '%s'", name.c_str());
    274274        return m_UnitCostClassTags["default"];
    275275    }
    276276
  • source/simulation2/components/CCmpPosition.cpp

    diff --git a/source/simulation2/components/CCmpPosition.cpp b/source/simulation2/components/CCmpPosition.cpp
    index 51004b4..d5838b7 100644
    a b public:  
    271271        CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), m_TurretParent);
    272272        if (!cmpPosition)
    273273        {
    274             LOGERROR(L"Turret with parent without position component");
     274            LOGERROR("Turret with parent without position component");
    275275            return;
    276276        }
    277277        if (!cmpPosition->IsInWorld())
    public:  
    482482    {
    483483        if (!m_InWorld)
    484484        {
    485             LOGERROR(L"CCmpPosition::GetPosition called on entity when IsInWorld is false");
     485            LOGERROR("CCmpPosition::GetPosition called on entity when IsInWorld is false");
    486486            return CFixedVector3D();
    487487        }
    488488
    public:  
    493493    {
    494494        if (!m_InWorld)
    495495        {
    496             LOGERROR(L"CCmpPosition::GetPosition2D called on entity when IsInWorld is false");
     496            LOGERROR("CCmpPosition::GetPosition2D called on entity when IsInWorld is false");
    497497            return CFixedVector2D();
    498498        }
    499499
    public:  
    504504    {
    505505        if (!m_InWorld)
    506506        {
    507             LOGERROR(L"CCmpPosition::GetPreviousPosition called on entity when IsInWorld is false");
     507            LOGERROR("CCmpPosition::GetPreviousPosition called on entity when IsInWorld is false");
    508508            return CFixedVector3D();
    509509        }
    510510
    public:  
    515515    {
    516516        if (!m_InWorld)
    517517        {
    518             LOGERROR(L"CCmpPosition::GetPreviousPosition2D called on entity when IsInWorld is false");
     518            LOGERROR("CCmpPosition::GetPreviousPosition2D called on entity when IsInWorld is false");
    519519            return CFixedVector2D();
    520520        }
    521521
    public:  
    589589    {
    590590        if (!m_InWorld)
    591591        {
    592             LOGERROR(L"CCmpPosition::GetDistanceTravelled called on entity when IsInWorld is false");
     592            LOGERROR("CCmpPosition::GetDistanceTravelled called on entity when IsInWorld is false");
    593593            return fixed::Zero();
    594594        }
    595595
    public:  
    630630    {
    631631        if (!m_InWorld)
    632632        {
    633             LOGERROR(L"CCmpPosition::GetInterpolatedPosition2D called on entity when IsInWorld is false");
     633            LOGERROR("CCmpPosition::GetInterpolatedPosition2D called on entity when IsInWorld is false");
    634634            return;
    635635        }
    636636
    public:  
    647647            CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), m_TurretParent);
    648648            if (!cmpPosition)
    649649            {
    650                 LOGERROR(L"Turret with parent without position component");
     650                LOGERROR("Turret with parent without position component");
    651651                CMatrix3D m;
    652652                m.SetIdentity();
    653653                return m;
    654654            }
    655655            if (!cmpPosition->IsInWorld())
    656656            {
    657                 LOGERROR(L"CCmpPosition::GetInterpolatedTransform called on turret entity when IsInWorld is false");
     657                LOGERROR("CCmpPosition::GetInterpolatedTransform called on turret entity when IsInWorld is false");
    658658                CMatrix3D m;
    659659                m.SetIdentity();
    660660                return m;
    public:  
    670670        }
    671671        if (!m_InWorld)
    672672        {
    673             LOGERROR(L"CCmpPosition::GetInterpolatedTransform called on entity when IsInWorld is false");
     673            LOGERROR("CCmpPosition::GetInterpolatedTransform called on entity when IsInWorld is false");
    674674            CMatrix3D m;
    675675            m.SetIdentity();
    676676            return m;
    private:  
    925925    {
    926926        if (!m_InWorld)
    927927        {
    928             LOGERROR(L"CCmpPosition::UpdateXZRotation called on entity when IsInWorld is false");
     928            LOGERROR("CCmpPosition::UpdateXZRotation called on entity when IsInWorld is false");
    929929            return;
    930930        }
    931931
    private:  
    940940        CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity());
    941941        if (!cmpTerrain || !cmpTerrain->IsLoaded())
    942942        {
    943             LOGERROR(L"Terrain not loaded");
     943            LOGERROR("Terrain not loaded");
    944944            return;
    945945        }
    946946
  • source/simulation2/components/CCmpProjectileManager.cpp

    diff --git a/source/simulation2/components/CCmpProjectileManager.cpp b/source/simulation2/components/CCmpProjectileManager.cpp
    index 3b243a7..8e0d5c3 100644
    a b uint32_t CCmpProjectileManager::LaunchProjectile(entity_id_t source, CFixedVecto  
    175175    {
    176176        // If the actor was actually loaded, complain that it doesn't have a projectile
    177177        if (!cmpSourceVisual->GetActorShortName().empty())
    178             LOGERROR(L"Unit with actor '%ls' launched a projectile but has no actor on 'projectile' attachpoint", cmpSourceVisual->GetActorShortName().c_str());
     178            LOGERROR("Unit with actor '%s' launched a projectile but has no actor on 'projectile' attachpoint", utf8_from_wstring(cmpSourceVisual->GetActorShortName()));
    179179        return 0;
    180180    }
    181181
  • source/simulation2/components/CCmpRallyPointRenderer.cpp

    diff --git a/source/simulation2/components/CCmpRallyPointRenderer.cpp b/source/simulation2/components/CCmpRallyPointRenderer.cpp
    index a5258fe..e686c40 100644
    a b void CCmpRallyPointRenderer::UpdateMarkers()  
    521521
    522522        // the marker entity should be valid at this point, otherwise something went wrong trying to allocate it
    523523        if (m_MarkerEntityIds[i] == INVALID_ENTITY)
    524             LOGERROR(L"Failed to create rally point marker entity");
     524            LOGERROR("Failed to create rally point marker entity");
    525525
    526526        CmpPtr<ICmpPosition> markerCmpPosition(GetSimContext(), m_MarkerEntityIds[i]);
    527527        if (markerCmpPosition)
  • source/simulation2/components/CCmpRangeManager.cpp

    diff --git a/source/simulation2/components/CCmpRangeManager.cpp b/source/simulation2/components/CCmpRangeManager.cpp
    index b4988b9..275b1ec 100644
    a b public:  
    738738    {
    739739        if (m_Queries.find(tag) == m_Queries.end())
    740740        {
    741             LOGERROR(L"CCmpRangeManager: DestroyActiveQuery called with invalid tag %u", tag);
     741            LOGERROR("CCmpRangeManager: DestroyActiveQuery called with invalid tag %u", tag);
    742742            return;
    743743        }
    744744
    public:  
    750750        std::map<tag_t, Query>::iterator it = m_Queries.find(tag);
    751751        if (it == m_Queries.end())
    752752        {
    753             LOGERROR(L"CCmpRangeManager: EnableActiveQuery called with invalid tag %u", tag);
     753            LOGERROR("CCmpRangeManager: EnableActiveQuery called with invalid tag %u", tag);
    754754            return;
    755755        }
    756756
    public:  
    763763        std::map<tag_t, Query>::iterator it = m_Queries.find(tag);
    764764        if (it == m_Queries.end())
    765765        {
    766             LOGERROR(L"CCmpRangeManager: DisableActiveQuery called with invalid tag %u", tag);
     766            LOGERROR("CCmpRangeManager: DisableActiveQuery called with invalid tag %u", tag);
    767767            return;
    768768        }
    769769
    public:  
    820820        std::map<tag_t, Query>::iterator it = m_Queries.find(tag);
    821821        if (it == m_Queries.end())
    822822        {
    823             LOGERROR(L"CCmpRangeManager: ResetActiveQuery called with invalid tag %u", tag);
     823            LOGERROR("CCmpRangeManager: ResetActiveQuery called with invalid tag %u", tag);
    824824            return r;
    825825        }
    826826
    public:  
    11561156    {
    11571157        // Min range must be non-negative
    11581158        if (minRange < entity_pos_t::Zero())
    1159             LOGWARNING(L"CCmpRangeManager: Invalid min range %f in query for entity %u", minRange.ToDouble(), source);
     1159            LOGWARNING("CCmpRangeManager: Invalid min range %f in query for entity %u", minRange.ToDouble(), source);
    11601160
    11611161        // Max range must be non-negative, or else -1
    11621162        if (maxRange < entity_pos_t::Zero() && maxRange != entity_pos_t::FromInt(-1))
    1163             LOGWARNING(L"CCmpRangeManager: Invalid max range %f in query for entity %u", maxRange.ToDouble(), source);
     1163            LOGWARNING("CCmpRangeManager: Invalid max range %f in query for entity %u", maxRange.ToDouble(), source);
    11641164
    11651165        Query q;
    11661166        q.enabled = false;
    public:  
    13371337        if (identifier == "injured")
    13381338            return 2;
    13391339
    1340         LOGWARNING(L"CCmpRangeManager: Invalid flag identifier %hs", identifier.c_str());
     1340        LOGWARNING("CCmpRangeManager: Invalid flag identifier %s", identifier.c_str());
    13411341        return 0;
    13421342    }
    13431343
    public:  
    13541354        // We don't have a flag set
    13551355        if (flag == 0)
    13561356        {
    1357             LOGWARNING(L"CCmpRangeManager: Invalid flag identifier %hs for entity %u", identifier.c_str(), ent);
     1357            LOGWARNING("CCmpRangeManager: Invalid flag identifier %s for entity %u", identifier.c_str(), ent);
    13581358            return;
    13591359        }
    13601360
  • source/simulation2/components/CCmpTemplateManager.cpp

    diff --git a/source/simulation2/components/CCmpTemplateManager.cpp b/source/simulation2/components/CCmpTemplateManager.cpp
    index ffb3cd8..8f90626 100644
    a b const CParamNode* CCmpTemplateManager::GetTemplate(std::string templateName)  
    187187
    188188            // Show error on the first failure to validate the template
    189189            if (!m_TemplateSchemaValidity[templateName])
    190                 LOGERROR(L"Failed to validate entity template '%hs'", templateName.c_str());
     190                LOGERROR("Failed to validate entity template '%s'", templateName.c_str());
    191191        }
    192192        // Refuse to return invalid templates
    193193        if (!m_TemplateSchemaValidity[templateName])
    const CParamNode* CCmpTemplateManager::GetTemplate(std::string templateName)  
    198198    if (!templateRoot.IsOk())
    199199    {
    200200        // The validator should never let this happen
    201         LOGERROR(L"Invalid root element in entity template '%hs'", templateName.c_str());
     201        LOGERROR("Invalid root element in entity template '%s'", templateName.c_str());
    202202        return NULL;
    203203    }
    204204
  • source/simulation2/components/CCmpUnitMotion.cpp

    diff --git a/source/simulation2/components/CCmpUnitMotion.cpp b/source/simulation2/components/CCmpUnitMotion.cpp
    index 6a4ebda..d24eb12 100644
    a b void CCmpUnitMotion::PathResult(u32 ticket, const ICmpPathfinder::Path& path)  
    814814    }
    815815    else
    816816    {
    817         LOGWARNING(L"unexpected PathResult (%u %d %d)", GetEntityId(), m_State, m_PathState);
     817        LOGWARNING("unexpected PathResult (%u %d %d)", GetEntityId(), m_State, m_PathState);
    818818    }
    819819}
    820820
  • source/simulation2/components/CCmpVisualActor.cpp

    diff --git a/source/simulation2/components/CCmpVisualActor.cpp b/source/simulation2/components/CCmpVisualActor.cpp
    index 52c189b..0e4a003 100644
    a b void CCmpVisualActor::InitSelectionShapeDescriptor(const CParamNode& paramNode)  
    655655            }
    656656            else
    657657            {
    658                 LOGERROR(L"[VisualActor] Cannot apply footprint-based SelectionShape; Footprint component not initialized.");
     658                LOGERROR("[VisualActor] Cannot apply footprint-based SelectionShape; Footprint component not initialized.");
    659659            }
    660660        }
    661661        else if (shapeNode.GetChild("Box").IsOk())
    void CCmpVisualActor::InitSelectionShapeDescriptor(const CParamNode& paramNode)  
    669669        }
    670670        else if (shapeNode.GetChild("Cylinder").IsOk())
    671671        {
    672             LOGWARNING(L"[VisualActor] TODO: Cylinder selection shapes are not yet implemented; defaulting to recursive bounding boxes");
     672            LOGWARNING("[VisualActor] TODO: Cylinder selection shapes are not yet implemented; defaulting to recursive bounding boxes");
    673673        }
    674674        else
    675675        {
    676676            // shouldn't happen by virtue of validation against schema
    677             LOGERROR(L"[VisualActor] No selection shape specified");
     677            LOGERROR("[VisualActor] No selection shape specified");
    678678        }
    679679    }
    680680
  • source/simulation2/components/ICmpVisibility.cpp

    diff --git a/source/simulation2/components/ICmpVisibility.cpp b/source/simulation2/components/ICmpVisibility.cpp
    index f597605..b700f87 100644
    a b public:  
    4343        case ICmpRangeManager::VIS_VISIBLE:
    4444            return ICmpRangeManager::VIS_VISIBLE;
    4545        default:
    46             LOGERROR(L"Received the invalid visibility value %d from the Visibility scripted component!", visibility);
     46            LOGERROR("Received the invalid visibility value %d from the Visibility scripted component!", visibility);
    4747            return ICmpRangeManager::VIS_HIDDEN;
    4848        }
    4949    }
  • source/simulation2/scripting/EngineScriptConversions.cpp

    diff --git a/source/simulation2/scripting/EngineScriptConversions.cpp b/source/simulation2/scripting/EngineScriptConversions.cpp
    index 2f907a3..baeffc6 100644
    a b template<> void ScriptInterface::ToJSVal<IComponent*>(JSContext* cx, JS::Mutable  
    5555    if (!val->NewJSObject(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface, &obj))
    5656    {
    5757        // Report as an error, since scripts really shouldn't try to use unscriptable interfaces
    58         LOGERROR(L"IComponent does not have a scriptable interface");
     58        LOGERROR("IComponent does not have a scriptable interface");
    5959        ret.setUndefined();
    6060        return;
    6161    }
  • source/simulation2/scripting/MessageTypeConversions.cpp

    diff --git a/source/simulation2/scripting/MessageTypeConversions.cpp b/source/simulation2/scripting/MessageTypeConversions.cpp
    index d6a909d..2adb6fe 100644
    a b CMessage* CMessageInterpolate::FromJSVal(ScriptInterface& scriptInterface, JS::H  
    119119
    120120JS::Value CMessageRenderSubmit::ToJSVal(ScriptInterface& UNUSED(scriptInterface)) const
    121121{
    122     LOGWARNING(L"CMessageRenderSubmit::ToJSVal not implemented");
     122    LOGWARNING("CMessageRenderSubmit::ToJSVal not implemented");
    123123    return JS::UndefinedValue();
    124124}
    125125
    126126CMessage* CMessageRenderSubmit::FromJSVal(ScriptInterface& UNUSED(scriptInterface), JS::HandleValue UNUSED(val))
    127127{
    128     LOGWARNING(L"CMessageRenderSubmit::FromJSVal not implemented");
     128    LOGWARNING("CMessageRenderSubmit::FromJSVal not implemented");
    129129    return NULL;
    130130}
    131131
    CMessage* CMessageRenderSubmit::FromJSVal(ScriptInterface& UNUSED(scriptInterfac  
    133133
    134134JS::Value CMessageProgressiveLoad::ToJSVal(ScriptInterface& UNUSED(scriptInterface)) const
    135135{
    136     LOGWARNING(L"CMessageProgressiveLoad::ToJSVal not implemented");
     136    LOGWARNING("CMessageProgressiveLoad::ToJSVal not implemented");
    137137    return JS::UndefinedValue();
    138138}
    139139
    140140CMessage* CMessageProgressiveLoad::FromJSVal(ScriptInterface& UNUSED(scriptInterface), JS::HandleValue UNUSED(val))
    141141{
    142     LOGWARNING(L"CMessageProgressiveLoad::FromJSVal not implemented");
     142    LOGWARNING("CMessageProgressiveLoad::FromJSVal not implemented");
    143143    return NULL;
    144144}
    145145
    CMessage* CMessageProgressiveLoad::FromJSVal(ScriptInterface& UNUSED(scriptInter  
    147147
    148148JS::Value CMessageDeserialized::ToJSVal(ScriptInterface& UNUSED(scriptInterface)) const
    149149{
    150     LOGWARNING(L"CMessageDeserialized::ToJSVal not implemented");
     150    LOGWARNING("CMessageDeserialized::ToJSVal not implemented");
    151151    return JS::UndefinedValue();
    152152}
    153153
    154154CMessage* CMessageDeserialized::FromJSVal(ScriptInterface& UNUSED(scriptInterface), JS::HandleValue UNUSED(val))
    155155{
    156     LOGWARNING(L"CMessageDeserialized::FromJSVal not implemented");
     156    LOGWARNING("CMessageDeserialized::FromJSVal not implemented");
    157157    return NULL;
    158158}
    159159
    CMessage* CMessagePositionChanged::FromJSVal(ScriptInterface& scriptInterface, J  
    237237
    238238JS::Value CMessageInterpolatedPositionChanged::ToJSVal(ScriptInterface& UNUSED(scriptInterface)) const
    239239{
    240     LOGWARNING(L"CMessageInterpolatedPositionChanged::ToJSVal not implemented");
     240    LOGWARNING("CMessageInterpolatedPositionChanged::ToJSVal not implemented");
    241241    return JS::UndefinedValue();
    242242}
    243243
    244244CMessage* CMessageInterpolatedPositionChanged::FromJSVal(ScriptInterface& UNUSED(scriptInterface), JS::HandleValue UNUSED(val))
    245245{
    246     LOGWARNING(L"CMessageInterpolatedPositionChanged::FromJSVal not implemented");
     246    LOGWARNING("CMessageInterpolatedPositionChanged::FromJSVal not implemented");
    247247    return NULL;
    248248}
    249249
    JS::Value CMessageRangeUpdate::ToJSVal(ScriptInterface& scriptInterface) const  
    379379
    380380CMessage* CMessageRangeUpdate::FromJSVal(ScriptInterface& UNUSED(scriptInterface), JS::HandleValue UNUSED(val))
    381381{
    382     LOGWARNING(L"CMessageRangeUpdate::FromJSVal not implemented");
     382    LOGWARNING("CMessageRangeUpdate::FromJSVal not implemented");
    383383    return NULL;
    384384}
    385385
    CMessage* CMessageRangeUpdate::FromJSVal(ScriptInterface& UNUSED(scriptInterface  
    387387
    388388JS::Value CMessagePathResult::ToJSVal(ScriptInterface& UNUSED(scriptInterface)) const
    389389{
    390     LOGWARNING(L"CMessagePathResult::ToJSVal not implemented");
     390    LOGWARNING("CMessagePathResult::ToJSVal not implemented");
    391391    return JS::UndefinedValue();
    392392}
    393393
    394394CMessage* CMessagePathResult::FromJSVal(ScriptInterface& UNUSED(scriptInterface), JS::HandleValue UNUSED(val))
    395395{
    396     LOGWARNING(L"CMessagePathResult::FromJSVal not implemented");
     396    LOGWARNING("CMessagePathResult::FromJSVal not implemented");
    397397    return NULL;
    398398}
    399399
  • source/simulation2/scripting/ScriptComponent.cpp

    diff --git a/source/simulation2/scripting/ScriptComponent.cpp b/source/simulation2/scripting/ScriptComponent.cpp
    index f3ada5b..f2fe1fc 100644
    a b void CComponentTypeScript::HandleMessage(const CMessage& msg, bool global)  
    7373
    7474    JS::RootedValue tmpInstance(cx, m_Instance.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
    7575    if (!m_ScriptInterface.CallFunctionVoid(tmpInstance, name, msgVal))
    76         LOGERROR(L"Script message handler %hs failed", name);
     76        LOGERROR("Script message handler %s failed", name);
    7777}
    7878
    7979void CComponentTypeScript::Serialize(ISerializer& serialize)
    void CComponentTypeScript::Serialize(ISerializer& serialize)  
    9292    {
    9393        JS::RootedValue val(cx);
    9494        if (!m_ScriptInterface.CallFunction(tmpInstance, "Serialize", &val))
    95             LOGERROR(L"Script Serialize call failed");
     95            LOGERROR("Script Serialize call failed");
    9696        serialize.ScriptVal("object", &val);
    9797    }
    9898    else
    void CComponentTypeScript::Deserialize(const CParamNode& paramNode, IDeserialize  
    118118            deserialize.ScriptVal("object", &val);
    119119
    120120        if (!m_ScriptInterface.CallFunctionVoid(tmpInstance, "Deserialize", val))
    121             LOGERROR(L"Script Deserialize call failed");
     121            LOGERROR("Script Deserialize call failed");
    122122    }
    123123    else
    124124    {
  • source/simulation2/scripting/ScriptComponent.h

    diff --git a/source/simulation2/scripting/ScriptComponent.h b/source/simulation2/scripting/ScriptComponent.h
    index 035013c..7268499 100644
    a b public:  
    6464        R ret; \
    6565        if (m_ScriptInterface.CallFunction(tmpInstance, funcname  BOOST_PP_ENUM_TRAILING_PARAMS(i, a), ret)) \
    6666            return ret; \
    67         LOGERROR(L"Error calling component script function %hs", funcname); \
     67        LOGERROR("Error calling component script function %s", funcname); \
    6868        return R(); \
    6969    } \
    7070    BOOST_PP_IF(i, template<, ) BOOST_PP_ENUM_PARAMS(i, typename T) BOOST_PP_IF(i, >, ) \
    public:  
    7575        JS::RootedValue tmpInstance(cx, m_Instance.get()); \
    7676        if (m_ScriptInterface.CallFunctionVoid(tmpInstance, funcname  BOOST_PP_ENUM_TRAILING_PARAMS(i, a))) \
    7777            return; \
    78         LOGERROR(L"Error calling component script function %hs", funcname); \
     78        LOGERROR("Error calling component script function %s", funcname); \
    7979    }
    8080BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
    8181#undef OVERLOADS
  • source/simulation2/serialization/BinarySerializer.cpp

    diff --git a/source/simulation2/serialization/BinarySerializer.cpp b/source/simulation2/serialization/BinarySerializer.cpp
    index 9cc61ac..4878226 100644
    a b static u8 GetArrayType(JSArrayBufferViewType arrayType)  
    4949    case js::ArrayBufferView::TYPE_UINT8_CLAMPED:
    5050        return SCRIPT_TYPED_ARRAY_UINT8_CLAMPED;
    5151    default:
    52         LOGERROR(L"Cannot serialize unrecognized typed array view: %d", arrayType);
     52        LOGERROR("Cannot serialize unrecognized typed array view: %d", arrayType);
    5353        throw PSERROR_Serialize_InvalidScriptValue();
    5454    }
    5555}
    void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val)  
    258258            else
    259259            {
    260260                // Unrecognized class
    261                 LOGERROR(L"Cannot serialise JS objects with unrecognized class '%hs'", jsclass->name);
     261                LOGERROR("Cannot serialise JS objects with unrecognized class '%s'", jsclass->name);
    262262                throw PSERROR_Serialize_InvalidScriptValue();
    263263            }
    264264        }
    void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val)  
    317317            }
    318318        }
    319319
    320         LOGERROR(L"Cannot serialise JS objects of type 'function': %ls", funcname.c_str());
     320        LOGERROR("Cannot serialise JS objects of type 'function': %s", utf8_from_wstring(funcname));
    321321        throw PSERROR_Serialize_InvalidScriptValue();
    322322    }
    323323    case JSTYPE_STRING:
  • source/simulation2/system/ComponentManager.cpp

    diff --git a/source/simulation2/system/ComponentManager.cpp b/source/simulation2/system/ComponentManager.cpp
    index 3e8aef7..0ee90a0 100644
    a b std::vector<IComponent*> CComponentManager::Script_GetComponentsWithInterface(Sc  
    429429CMessage* CComponentManager::ConstructMessage(int mtid, JS::HandleValue data)
    430430{
    431431    if (mtid == MT__Invalid || mtid > (int)m_MessageTypeIdsByName.size()) // (IDs start at 1 so use '>' here)
    432         LOGERROR(L"PostMessage with invalid message type ID '%d'", mtid);
     432        LOGERROR("PostMessage with invalid message type ID '%d'", mtid);
    433433
    434434    if (mtid < MT__LastNative)
    435435    {
    CComponentManager::ComponentTypeId CComponentManager::GetScriptWrapper(Interface  
    672672    for (; iiit != m_InterfaceIdsByName.end(); ++iiit)
    673673        if (iiit->second == iid)
    674674        {
    675             LOGERROR(L"No script wrapper found for interface id %d '%hs'", iid, iiit->first.c_str());
     675            LOGERROR("No script wrapper found for interface id %d '%s'", iid, iiit->first.c_str());
    676676            return CID__Invalid;
    677677        }
    678678
    679     LOGERROR(L"No script wrapper found for interface id %d", iid);
     679    LOGERROR("No script wrapper found for interface id %d", iid);
    680680    return CID__Invalid;
    681681}
    682682
    IComponent* CComponentManager::ConstructComponent(CEntityHandle ent, ComponentTy  
    753753    std::map<ComponentTypeId, ComponentType>::const_iterator it = m_ComponentTypesById.find(cid);
    754754    if (it == m_ComponentTypesById.end())
    755755    {
    756         LOGERROR(L"Invalid component id %d", cid);
     756        LOGERROR("Invalid component id %d", cid);
    757757        return NULL;
    758758    }
    759759
    IComponent* CComponentManager::ConstructComponent(CEntityHandle ent, ComponentTy  
    764764    boost::unordered_map<entity_id_t, IComponent*>& emap1 = m_ComponentsByInterface[ct.iid];
    765765    if (emap1.find(ent.GetId()) != emap1.end())
    766766    {
    767         LOGERROR(L"Multiple components for interface %d", ct.iid);
     767        LOGERROR("Multiple components for interface %d", ct.iid);
    768768        return NULL;
    769769    }
    770770
    IComponent* CComponentManager::ConstructComponent(CEntityHandle ent, ComponentTy  
    780780        m_ScriptInterface.CallConstructor(tmpCtor, argv, &obj);
    781781        if (obj.isNull())
    782782        {
    783             LOGERROR(L"Script component constructor failed");
     783            LOGERROR("Script component constructor failed");
    784784            return NULL;
    785785        }
    786786    }
    entity_id_t CComponentManager::AddEntity(const std::wstring& templateName, entit  
    887887        CComponentManager::ComponentTypeId cid = LookupCID(it->first);
    888888        if (cid == CID__Invalid)
    889889        {
    890             LOGERROR(L"Unrecognised component type name '%hs' in entity template '%ls'", it->first.c_str(), templateName.c_str());
     890            LOGERROR("Unrecognised component type name '%s' in entity template '%s'", it->first, utf8_from_wstring(templateName));
    891891            return INVALID_ENTITY;
    892892        }
    893893
    894894        if (!AddComponent(handle, cid, it->second))
    895895        {
    896             LOGERROR(L"Failed to construct component type name '%hs' in entity template '%ls'", it->first.c_str(), templateName.c_str());
     896            LOGERROR("Failed to construct component type name '%s' in entity template '%s'", it->first, utf8_from_wstring(templateName));
    897897            return INVALID_ENTITY;
    898898        }
    899899        // TODO: maybe we should delete already-constructed components if one of them fails?
    std::vector<std::string> CComponentManager::Script_FindJSONFiles(ScriptInterface  
    12261226    {
    12271227        // Some error reading directory
    12281228        wchar_t error[200];
    1229         LOGERROR(L"Error reading directory '%ls': %ls", cbData.path.string().c_str(), StatusDescription(ret, error, ARRAY_SIZE(error)));
     1229        LOGERROR("Error reading directory '%s': %s", cbData.path.string8(), utf8_from_wstring(StatusDescription(ret, error, ARRAY_SIZE(error))));
    12301230    }
    12311231   
    12321232    return cbData.templates;
  • source/simulation2/system/ComponentManagerSerialization.cpp

    diff --git a/source/simulation2/system/ComponentManagerSerialization.cpp b/source/simulation2/system/ComponentManagerSerialization.cpp
    index 78b2cd3..053b3c6 100644
    a b bool CComponentManager::DeserializeState(std::istream& stream)  
    322322            ComponentTypeId ctid = LookupCID(ctname);
    323323            if (ctid == CID__Invalid)
    324324            {
    325                 LOGERROR(L"Deserialization saw unrecognised component type '%hs'", ctname.c_str());
     325                LOGERROR("Deserialization saw unrecognised component type '%s'", ctname.c_str());
    326326                return false;
    327327            }
    328328
    bool CComponentManager::DeserializeState(std::istream& stream)  
    349349            ComponentTypeId ctid = LookupCID(ctname);
    350350            if (ctid == CID__Invalid)
    351351            {
    352                 LOGERROR(L"Deserialization saw unrecognised component type '%hs'", ctname.c_str());
     352                LOGERROR("Deserialization saw unrecognised component type '%s'", ctname.c_str());
    353353                return false;
    354354            }
    355355
    bool CComponentManager::DeserializeState(std::istream& stream)  
    379379
    380380        if (stream.peek() != EOF)
    381381        {
    382             LOGERROR(L"Deserialization didn't reach EOF");
     382            LOGERROR("Deserialization didn't reach EOF");
    383383            return false;
    384384        }
    385385
    bool CComponentManager::DeserializeState(std::istream& stream)  
    391391    }
    392392    catch (PSERROR_Deserialize& e)
    393393    {
    394         LOGERROR(L"Deserialization failed: %hs", e.what());
     394        LOGERROR("Deserialization failed: %s", e.what());
    395395        return false;
    396396    }
    397397}
  • source/simulation2/system/ParamNode.cpp

    diff --git a/source/simulation2/system/ParamNode.cpp b/source/simulation2/system/ParamNode.cpp
    index f966004..2e4b172 100644
    a b void CParamNode::ApplyLayer(const XMBFile& xmb, const XMBElement& element, const  
    123123                        if (tokenIt != tokens.end())
    124124                            tokens.erase(tokenIt);
    125125                        else
    126                             LOGWARNING(L"[ParamNode] Could not remove token '%ls' from node '%hs'%ls; not present in list nor inherited (possible typo?)",
    127                                 newTokens[i].substr(1).c_str(), name.c_str(), sourceIdentifier ? (L" in '" + std::wstring(sourceIdentifier) + L"'").c_str() : L"");
     126                            LOGWARNING("[ParamNode] Could not remove token '%s' from node '%s'%s; not present in list nor inherited (possible typo?)",
     127                                utf8_from_wstring(newTokens[i].substr(1)), name, sourceIdentifier ? (" in '" + utf8_from_wstring(sourceIdentifier) + "'").c_str() : "");
    128128                    }
    129129                    else
    130130                    {
  • source/simulation2/tests/test_ComponentManager.h

    diff --git a/source/simulation2/tests/test_ComponentManager.h b/source/simulation2/tests/test_ComponentManager.h
    index c84fe34..9c92b4b 100644
    a b public:  
    109109        {
    110110            TestLogger log;
    111111            TS_ASSERT(! man.AddComponent(hnd1, 12345, noParam));
    112             TS_ASSERT_WSTR_CONTAINS(log.GetOutput(), L"ERROR: Invalid component id 12345");
     112            TS_ASSERT_STR_CONTAINS(log.GetOutput(), "ERROR: Invalid component id 12345");
    113113        }
    114114
    115115        {
    116116            TestLogger log;
    117117            TS_ASSERT(! man.AddComponent(hnd1, CID_Test1B, noParam));
    118             TS_ASSERT_WSTR_CONTAINS(log.GetOutput(), L"ERROR: Multiple components for interface ");
     118            TS_ASSERT_STR_CONTAINS(log.GetOutput(), "ERROR: Multiple components for interface ");
    119119        }
    120120    }
    121121
    public:  
    347347            // In SpiderMonkey 1.6, JS_ReportError calls the error reporter even if it's inside
    348348            // a try{} in the script; in recent versions (not sure when it changed) it doesn't
    349349            // so the error here won't get reported.
    350             TS_ASSERT_WSTR_NOT_CONTAINS(log.GetOutput(), L"ERROR: JavaScript error: simulation/components/error.js line 4\nInvalid interface id");
     350            TS_ASSERT_STR_NOT_CONTAINS(log.GetOutput(), "ERROR: JavaScript error: simulation/components/error.js line 4\nInvalid interface id");
    351351        }
    352352    }
    353353
  • source/soundmanager/SoundManager.cpp

    diff --git a/source/soundmanager/SoundManager.cpp b/source/soundmanager/SoundManager.cpp
    index daa6f3e..48d0917 100644
    a b void ISoundManager::CloseGame()  
    204204
    205205void CSoundManager::al_ReportError(ALenum err, const char* caller, int line)
    206206{
    207     LOGERROR(L"OpenAL error: %hs; called from %hs (line %d)\n", alGetString(err), caller, line);
     207    LOGERROR("OpenAL error: %s; called from %s (line %d)\n", alGetString(err), caller, line);
    208208}
    209209
    210210void CSoundManager::al_check(const char* caller, int line)
    void CSoundManager::al_check(const char* caller, int line)  
    216216
    217217Status CSoundManager::ReloadChangedFiles(const VfsPath& UNUSED(path))
    218218{
    219 //  LOGERROR(L"GUI file '%ls' changed - reloading page", path.string().c_str());
     219//  LOGERROR("GUI file '%s' changed - reloading page", path.string8());
    220220
    221221    return INFO::OK;
    222222}
    Status CSoundManager::AlcInit()  
    338338            }
    339339            else
    340340            {
    341                 LOGERROR(L"error in gensource = %d", err);
     341                LOGERROR("error in gensource = %d", err);
    342342            }
    343343            delete[] sourceList;
    344344        }
    Status CSoundManager::AlcInit()  
    354354        debug_printf(L"Sound: AlcInit success, using %hs\n", dev_name);
    355355    else
    356356    {
    357         LOGERROR(L"Sound: AlcInit failed, m_Device=%p m_Context=%p dev_name=%hs err=%x\n", m_Device, m_Context, dev_name, err);
     357        LOGERROR("Sound: AlcInit failed, m_Device=%p m_Context=%p dev_name=%s err=%x\n", (void *)m_Device, (void *)m_Context, dev_name, err);
    358358
    359359// FIXME Hack to get around exclusive access to the sound device
    360360#if OS_UNIX
    void CSoundManager::PlayAsGroup(const VfsPath& groupPath, CVector3D sourcePos, e  
    654654        group = new CSoundGroup();
    655655        if (!group->LoadSoundGroup(L"audio/" + groupPath.string()))
    656656        {
    657             LOGERROR(L"Failed to load sound group '%ls'", groupPath.string().c_str());
     657            LOGERROR("Failed to load sound group '%s'", groupPath.string8());
    658658            delete group;
    659659            group = NULL;
    660660        }
  • source/soundmanager/data/OggData.cpp

    diff --git a/source/soundmanager/data/OggData.cpp b/source/soundmanager/data/OggData.cpp
    index 6165c5c..26321fc 100644
    a b bool COggData::InitOggFile(const VfsPath& itemPath)  
    7878           
    7979            if(alGetError() != AL_NO_ERROR)
    8080            {
    81                 LOGERROR( L"- Error creating initial buffer !!\n");
     81                LOGERROR( "- Error creating initial buffer !!\n");
    8282                return false;
    8383            }
    8484            else
  • source/soundmanager/data/SoundData.cpp

    diff --git a/source/soundmanager/data/SoundData.cpp b/source/soundmanager/data/SoundData.cpp
    index e3f6173..80bb547 100644
    a b CSoundData* CSoundData::SoundDataFromOgg(const VfsPath& itemPath)  
    107107    }
    108108    else
    109109    {
    110         LOGERROR(L"could not initialize ogg data at %ls", itemPath.string().c_str());
     110        LOGERROR("could not initialize ogg data at %s", itemPath.string8());
    111111        delete oggAnswer;
    112112    }
    113113
  • source/soundmanager/items/CSoundBase.cpp

    diff --git a/source/soundmanager/items/CSoundBase.cpp b/source/soundmanager/items/CSoundBase.cpp
    index e7dce37..8486114 100644
    a b bool CSoundBase::InitOpenAL()  
    112112    }
    113113    else
    114114    {
    115 //      LOGERROR(L"Source not allocated by SoundManager\n", 0);
     115//      LOGERROR("Source not allocated by SoundManager\n", 0);
    116116    }
    117117    return false;
    118118}
  • source/soundmanager/scripting/SoundGroup.cpp

    diff --git a/source/soundmanager/scripting/SoundGroup.cpp b/source/soundmanager/scripting/SoundGroup.cpp
    index 2969e2e..0dc524c 100644
    a b void CSoundGroup::UploadPropertiesAndPlay(size_t theIndex, const CVector3D& posi  
    197197            itemRollOff = 0;
    198198       
    199199        if ( sndData->IsStereo() )
    200             LOGWARNING( L"OpenAL: stereo sounds can't be positioned: %ls", sndData->GetFileName()->string().c_str() );
     200            LOGWARNING( "OpenAL: stereo sounds can't be positioned: %s", sndData->GetFileName()->string8() );
    201201
    202202        hSound->SetLocation(CVector3D((sndDist * sin(offSet)), 0, - sndDist * cos(offSet)));
    203203        hSound->SetRollOff(itemRollOff);
    static void HandleError(const CStrW& message, const VfsPath& pathname, Status er  
    227227{
    228228    if (err == ERR::AGAIN)
    229229        return; // open failed because sound is disabled (don't log this)
    230     LOGERROR(L"%ls: pathname=%ls, error=%ls", message.c_str(), pathname.string().c_str(), ErrorString(err));
     230    LOGERROR("%s: pathname=%s, error=%s", utf8_from_wstring(message), pathname.string8(), utf8_from_wstring(ErrorString(err)));
    231231}
    232232
    233233void CSoundGroup::PlayNext(const CVector3D& position, entity_id_t source)
    bool CSoundGroup::LoadSoundGroup(const VfsPath& pathnameXML)  
    320320
    321321    if (root.GetNodeName() != el_soundgroup)
    322322    {
    323         LOGERROR(L"Invalid SoundGroup format (unrecognised root element '%hs')", XeroFile.GetElementString(root.GetNodeName()).c_str());
     323        LOGERROR("Invalid SoundGroup format (unrecognised root element '%s')", XeroFile.GetElementString(root.GetNodeName()).c_str());
    324324        return false;
    325325    }
    326326   
  • source/test_setup.cpp

    diff --git a/source/test_setup.cpp b/source/test_setup.cpp
    index 448a650..c75f43a 100644
    a b static MiscSetup miscSetup;  
    100100
    101101// Definition of functions from lib/self_test.h
    102102
     103bool ts_str_contains(const std::string& str1, const std::string& str2)
     104{
     105    return str1.find(str2) != str1.npos;
     106}
     107
    103108bool ts_str_contains(const std::wstring& str1, const std::wstring& str2)
    104109{
    105110    return str1.find(str2) != str1.npos;
  • new file source/third_party/cppformat/format.cpp

    diff --git a/source/third_party/cppformat/format.cpp b/source/third_party/cppformat/format.cpp
    new file mode 100644
    index 0000000..580d6cd
    - +  
     1/*
     2 * Slightly modified version of cppformat, by Wildfire Games, for 0 A.D.
     3 * Based on cppformat v0.11.0 from https://github.com/cppformat/cppformat
     4 */
     5
     6/*
     7 Formatting library for C++
     8
     9 Copyright (c) 2012 - 2014, Victor Zverovich
     10 All rights reserved.
     11
     12 Redistribution and use in source and binary forms, with or without
     13 modification, are permitted provided that the following conditions are met:
     14
     15 1. Redistributions of source code must retain the above copyright notice, this
     16    list of conditions and the following disclaimer.
     17 2. Redistributions in binary form must reproduce the above copyright notice,
     18    this list of conditions and the following disclaimer in the documentation
     19    and/or other materials provided with the distribution.
     20
     21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
     22 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
     25 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     26 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     27 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     28 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     30 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31 */
     32
     33// Disable useless MSVC warnings.
     34#undef _CRT_SECURE_NO_WARNINGS
     35#define _CRT_SECURE_NO_WARNINGS
     36#undef _SCL_SECURE_NO_WARNINGS
     37#define _SCL_SECURE_NO_WARNINGS
     38
     39#include "format.h"
     40
     41#include <string.h>
     42
     43#include <cctype>
     44#include <cerrno>
     45#include <climits>
     46#include <cmath>
     47#include <cstdarg>
     48
     49#ifdef _WIN32
     50# define WIN32_LEAN_AND_MEAN
     51# ifdef __MINGW32__
     52#  include <cstring>
     53# endif
     54# include <windows.h>
     55# undef ERROR
     56#endif
     57
     58using fmt::LongLong;
     59using fmt::ULongLong;
     60using fmt::internal::Arg;
     61
     62#ifdef _MSC_VER
     63# pragma warning(push)
     64# pragma warning(disable: 4127) // conditional expression is constant
     65#endif
     66
     67namespace {
     68
     69#ifndef _MSC_VER
     70
     71// Portable version of signbit.
     72// When compiled in C++11 mode signbit is no longer a macro but a function
     73// defined in namespace std and the macro is undefined.
     74inline int getsign(double x) {
     75#ifdef signbit
     76  return signbit(x);
     77#else
     78  return std::signbit(x);
     79#endif
     80}
     81
     82// Portable version of isinf.
     83#ifdef isinf
     84inline int isinfinity(double x) { return isinf(x); }
     85inline int isinfinity(long double x) { return isinf(x); }
     86#else
     87inline int isinfinity(double x) { return std::isinf(x); }
     88inline int isinfinity(long double x) { return std::isinf(x); }
     89#endif
     90
     91#define FMT_SNPRINTF snprintf
     92
     93#else  // _MSC_VER
     94
     95inline int getsign(double value) {
     96  if (value < 0) return 1;
     97  if (value == value) return 0;
     98  int dec = 0, sign = 0;
     99  char buffer[2];  // The buffer size must be >= 2 or _ecvt_s will fail.
     100  _ecvt_s(buffer, sizeof(buffer), value, 0, &dec, &sign);
     101  return sign;
     102}
     103
     104inline int isinfinity(double x) { return !_finite(x); }
     105
     106inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
     107  va_list args;
     108  va_start(args, format);
     109  int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
     110  va_end(args);
     111  return result;
     112}
     113#define FMT_SNPRINTF fmt_snprintf
     114
     115#endif  // _MSC_VER
     116
     117template <typename T>
     118struct IsLongDouble { enum {VALUE = 0}; };
     119
     120template <>
     121struct IsLongDouble<long double> { enum {VALUE = 1}; };
     122
     123// Checks if a value fits in int - used to avoid warnings about comparing
     124// signed and unsigned integers.
     125template <bool IsSigned>
     126struct IntChecker {
     127  template <typename T>
     128  static bool fits_in_int(T value) {
     129    unsigned max = INT_MAX;
     130    return value <= max;
     131  }
     132};
     133
     134template <>
     135struct IntChecker<true> {
     136  template <typename T>
     137  static bool fits_in_int(T value) {
     138    return value >= INT_MIN && value <= INT_MAX;
     139  }
     140};
     141
     142const char RESET_COLOR[] = "\x1b[0m";
     143
     144typedef void (*FormatFunc)(fmt::Writer &, int , fmt::StringRef);
     145
     146void report_error(FormatFunc func,
     147    int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
     148  try {
     149    fmt::Writer full_message;
     150    func(full_message, error_code, message); // TODO: make sure this doesn't throw
     151    std::fwrite(full_message.c_str(), full_message.size(), 1, stderr);
     152    std::fputc('\n', stderr);
     153  } catch (...) {}
     154}
     155
     156const Arg DUMMY_ARG = {Arg::INT, {0}};
     157
     158// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
     159class IsZeroInt : public fmt::internal::ArgVisitor<IsZeroInt, bool> {
     160 public:
     161  template <typename T>
     162  bool visit_any_int(T value) { return value == 0; }
     163};
     164
     165// Parses an unsigned integer advancing s to the end of the parsed input.
     166// This function assumes that the first character of s is a digit.
     167template <typename Char>
     168int parse_nonnegative_int(
     169    const Char *&s, const char *&error) FMT_NOEXCEPT(true) {
     170  assert('0' <= *s && *s <= '9');
     171  unsigned value = 0;
     172  do {
     173    unsigned new_value = value * 10 + (*s++ - '0');
     174    // Check if value wrapped around.
     175    value = new_value >= value ? new_value : UINT_MAX;
     176  } while ('0' <= *s && *s <= '9');
     177  if (value > INT_MAX) {
     178    if (!error)
     179      error = "number is too big in format";
     180    return 0;
     181  }
     182  return value;
     183}
     184
     185template <typename Char>
     186const Char *find_closing_brace(const Char *s, int num_open_braces = 1) {
     187  for (int n = num_open_braces; *s; ++s) {
     188    if (*s == '{') {
     189      ++n;
     190    } else if (*s == '}') {
     191      if (--n == 0)
     192        return s;
     193    }
     194  }
     195  throw fmt::FormatError("unmatched '{' in format");
     196}
     197
     198// Checks if an argument is a valid printf width specifier and sets
     199// left alignment if it is negative.
     200class WidthHandler : public fmt::internal::ArgVisitor<WidthHandler, unsigned> {
     201 private:
     202  fmt::FormatSpec &spec_;
     203
     204 public:
     205  explicit WidthHandler(fmt::FormatSpec &spec) : spec_(spec) {}
     206
     207  unsigned visit_unhandled_arg() {
     208    throw fmt::FormatError("width is not integer");
     209  }
     210
     211  template <typename T>
     212  unsigned visit_any_int(T value) {
     213    typedef typename fmt::internal::IntTraits<T>::MainType UnsignedType;
     214    UnsignedType width = value;
     215    if (fmt::internal::is_negative(value)) {
     216      spec_.align_ = fmt::ALIGN_LEFT;
     217      width = 0 - width;
     218    }
     219    if (width > INT_MAX)
     220      throw fmt::FormatError("number is too big in format");
     221    return static_cast<unsigned>(width);
     222  }
     223};
     224
     225class PrecisionHandler :
     226    public fmt::internal::ArgVisitor<PrecisionHandler, int> {
     227 public:
     228  unsigned visit_unhandled_arg() {
     229    throw fmt::FormatError("precision is not integer");
     230  }
     231
     232  template <typename T>
     233  int visit_any_int(T value) {
     234    if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
     235      throw fmt::FormatError("number is too big in format");
     236    return static_cast<int>(value);
     237  }
     238};
     239
     240// Converts an integer argument to type T.
     241template <typename T>
     242class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> {
     243 private:
     244  fmt::internal::Arg &arg_;
     245  wchar_t type_;
     246
     247 public:
     248  ArgConverter(fmt::internal::Arg &arg, wchar_t type)
     249    : arg_(arg), type_(type) {}
     250
     251  template <typename U>
     252  void visit_any_int(U value) {
     253    bool is_signed = type_ == 'd' || type_ == 'i';
     254    using fmt::internal::Arg;
     255    if (sizeof(T) <= sizeof(int)) {
     256      if (is_signed) {
     257        arg_.type = Arg::INT;
     258        arg_.int_value = static_cast<int>(static_cast<T>(value));
     259      } else {
     260        arg_.type = Arg::UINT;
     261        arg_.uint_value = static_cast<unsigned>(
     262            static_cast<typename fmt::internal::MakeUnsigned<T>::Type>(value));
     263      }
     264    } else {
     265      if (is_signed) {
     266        arg_.type = Arg::LONG_LONG;
     267        arg_.long_long_value =
     268            static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
     269      } else {
     270        arg_.type = Arg::ULONG_LONG;
     271        arg_.ulong_long_value =
     272            static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
     273      }
     274    }
     275  }
     276};
     277
     278// Converts an integer argument to char.
     279class CharConverter : public fmt::internal::ArgVisitor<CharConverter, void> {
     280 private:
     281  fmt::internal::Arg &arg_;
     282
     283 public:
     284  explicit CharConverter(fmt::internal::Arg &arg) : arg_(arg) {}
     285
     286  template <typename T>
     287  void visit_any_int(T value) {
     288    arg_.type = Arg::CHAR;
     289    arg_.int_value = static_cast<char>(value);
     290  }
     291};
     292
     293// This function template is used to prevent compile errors when handling
     294// incompatible string arguments, e.g. handling a wide string in a narrow
     295// string formatter.
     296template <typename Char>
     297Arg::StringValue<Char> ignore_incompatible_str(Arg::StringValue<wchar_t>);
     298
     299template <>
     300inline Arg::StringValue<char> ignore_incompatible_str(
     301    Arg::StringValue<wchar_t>) { return Arg::StringValue<char>(); }
     302
     303template <>
     304inline Arg::StringValue<wchar_t> ignore_incompatible_str(
     305    Arg::StringValue<wchar_t> s) { return s; }
     306}  // namespace
     307
     308void fmt::SystemError::init(
     309    int error_code, StringRef format_str, const ArgList &args) {
     310  error_code_ = error_code;
     311  Writer w;
     312  internal::format_system_error(w, error_code, format(format_str, args));
     313  std::runtime_error &base = *this;
     314  base = std::runtime_error(w.str());
     315}
     316
     317template <typename T>
     318int fmt::internal::CharTraits<char>::format_float(
     319    char *buffer, std::size_t size, const char *format,
     320    unsigned width, int precision, T value) {
     321  if (width == 0) {
     322    return precision < 0 ?
     323        FMT_SNPRINTF(buffer, size, format, value) :
     324        FMT_SNPRINTF(buffer, size, format, precision, value);
     325  }
     326  return precision < 0 ?
     327      FMT_SNPRINTF(buffer, size, format, width, value) :
     328      FMT_SNPRINTF(buffer, size, format, width, precision, value);
     329}
     330
     331template <typename T>
     332int fmt::internal::CharTraits<wchar_t>::format_float(
     333    wchar_t *buffer, std::size_t size, const wchar_t *format,
     334    unsigned width, int precision, T value) {
     335  if (width == 0) {
     336    return precision < 0 ?
     337        swprintf(buffer, size, format, value) :
     338        swprintf(buffer, size, format, precision, value);
     339  }
     340  return precision < 0 ?
     341      swprintf(buffer, size, format, width, value) :
     342      swprintf(buffer, size, format, width, precision, value);
     343}
     344
     345const char fmt::internal::DIGITS[] =
     346    "0001020304050607080910111213141516171819"
     347    "2021222324252627282930313233343536373839"
     348    "4041424344454647484950515253545556575859"
     349    "6061626364656667686970717273747576777879"
     350    "8081828384858687888990919293949596979899";
     351
     352#define FMT_POWERS_OF_10(factor) \
     353  factor * 10, \
     354  factor * 100, \
     355  factor * 1000, \
     356  factor * 10000, \
     357  factor * 100000, \
     358  factor * 1000000, \
     359  factor * 10000000, \
     360  factor * 100000000, \
     361  factor * 1000000000
     362
     363const uint32_t fmt::internal::POWERS_OF_10_32[] = {0, FMT_POWERS_OF_10(1)};
     364const uint64_t fmt::internal::POWERS_OF_10_64[] = {
     365  0,
     366  FMT_POWERS_OF_10(1),
     367  FMT_POWERS_OF_10(ULongLong(1000000000)),
     368  // Multiply several constants instead of using a single long long constant
     369  // to avoid warnings about C++98 not supporting long long.
     370  ULongLong(1000000000) * ULongLong(1000000000) * 10
     371};
     372
     373void fmt::internal::report_unknown_type(char code, const char *type) {
     374  if (std::isprint(static_cast<unsigned char>(code))) {
     375    throw fmt::FormatError(
     376        fmt::format("unknown format code '{}' for {}", code, type));
     377  }
     378  throw fmt::FormatError(
     379      fmt::format("unknown format code '\\x{:02x}' for {}",
     380        static_cast<unsigned>(code), type));
     381}
     382
     383#ifdef _WIN32
     384
     385fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
     386  int length = MultiByteToWideChar(
     387      CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, 0, 0);
     388  static const char ERROR[] = "cannot convert string from UTF-8 to UTF-16";
     389  if (length == 0)
     390    throw WindowsError(GetLastError(), ERROR);
     391  buffer_.resize(length);
     392  length = MultiByteToWideChar(
     393    CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, &buffer_[0], length);
     394  if (length == 0)
     395    throw WindowsError(GetLastError(), ERROR);
     396}
     397
     398fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
     399  if (int error_code = convert(s)) {
     400    throw WindowsError(error_code,
     401        "cannot convert string from UTF-16 to UTF-8");
     402  }
     403}
     404
     405int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) {
     406  int length = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, 0, 0, 0, 0);
     407  if (length == 0)
     408    return GetLastError();
     409  buffer_.resize(length);
     410  length = WideCharToMultiByte(
     411    CP_UTF8, 0, s.c_str(), -1, &buffer_[0], length, 0, 0);
     412  if (length == 0)
     413    return GetLastError();
     414  return 0;
     415}
     416
     417void fmt::WindowsError::init(
     418    int error_code, StringRef format_str, const ArgList &args) {
     419  error_code_ = error_code;
     420  Writer w;
     421  internal::format_windows_error(w, error_code, format(format_str, args));
     422  std::runtime_error &base = *this;
     423  base = std::runtime_error(w.str());
     424}
     425
     426#endif
     427
     428int fmt::internal::safe_strerror(
     429    int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT(true) {
     430  assert(buffer != 0 && buffer_size != 0);
     431  int result = 0;
     432#ifdef _GNU_SOURCE
     433  char *message = strerror_r(error_code, buffer, buffer_size);
     434  // If the buffer is full then the message is probably truncated.
     435  if (message == buffer && strlen(buffer) == buffer_size - 1)
     436    result = ERANGE;
     437  buffer = message;
     438#elif defined(__MINGW32__)
     439  errno = 0;
     440  (void)buffer_size;
     441  buffer = strerror(error_code);
     442  result = errno;
     443#elif defined(_WIN32)
     444  result = strerror_s(buffer, buffer_size, error_code);
     445  // If the buffer is full then the message is probably truncated.
     446  if (result == 0 && std::strlen(buffer) == buffer_size - 1)
     447    result = ERANGE;
     448#else
     449  result = strerror_r(error_code, buffer, buffer_size);
     450  if (result == -1)
     451    result = errno;  // glibc versions before 2.13 return result in errno.
     452#endif
     453  return result;
     454}
     455
     456void fmt::internal::format_system_error(
     457    fmt::Writer &out, int error_code, fmt::StringRef message) {
     458  Array<char, INLINE_BUFFER_SIZE> buffer;
     459  buffer.resize(INLINE_BUFFER_SIZE);
     460  char *system_message = 0;
     461  for (;;) {
     462    system_message = &buffer[0];
     463    int result = safe_strerror(error_code, system_message, buffer.size());
     464    if (result == 0)
     465      break;
     466    if (result != ERANGE) {
     467      // Can't get error message, report error code instead.
     468      out << message << ": error code = " << error_code;
     469      return;
     470    }
     471    buffer.resize(buffer.size() * 2);
     472  }
     473  out << message << ": " << system_message;
     474}
     475
     476#ifdef _WIN32
     477void fmt::internal::format_windows_error(
     478    fmt::Writer &out, int error_code, fmt::StringRef message) {
     479  class String {
     480   private:
     481    LPWSTR str_;
     482
     483   public:
     484    String() : str_() {}
     485    ~String() { LocalFree(str_); }
     486    LPWSTR *ptr() { return &str_; }
     487    LPCWSTR c_str() const { return str_; }
     488  };
     489  String system_message;
     490  if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
     491      FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
     492      error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
     493      reinterpret_cast<LPWSTR>(system_message.ptr()), 0, 0)) {
     494    UTF16ToUTF8 utf8_message;
     495    if (!utf8_message.convert(system_message.c_str())) {
     496      out << message << ": " << utf8_message;
     497      return;
     498    }
     499  }
     500  // Can't get error message, report error code instead.
     501  out << message << ": error code = " << error_code;
     502}
     503#endif
     504
     505// An argument formatter.
     506template <typename Char>
     507class fmt::internal::ArgFormatter :
     508    public fmt::internal::ArgVisitor<fmt::internal::ArgFormatter<Char>, void> {
     509 private:
     510  fmt::BasicFormatter<Char> &formatter_;
     511  fmt::BasicWriter<Char> &writer_;
     512  fmt::FormatSpec &spec_;
     513  const Char *format_;
     514
     515 public:
     516  ArgFormatter(
     517      fmt::BasicFormatter<Char> &f,fmt::FormatSpec &s, const Char *fmt)
     518  : formatter_(f), writer_(f.writer()), spec_(s), format_(fmt) {}
     519
     520  template <typename T>
     521  void visit_any_int(T value) { writer_.write_int(value, spec_); }
     522
     523  template <typename T>
     524  void visit_any_double(T value) { writer_.write_double(value, spec_); }
     525
     526  void visit_char(int value) {
     527    if (spec_.type_ && spec_.type_ != 'c') {
     528      spec_.flags_ |= CHAR_FLAG;
     529      writer_.write_int(value, spec_);
     530      return;
     531    }
     532    if (spec_.align_ == ALIGN_NUMERIC || spec_.flags_ != 0)
     533      throw FormatError("invalid format specifier for char");
     534    typedef typename fmt::BasicWriter<Char>::CharPtr CharPtr;
     535    CharPtr out = CharPtr();
     536    if (spec_.width_ > 1) {
     537      Char fill = static_cast<Char>(spec_.fill());
     538      out = writer_.grow_buffer(spec_.width_);
     539      if (spec_.align_ == fmt::ALIGN_RIGHT) {
     540        std::fill_n(out, spec_.width_ - 1, fill);
     541        out += spec_.width_ - 1;
     542      } else if (spec_.align_ == fmt::ALIGN_CENTER) {
     543        out = writer_.fill_padding(out, spec_.width_, 1, fill);
     544      } else {
     545        std::fill_n(out + 1, spec_.width_ - 1, fill);
     546      }
     547    } else {
     548      out = writer_.grow_buffer(1);
     549    }
     550    *out = static_cast<Char>(value);
     551  }
     552
     553  void visit_string(Arg::StringValue<char> value) {
     554    writer_.write_str(value, spec_);
     555  }
     556  void visit_wstring(Arg::StringValue<wchar_t> value) {
     557    writer_.write_str(ignore_incompatible_str<Char>(value), spec_);
     558  }
     559
     560  void visit_pointer(const void *value) {
     561    if (spec_.type_ && spec_.type_ != 'p')
     562      fmt::internal::report_unknown_type(spec_.type_, "pointer");
     563    spec_.flags_ = fmt::HASH_FLAG;
     564    spec_.type_ = 'x';
     565    writer_.write_int(reinterpret_cast<uintptr_t>(value), spec_);
     566  }
     567
     568  void visit_custom(Arg::CustomValue c) {
     569    c.format(&formatter_, c.value, format_);
     570  }
     571};
     572
     573template <typename Char>
     574void fmt::internal::FormatErrorReporter<Char>::operator()(
     575        const Char *s, fmt::StringRef message) const {
     576  if (find_closing_brace(s, num_open_braces))
     577    throw fmt::FormatError(message);
     578}
     579
     580// Fills the padding around the content and returns the pointer to the
     581// content area.
     582template <typename Char>
     583typename fmt::BasicWriter<Char>::CharPtr
     584  fmt::BasicWriter<Char>::fill_padding(CharPtr buffer,
     585    unsigned total_size, std::size_t content_size, wchar_t fill) {
     586  std::size_t padding = total_size - content_size;
     587  std::size_t left_padding = padding / 2;
     588  Char fill_char = static_cast<Char>(fill);
     589  std::fill_n(buffer, left_padding, fill_char);
     590  buffer += left_padding;
     591  CharPtr content = buffer;
     592  std::fill_n(buffer + content_size, padding - left_padding, fill_char);
     593  return content;
     594}
     595
     596template <typename Char>
     597template <typename T>
     598void fmt::BasicWriter<Char>::write_double(T value, const FormatSpec &spec) {
     599  // Check type.
     600  char type = spec.type();
     601  bool upper = false;
     602  switch (type) {
     603  case 0:
     604    type = 'g';
     605    break;
     606  case 'e': case 'f': case 'g': case 'a':
     607    break;
     608  case 'F':
     609#ifdef _MSC_VER
     610    // MSVC's printf doesn't support 'F'.
     611    type = 'f';
     612#endif
     613    // Fall through.
     614  case 'E': case 'G': case 'A':
     615    upper = true;
     616    break;
     617  default:
     618    internal::report_unknown_type(type, "double");
     619    break;
     620  }
     621
     622  char sign = 0;
     623  // Use getsign instead of value < 0 because the latter is always
     624  // false for NaN.
     625  if (getsign(static_cast<double>(value))) {
     626    sign = '-';
     627    value = -value;
     628  } else if (spec.flag(SIGN_FLAG)) {
     629    sign = spec.flag(PLUS_FLAG) ? '+' : ' ';
     630  }
     631
     632  if (value != value) {
     633    // Format NaN ourselves because sprintf's output is not consistent
     634    // across platforms.
     635    std::size_t size = 4;
     636    const char *nan = upper ? " NAN" : " nan";
     637    if (!sign) {
     638      --size;
     639      ++nan;
     640    }
     641    CharPtr out = write_str(nan, size, spec);
     642    if (sign)
     643      *out = sign;
     644    return;
     645  }
     646
     647  if (isinfinity(value)) {
     648    // Format infinity ourselves because sprintf's output is not consistent
     649    // across platforms.
     650    std::size_t size = 4;
     651    const char *inf = upper ? " INF" : " inf";
     652    if (!sign) {
     653      --size;
     654      ++inf;
     655    }
     656    CharPtr out = write_str(inf, size, spec);
     657    if (sign)
     658      *out = sign;
     659    return;
     660  }
     661
     662  std::size_t offset = buffer_.size();
     663  unsigned width = spec.width();
     664  if (sign) {
     665    buffer_.reserve(buffer_.size() + (std::max)(width, 1u));
     666    if (width > 0)
     667      --width;
     668    ++offset;
     669  }
     670
     671  // Build format string.
     672  enum { MAX_FORMAT_SIZE = 10}; // longest format: %#-*.*Lg
     673  Char format[MAX_FORMAT_SIZE];
     674  Char *format_ptr = format;
     675  *format_ptr++ = '%';
     676  unsigned width_for_sprintf = width;
     677  if (spec.flag(HASH_FLAG))
     678    *format_ptr++ = '#';
     679  if (spec.align() == ALIGN_CENTER) {
     680    width_for_sprintf = 0;
     681  } else {
     682    if (spec.align() == ALIGN_LEFT)
     683      *format_ptr++ = '-';
     684    if (width != 0)
     685      *format_ptr++ = '*';
     686  }
     687  if (spec.precision() >= 0) {
     688    *format_ptr++ = '.';
     689    *format_ptr++ = '*';
     690  }
     691  if (IsLongDouble<T>::VALUE)
     692    *format_ptr++ = 'L';
     693  *format_ptr++ = type;
     694  *format_ptr = '\0';
     695
     696  // Format using snprintf.
     697  Char fill = static_cast<Char>(spec.fill());
     698  for (;;) {
     699    std::size_t size = buffer_.capacity() - offset;
     700#ifdef _MSC_VER
     701    // MSVC's vsnprintf_s doesn't work with zero size, so reserve
     702    // space for at least one extra character to make the size non-zero.
     703    // Note that the buffer's capacity will increase by more than 1.
     704    if (size == 0) {
     705      buffer_.reserve(offset + 1);
     706      size = buffer_.capacity() - offset;
     707    }
     708#endif
     709    Char *start = &buffer_[offset];
     710    int n = internal::CharTraits<Char>::format_float(
     711        start, size, format, width_for_sprintf, spec.precision(), value);
     712    if (n >= 0 && offset + n < buffer_.capacity()) {
     713      if (sign) {
     714        if ((spec.align() != ALIGN_RIGHT && spec.align() != ALIGN_DEFAULT) ||
     715            *start != ' ') {
     716          *(start - 1) = sign;
     717          sign = 0;
     718        } else {
     719          *(start - 1) = fill;
     720        }
     721        ++n;
     722      }
     723      if (spec.align() == ALIGN_CENTER &&
     724          spec.width() > static_cast<unsigned>(n)) {
     725        unsigned width = spec.width();
     726        CharPtr p = grow_buffer(width);
     727        std::copy(p, p + n, p + (width - n) / 2);
     728        fill_padding(p, spec.width(), n, fill);
     729        return;
     730      }
     731      if (spec.fill() != ' ' || sign) {
     732        while (*start == ' ')
     733          *start++ = fill;
     734        if (sign)
     735          *(start - 1) = sign;
     736      }
     737      grow_buffer(n);
     738      return;
     739    }
     740    // If n is negative we ask to increase the capacity by at least 1,
     741    // but as std::vector, the buffer grows exponentially.
     742    buffer_.reserve(n >= 0 ? offset + n + 1 : buffer_.capacity() + 1);
     743  }
     744}
     745
     746template <typename Char>
     747template <typename StrChar>
     748void fmt::BasicWriter<Char>::write_str(
     749    const Arg::StringValue<StrChar> &str, const FormatSpec &spec) {
     750  // Check if StrChar is convertible to Char.
     751  internal::CharTraits<Char>::convert(StrChar());
     752  if (spec.type_ && spec.type_ != 's')
     753    internal::report_unknown_type(spec.type_, "string");
     754  const StrChar *s = str.value;
     755  std::size_t size = str.size;
     756  if (size == 0) {
     757    if (!s) {
     758      Char err[] = { '(', 'n', 'u', 'l', 'l', ')', 0 };
     759      write_str(err, 6, spec);
     760      return;
     761    }
     762    if (*s)
     763      size = std::char_traits<StrChar>::length(s);
     764  }
     765  write_str(s, size, spec);
     766}
     767
     768template <typename Char>
     769inline const Arg
     770    &fmt::BasicFormatter<Char>::parse_arg_index(const Char *&s) {
     771  unsigned arg_index = 0;
     772  if (*s < '0' || *s > '9') {
     773    if (*s != '}' && *s != ':')
     774      report_error_(s, "invalid argument index in format string");
     775    const Arg &arg = next_arg();
     776    if (error_)
     777      report_error_(s, error_);
     778    return arg;
     779  }
     780  if (next_arg_index_ > 0) {
     781    report_error_(s,
     782        "cannot switch from automatic to manual argument indexing");
     783  }
     784  next_arg_index_ = -1;
     785  arg_index = parse_nonnegative_int(s, error_);
     786  if (error_)
     787    report_error_(s, error_); // TODO: don't use report_error_
     788  if (arg_index >= args_.size())
     789    report_error_(s, "argument index is out of range in format");
     790  return args_[arg_index];
     791}
     792
     793template <typename Char>
     794void fmt::BasicFormatter<Char>::check_sign(
     795    const Char *&s, const Arg &arg) {
     796  char sign = static_cast<char>(*s);
     797  if (arg.type > Arg::LAST_NUMERIC_TYPE) {
     798    report_error_(s, fmt::format(
     799      "format specifier '{}' requires numeric argument", sign).c_str());
     800  }
     801  if (arg.type == Arg::UINT || arg.type == Arg::ULONG_LONG) {
     802    report_error_(s, fmt::format(
     803      "format specifier '{}' requires signed argument", sign).c_str());
     804  }
     805  ++s;
     806}
     807
     808const Arg &fmt::internal::FormatterBase::next_arg() {
     809  if (next_arg_index_ < 0) {
     810    if (!error_)
     811      error_ = "cannot switch from manual to automatic argument indexing";
     812    return DUMMY_ARG;
     813  }
     814  unsigned arg_index = next_arg_index_++;
     815  if (arg_index < args_.size())
     816    return args_[arg_index];
     817  if (!error_)
     818    error_ = "argument index is out of range in format";
     819  return DUMMY_ARG;
     820}
     821
     822const Arg &fmt::internal::FormatterBase::handle_arg_index(unsigned arg_index) {
     823  if (arg_index != UINT_MAX) {
     824    if (next_arg_index_ <= 0) {
     825      next_arg_index_ = -1;
     826      --arg_index;
     827    } else if (!error_) {
     828      error_ = "cannot switch from automatic to manual argument indexing";
     829    }
     830    if (arg_index < args_.size())
     831      return args_[arg_index];
     832    if (!error_)
     833      error_ = "argument index is out of range in format";
     834    return DUMMY_ARG;
     835  }
     836  return next_arg();
     837}
     838
     839template <typename Char>
     840void fmt::internal::PrintfFormatter<Char>::parse_flags(
     841    FormatSpec &spec, const Char *&s) {
     842  for (;;) {
     843    switch (*s++) {
     844      case '-':
     845        spec.align_ = ALIGN_LEFT;
     846        break;
     847      case '+':
     848        spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
     849        break;
     850      case '0':
     851        spec.fill_ = '0';
     852        break;
     853      case ' ':
     854        spec.flags_ |= SIGN_FLAG;
     855        break;
     856      case '#':
     857        spec.flags_ |= HASH_FLAG;
     858        break;
     859      default:
     860        --s;
     861        return;
     862    }
     863  }
     864}
     865
     866template <typename Char>
     867unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
     868  const Char *&s, FormatSpec &spec) {
     869  unsigned arg_index = UINT_MAX;
     870  Char c = *s;
     871  if (c >= '0' && c <= '9') {
     872    // Parse an argument index (if followed by '$') or a width possibly
     873    // preceded with '0' flag(s).
     874    unsigned value = parse_nonnegative_int(s, error_);
     875    if (*s == '$') {  // value is an argument index
     876      ++s;
     877      arg_index = value;
     878    } else {
     879      if (c == '0')
     880        spec.fill_ = '0';
     881      if (value != 0) {
     882        // Nonzero value means that we parsed width and don't need to
     883        // parse it or flags again, so return now.
     884        spec.width_ = value;
     885        return arg_index;
     886      }
     887    }
     888  }
     889  parse_flags(spec, s);
     890  // Parse width.
     891  if (*s >= '0' && *s <= '9') {
     892    spec.width_ = parse_nonnegative_int(s, error_);
     893  } else if (*s == '*') {
     894    ++s;
     895    spec.width_ = WidthHandler(spec).visit(handle_arg_index(UINT_MAX));
     896  }
     897  return arg_index;
     898}
     899
     900template <typename Char>
     901void fmt::internal::PrintfFormatter<Char>::format(
     902    BasicWriter<Char> &writer, BasicStringRef<Char> format,
     903    const ArgList &args) {
     904  const Char *start = format.c_str();
     905  args_ = args;
     906  next_arg_index_ = 0;
     907  const Char *s = start;
     908  while (*s) {
     909    Char c = *s++;
     910    if (c != '%') continue;
     911    if (*s == c) {
     912      write(writer, start, s);
     913      start = ++s;
     914      continue;
     915    }
     916    write(writer, start, s - 1);
     917
     918    FormatSpec spec;
     919    spec.align_ = ALIGN_RIGHT;
     920
     921    // Reporting errors is delayed till the format specification is
     922    // completely parsed. This is done to avoid potentially confusing
     923    // error messages for incomplete format strings. For example, in
     924    //   sprintf("%2$", 42);
     925    // the format specification is incomplete. In a naive approach we
     926    // would parse 2 as an argument index and report an error that the
     927    // index is out of range which would be rather confusing if the
     928    // use meant "%2d$" rather than "%2$d". If we delay an error, the
     929    // user will get an error that the format string is invalid which
     930    // is OK for both cases.
     931
     932    // Parse argument index, flags and width.
     933    unsigned arg_index = parse_header(s, spec);
     934
     935    // Parse precision.
     936    if (*s == '.') {
     937      ++s;
     938      if ('0' <= *s && *s <= '9') {
     939        spec.precision_ = parse_nonnegative_int(s, error_);
     940      } else if (*s == '*') {
     941        ++s;
     942        spec.precision_ = PrecisionHandler().visit(handle_arg_index(UINT_MAX));
     943      }
     944    }
     945
     946    Arg arg = handle_arg_index(arg_index);
     947    if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg))
     948      spec.flags_ &= ~HASH_FLAG;
     949    if (spec.fill_ == '0') {
     950      if (arg.type <= Arg::LAST_NUMERIC_TYPE)
     951        spec.align_ = ALIGN_NUMERIC;
     952      else
     953        spec.fill_ = ' ';  // Ignore '0' flag for non-numeric types.
     954    }
     955
     956    // Parse length and convert the argument to the required type.
     957    switch (*s++) {
     958    case 'h':
     959      if (*s == 'h')
     960        ArgConverter<signed char>(arg, *++s).visit(arg);
     961      else
     962        ArgConverter<short>(arg, *s).visit(arg);
     963      break;
     964    case 'l':
     965      if (*s == 'l')
     966        ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
     967      else
     968        ArgConverter<long>(arg, *s).visit(arg);
     969      break;
     970    case 'j':
     971      ArgConverter<intmax_t>(arg, *s).visit(arg);
     972      break;
     973    case 'z':
     974      ArgConverter<size_t>(arg, *s).visit(arg);
     975      break;
     976    case 't':
     977      ArgConverter<ptrdiff_t>(arg, *s).visit(arg);
     978      break;
     979    case 'L':
     980      // printf produces garbage when 'L' is omitted for long double, no
     981      // need to do the same.
     982      break;
     983    default:
     984      --s;
     985      ArgConverter<int>(arg, *s).visit(arg);
     986    }
     987
     988    // Parse type.
     989    if (!*s)
     990      throw FormatError("invalid format string");
     991    if (error_)
     992      throw FormatError(error_);
     993    spec.type_ = static_cast<char>(*s++);
     994    if (arg.type <= Arg::LAST_INTEGER_TYPE) {
     995      // Normalize type.
     996      switch (spec.type_) {
     997      case 'i': case 'u':
     998        spec.type_ = 'd';
     999        break;
     1000      case 'c':
     1001        // TODO: handle wchar_t
     1002        CharConverter(arg).visit(arg);
     1003        break;
     1004      }
     1005    }
     1006
     1007    start = s;
     1008
     1009    // Format argument.
     1010    switch (arg.type) {
     1011    case Arg::INT:
     1012      writer.write_int(arg.int_value, spec);
     1013      break;
     1014    case Arg::UINT:
     1015      writer.write_int(arg.uint_value, spec);
     1016      break;
     1017    case Arg::LONG_LONG:
     1018      writer.write_int(arg.long_long_value, spec);
     1019      break;
     1020    case Arg::ULONG_LONG:
     1021      writer.write_int(arg.ulong_long_value, spec);
     1022      break;
     1023    case Arg::CHAR: {
     1024      if (spec.type_ && spec.type_ != 'c')
     1025        writer.write_int(arg.int_value, spec);
     1026      typedef typename BasicWriter<Char>::CharPtr CharPtr;
     1027      CharPtr out = CharPtr();
     1028      if (spec.width_ > 1) {
     1029        Char fill = ' ';
     1030        out = writer.grow_buffer(spec.width_);
     1031        if (spec.align_ != ALIGN_LEFT) {
     1032          std::fill_n(out, spec.width_ - 1, fill);
     1033          out += spec.width_ - 1;
     1034        } else {
     1035          std::fill_n(out + 1, spec.width_ - 1, fill);
     1036        }
     1037      } else {
     1038        out = writer.grow_buffer(1);
     1039      }
     1040      *out = static_cast<Char>(arg.int_value);
     1041      break;
     1042    }
     1043    case Arg::DOUBLE:
     1044      writer.write_double(arg.double_value, spec);
     1045      break;
     1046    case Arg::LONG_DOUBLE:
     1047      writer.write_double(arg.long_double_value, spec);
     1048      break;
     1049    case Arg::STRING:
     1050      writer.write_str(arg.string, spec);
     1051      break;
     1052    case Arg::WSTRING:
     1053      writer.write_str(ignore_incompatible_str<Char>(arg.wstring), spec);
     1054      break;
     1055    case Arg::POINTER:
     1056      if (spec.type_ && spec.type_ != 'p')
     1057        internal::report_unknown_type(spec.type_, "pointer");
     1058      spec.flags_= HASH_FLAG;
     1059      spec.type_ = 'x';
     1060      writer.write_int(reinterpret_cast<uintptr_t>(arg.pointer_value), spec);
     1061      break;
     1062    case Arg::CUSTOM:
     1063      if (spec.type_)
     1064        internal::report_unknown_type(spec.type_, "object");
     1065      arg.custom.format(&writer, arg.custom.value, "s");
     1066      break;
     1067    default:
     1068      assert(false);
     1069      break;
     1070    }
     1071  }
     1072  write(writer, start, s);
     1073}
     1074
     1075template <typename Char>
     1076const Char *fmt::BasicFormatter<Char>::format(
     1077    const Char *format_str, const Arg &arg) {
     1078  const Char *s = format_str;
     1079  const char *error = 0;
     1080  FormatSpec spec;
     1081  if (*s == ':') {
     1082    if (arg.type == Arg::CUSTOM) {
     1083      arg.custom.format(this, arg.custom.value, s);
     1084      return find_closing_brace(s) + 1;
     1085    }
     1086    ++s;
     1087    // Parse fill and alignment.
     1088    if (Char c = *s) {
     1089      const Char *p = s + 1;
     1090      spec.align_ = ALIGN_DEFAULT;
     1091      do {
     1092        switch (*p) {
     1093          case '<':
     1094            spec.align_ = ALIGN_LEFT;
     1095            break;
     1096          case '>':
     1097            spec.align_ = ALIGN_RIGHT;
     1098            break;
     1099          case '=':
     1100            spec.align_ = ALIGN_NUMERIC;
     1101            break;
     1102          case '^':
     1103            spec.align_ = ALIGN_CENTER;
     1104            break;
     1105        }
     1106        if (spec.align_ != ALIGN_DEFAULT) {
     1107          if (p != s) {
     1108            if (c == '}') break;
     1109            if (c == '{')
     1110              report_error_(s, "invalid fill character '{'");
     1111            s += 2;
     1112            spec.fill_ = c;
     1113          } else ++s;
     1114          if (spec.align_ == ALIGN_NUMERIC && arg.type > Arg::LAST_NUMERIC_TYPE)
     1115            report_error_(s, "format specifier '=' requires numeric argument");
     1116          break;
     1117        }
     1118      } while (--p >= s);
     1119    }
     1120
     1121    // Parse sign.
     1122    switch (*s) {
     1123      case '+':
     1124        check_sign(s, arg);
     1125        spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
     1126        break;
     1127      case '-':
     1128        check_sign(s, arg);
     1129        spec.flags_ |= MINUS_FLAG;
     1130        break;
     1131      case ' ':
     1132        check_sign(s, arg);
     1133        spec.flags_ |= SIGN_FLAG;
     1134        break;
     1135    }
     1136
     1137    if (*s == '#') {
     1138      if (arg.type > Arg::LAST_NUMERIC_TYPE)
     1139        report_error_(s, "format specifier '#' requires numeric argument");
     1140      spec.flags_ |= HASH_FLAG;
     1141      ++s;
     1142    }
     1143
     1144    // Parse width and zero flag.
     1145    if ('0' <= *s && *s <= '9') {
     1146      if (*s == '0') {
     1147        if (arg.type > Arg::LAST_NUMERIC_TYPE)
     1148          report_error_(s, "format specifier '0' requires numeric argument");
     1149        spec.align_ = ALIGN_NUMERIC;
     1150        spec.fill_ = '0';
     1151      }
     1152      // Zero may be parsed again as a part of the width, but it is simpler
     1153      // and more efficient than checking if the next char is a digit.
     1154      spec.width_ = parse_nonnegative_int(s, error);
     1155      if (error)
     1156        report_error_(s, error);
     1157    }
     1158
     1159    // Parse precision.
     1160    if (*s == '.') {
     1161      ++s;
     1162      spec.precision_ = 0;
     1163      if ('0' <= *s && *s <= '9') {
     1164        spec.precision_ = parse_nonnegative_int(s, error);
     1165        if (error)
     1166          report_error_(s, error);
     1167      } else if (*s == '{') {
     1168        ++s;
     1169        ++report_error_.num_open_braces;
     1170        const Arg &precision_arg = parse_arg_index(s);
     1171        ULongLong value = 0;
     1172        switch (precision_arg.type) {
     1173          case Arg::INT:
     1174            if (precision_arg.int_value < 0)
     1175              report_error_(s, "negative precision in format");
     1176            value = precision_arg.int_value;
     1177            break;
     1178          case Arg::UINT:
     1179            value = precision_arg.uint_value;
     1180            break;
     1181          case Arg::LONG_LONG:
     1182            if (precision_arg.long_long_value < 0)
     1183              report_error_(s, "negative precision in format");
     1184            value = precision_arg.long_long_value;
     1185            break;
     1186          case Arg::ULONG_LONG:
     1187            value = precision_arg.ulong_long_value;
     1188            break;
     1189          default:
     1190            report_error_(s, "precision is not integer");
     1191        }
     1192        if (value > INT_MAX)
     1193          report_error_(s, "number is too big in format");
     1194        spec.precision_ = static_cast<int>(value);
     1195        if (*s++ != '}')
     1196          throw FormatError("unmatched '{' in format");
     1197        --report_error_.num_open_braces;
     1198      } else {
     1199        report_error_(s, "missing precision in format");
     1200      }
     1201      if (arg.type != Arg::DOUBLE && arg.type != Arg::LONG_DOUBLE) {
     1202        report_error_(s,
     1203            "precision specifier requires floating-point argument");
     1204      }
     1205    }
     1206
     1207    // Parse type.
     1208    if (*s != '}' && *s)
     1209      spec.type_ = static_cast<char>(*s++);
     1210  }
     1211
     1212  if (*s++ != '}')
     1213    throw FormatError("unmatched '{' in format");
     1214  start_ = s;
     1215
     1216  // Format argument.
     1217  internal::ArgFormatter<Char>(*this, spec, s - 1).visit(arg);
     1218  return s;
     1219}
     1220
     1221template <typename Char>
     1222void fmt::BasicFormatter<Char>::format(
     1223    BasicStringRef<Char> format_str, const ArgList &args) {
     1224  const Char *s = start_ = format_str.c_str();
     1225  args_ = args;
     1226  next_arg_index_ = 0;
     1227  while (*s) {
     1228    Char c = *s++;
     1229    if (c != '{' && c != '}') continue;
     1230    if (*s == c) {
     1231      write(writer_, start_, s);
     1232      start_ = ++s;
     1233      continue;
     1234    }
     1235    if (c == '}')
     1236      throw FormatError("unmatched '}' in format");
     1237    report_error_.num_open_braces = 1;
     1238    write(writer_, start_, s - 1);
     1239    Arg arg = parse_arg_index(s);
     1240    s = format(s, arg);
     1241  }
     1242  write(writer_, start_, s);
     1243}
     1244
     1245void fmt::report_system_error(
     1246    int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
     1247  // FIXME: format_system_error may throw
     1248  report_error(internal::format_system_error, error_code, message);
     1249}
     1250
     1251#ifdef _WIN32
     1252void fmt::report_windows_error(
     1253    int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) {
     1254  // FIXME: format_windows_error may throw
     1255  report_error(internal::format_windows_error, error_code, message);
     1256}
     1257#endif
     1258
     1259void fmt::print(std::FILE *f, StringRef format_str, const ArgList &args) {
     1260  Writer w;
     1261  w.write(format_str, args);
     1262  std::fwrite(w.data(), 1, w.size(), f);
     1263}
     1264
     1265void fmt::print(std::ostream &os, StringRef format_str, const ArgList &args) {
     1266  Writer w;
     1267  w.write(format_str, args);
     1268  os.write(w.data(), w.size());
     1269}
     1270
     1271void fmt::print_colored(Color c, StringRef format, const ArgList &args) {
     1272  char escape[] = "\x1b[30m";
     1273  escape[3] = '0' + static_cast<char>(c);
     1274  std::fputs(escape, stdout);
     1275  print(format, args);
     1276  std::fputs(RESET_COLOR, stdout);
     1277}
     1278
     1279int fmt::fprintf(std::FILE *f, StringRef format, const ArgList &args) {
     1280  Writer w;
     1281  printf(w, format, args);
     1282  return std::fwrite(w.data(), 1, w.size(), f);
     1283}
     1284
     1285// Explicit instantiations for char.
     1286
     1287template fmt::BasicWriter<char>::CharPtr
     1288  fmt::BasicWriter<char>::fill_padding(CharPtr buffer,
     1289    unsigned total_size, std::size_t content_size, wchar_t fill);
     1290
     1291template void fmt::BasicFormatter<char>::format(
     1292  BasicStringRef<char> format, const ArgList &args);
     1293
     1294template void fmt::internal::PrintfFormatter<char>::format(
     1295  BasicWriter<char> &writer, BasicStringRef<char> format, const ArgList &args);
     1296
     1297// Explicit instantiations for wchar_t.
     1298
     1299template fmt::BasicWriter<wchar_t>::CharPtr
     1300  fmt::BasicWriter<wchar_t>::fill_padding(CharPtr buffer,
     1301    unsigned total_size, std::size_t content_size, wchar_t fill);
     1302
     1303template void fmt::BasicFormatter<wchar_t>::format(
     1304    BasicStringRef<wchar_t> format, const ArgList &args);
     1305
     1306template void fmt::internal::PrintfFormatter<wchar_t>::format(
     1307    BasicWriter<wchar_t> &writer, BasicStringRef<wchar_t> format,
     1308    const ArgList &args);
     1309
     1310#ifdef _MSC_VER
     1311# pragma warning(pop)
     1312#endif
  • new file source/third_party/cppformat/format.h

    diff --git a/source/third_party/cppformat/format.h b/source/third_party/cppformat/format.h
    new file mode 100644
    index 0000000..01452d0
    - +  
     1/*
     2 * Slightly modified version of cppformat, by Wildfire Games, for 0 A.D.
     3 * Based on cppformat v0.11.0 from https://github.com/cppformat/cppformat
     4 */
     5
     6/*
     7 Formatting library for C++
     8
     9 Copyright (c) 2012 - 2014, Victor Zverovich
     10 All rights reserved.
     11
     12 Redistribution and use in source and binary forms, with or without
     13 modification, are permitted provided that the following conditions are met:
     14
     15 1. Redistributions of source code must retain the above copyright notice, this
     16    list of conditions and the following disclaimer.
     17 2. Redistributions in binary form must reproduce the above copyright notice,
     18    this list of conditions and the following disclaimer in the documentation
     19    and/or other materials provided with the distribution.
     20
     21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
     22 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
     25 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     26 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     27 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     28 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     30 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31 */
     32
     33#ifndef FMT_FORMAT_H_
     34#define FMT_FORMAT_H_
     35
     36#include <stdint.h>
     37
     38#include <cassert>
     39#include <cstddef>  // for std::ptrdiff_t
     40#include <cstdio>
     41#include <algorithm>
     42#include <limits>
     43#include <stdexcept>
     44#include <string>
     45#include <sstream>
     46
     47#if defined(_SECURE_SCL) && _SECURE_SCL
     48# include <iterator>
     49#endif
     50
     51#ifdef __GNUC__
     52# define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
     53# define FMT_GCC_EXTENSION __extension__
     54// Disable warning about "long long" which is sometimes reported even
     55// when using __extension__.
     56# if FMT_GCC_VERSION >= 406
     57#  pragma GCC diagnostic push
     58#  pragma GCC diagnostic ignored "-Wlong-long"
     59# endif
     60#else
     61# define FMT_GCC_EXTENSION
     62#endif
     63
     64#ifdef __GNUC_LIBSTD__
     65# define FMT_GNUC_LIBSTD_VERSION (__GNUC_LIBSTD__ * 100 + __GNUC_LIBSTD_MINOR__)
     66#endif
     67
     68#ifdef __has_feature
     69# define FMT_HAS_FEATURE(x) __has_feature(x)
     70#else
     71# define FMT_HAS_FEATURE(x) 0
     72#endif
     73
     74#ifdef __has_builtin
     75# define FMT_HAS_BUILTIN(x) __has_builtin(x)
     76#else
     77# define FMT_HAS_BUILTIN(x) 0
     78#endif
     79
     80#ifndef FMT_USE_VARIADIC_TEMPLATES
     81// Variadic templates are available in GCC since version 4.4
     82// (http://gcc.gnu.org/projects/cxx0x.html) and in Visual C++
     83// since version 2013.
     84# define FMT_USE_VARIADIC_TEMPLATES \
     85   (FMT_HAS_FEATURE(cxx_variadic_templates) || \
     86       (FMT_GCC_VERSION >= 404 && __cplusplus >= 201103) || (defined(_MSC_VER) && _MSC_VER >= 1800))
     87#endif
     88
     89#ifndef FMT_USE_RVALUE_REFERENCES
     90// Don't use rvalue references when compiling with clang and an old libstdc++
     91// as the latter doesn't provide std::move.
     92# if defined(FMT_GNUC_LIBSTD_VERSION) && FMT_GNUC_LIBSTD_VERSION <= 402
     93#  define FMT_USE_RVALUE_REFERENCES 0
     94# else
     95#  define FMT_USE_RVALUE_REFERENCES \
     96    (FMT_HAS_FEATURE(cxx_rvalue_references) || \
     97        (FMT_GCC_VERSION >= 403 && __cplusplus >= 201103) || (defined(_MSC_VER) && _MSC_VER >= 1600))
     98# endif
     99#endif
     100
     101#if FMT_USE_RVALUE_REFERENCES
     102# include <utility>  // for std::move
     103#endif
     104
     105// Define FMT_USE_NOEXCEPT to make C++ Format use noexcept (C++11 feature).
     106#if (defined(FMT_USE_NOEXPECT) && FMT_USE_NOEXCEPT) || FMT_HAS_FEATURE(cxx_noexcept) || \
     107  (FMT_GCC_VERSION >= 408 && __cplusplus >= 201103)
     108# define FMT_NOEXCEPT(expr) noexcept(expr)
     109#else
     110# define FMT_NOEXCEPT(expr)
     111#endif
     112
     113// A macro to disallow the copy constructor and operator= functions
     114// This should be used in the private: declarations for a class
     115#define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \
     116  TypeName(const TypeName&); \
     117  void operator=(const TypeName&)
     118
     119namespace fmt {
     120
     121// Fix the warning about long long on older versions of GCC
     122// that don't support the diagnostic pragma.
     123FMT_GCC_EXTENSION typedef long long LongLong;
     124FMT_GCC_EXTENSION typedef unsigned long long ULongLong;
     125
     126#if FMT_USE_RVALUE_REFERENCES
     127using std::move;
     128#endif
     129
     130template <typename Char>
     131class BasicWriter;
     132
     133typedef BasicWriter<char> Writer;
     134typedef BasicWriter<wchar_t> WWriter;
     135
     136template <typename Char>
     137class BasicFormatter;
     138
     139template <typename Char, typename T>
     140void format(BasicFormatter<Char> &f, const Char *format_str, const T &value);
     141
     142/**
     143  \rst
     144  A string reference. It can be constructed from a C string or
     145  ``std::string``.
     146 
     147  You can use one of the following typedefs for common character types:
     148
     149  +------------+-------------------------+
     150  | Type       | Definition              |
     151  +============+=========================+
     152  | StringRef  | BasicStringRef<char>    |
     153  +------------+-------------------------+
     154  | WStringRef | BasicStringRef<wchar_t> |
     155  +------------+-------------------------+
     156
     157  This class is most useful as a parameter type to allow passing
     158  different types of strings to a function, for example::
     159
     160    template<typename... Args>
     161    std::string format(StringRef format, const Args & ... args);
     162
     163    format("{}", 42);
     164    format(std::string("{}"), 42);
     165  \endrst
     166 */
     167template <typename Char>
     168class BasicStringRef {
     169 private:
     170  const Char *data_;
     171  mutable std::size_t size_;
     172
     173 public:
     174  /**
     175    Constructs a string reference object from a C string and a size.
     176    If *size* is zero, which is the default, the size is computed
     177    automatically.
     178   */
     179  BasicStringRef(const Char *s, std::size_t size = 0) : data_(s), size_(size) {}
     180
     181  /**
     182    Constructs a string reference from an `std::string` object.
     183   */
     184  BasicStringRef(const std::basic_string<Char> &s)
     185  : data_(s.c_str()), size_(s.size()) {}
     186
     187  /**
     188    Converts a string reference to an `std::string` object.
     189   */
     190  operator std::basic_string<Char>() const {
     191    return std::basic_string<Char>(data_, size());
     192  }
     193
     194  /**
     195    Returns the pointer to a C string.
     196   */
     197  const Char *c_str() const { return data_; }
     198
     199  /**
     200    Returns the string size.
     201   */
     202  std::size_t size() const {
     203    if (size_ == 0 && data_) size_ = std::char_traits<Char>::length(data_);
     204    return size_;
     205  }
     206
     207  friend bool operator==(BasicStringRef lhs, BasicStringRef rhs) {
     208    return lhs.data_ == rhs.data_;
     209  }
     210  friend bool operator!=(BasicStringRef lhs, BasicStringRef rhs) {
     211    return lhs.data_ != rhs.data_;
     212  }
     213};
     214
     215typedef BasicStringRef<char> StringRef;
     216typedef BasicStringRef<wchar_t> WStringRef;
     217
     218/**
     219  A formatting error such as invalid format string.
     220*/
     221class FormatError : public std::runtime_error {
     222public:
     223  explicit FormatError(const std::string &message)
     224  : std::runtime_error(message) {}
     225};
     226
     227namespace internal {
     228
     229// The number of characters to store in the Array object, representing the
     230// output buffer, itself to avoid dynamic memory allocation.
     231enum { INLINE_BUFFER_SIZE = 500 };
     232
     233#if defined(_SECURE_SCL) && _SECURE_SCL
     234// Use checked iterator to avoid warnings on MSVC.
     235template <typename T>
     236inline stdext::checked_array_iterator<T*> make_ptr(T *ptr, std::size_t size) {
     237  return stdext::checked_array_iterator<T*>(ptr, size);
     238}
     239#else
     240template <typename T>
     241inline T *make_ptr(T *ptr, std::size_t) { return ptr; }
     242#endif
     243
     244// A simple array for POD types with the first SIZE elements stored in
     245// the object itself. It supports a subset of std::vector's operations.
     246template <typename T, std::size_t SIZE>
     247class Array {
     248 private:
     249  std::size_t size_;
     250  std::size_t capacity_;
     251  T *ptr_;
     252  T data_[SIZE];
     253
     254  void grow(std::size_t size);
     255
     256  // Free memory allocated by the array.
     257  void free() {
     258    if (ptr_ != data_) delete [] ptr_;
     259  }
     260
     261  // Move data from other to this array.
     262  void move(Array &other) {
     263    size_ = other.size_;
     264    capacity_ = other.capacity_;
     265    if (other.ptr_ == other.data_) {
     266      ptr_ = data_;
     267      std::copy(other.data_, other.data_ + size_, make_ptr(data_, capacity_));
     268    } else {
     269      ptr_ = other.ptr_;
     270      // Set pointer to the inline array so that delete is not called
     271      // when freeing.
     272      other.ptr_ = other.data_;
     273    }
     274  }
     275
     276  FMT_DISALLOW_COPY_AND_ASSIGN(Array);
     277
     278 public:
     279  explicit Array(std::size_t size = 0)
     280    : size_(size), capacity_(SIZE), ptr_(data_) {}
     281  ~Array() { free(); }
     282
     283#if FMT_USE_RVALUE_REFERENCES
     284  Array(Array &&other) {
     285    move(other);
     286  }
     287
     288  Array& operator=(Array &&other) {
     289    assert(this != &other);
     290    free();
     291    move(other);
     292    return *this;
     293  }
     294#endif
     295
     296  // Returns the size of this array.
     297  std::size_t size() const { return size_; }
     298
     299  // Returns the capacity of this array.
     300  std::size_t capacity() const { return capacity_; }
     301
     302  // Resizes the array. If T is a POD type new elements are not initialized.
     303  void resize(std::size_t new_size) {
     304    if (new_size > capacity_)
     305      grow(new_size);
     306    size_ = new_size;
     307  }
     308
     309  // Reserves space to store at least capacity elements.
     310  void reserve(std::size_t capacity) {
     311    if (capacity > capacity_)
     312      grow(capacity);
     313  }
     314
     315  void clear() { size_ = 0; }
     316
     317  void push_back(const T &value) {
     318    if (size_ == capacity_)
     319      grow(size_ + 1);
     320    ptr_[size_++] = value;
     321  }
     322
     323  // Appends data to the end of the array.
     324  void append(const T *begin, const T *end);
     325
     326  T &operator[](std::size_t index) { return ptr_[index]; }
     327  const T &operator[](std::size_t index) const { return ptr_[index]; }
     328};
     329
     330template <typename T, std::size_t SIZE>
     331void Array<T, SIZE>::grow(std::size_t size) {
     332  capacity_ = (std::max)(size, capacity_ + capacity_ / 2);
     333  T *p = new T[capacity_];
     334  std::copy(ptr_, ptr_ + size_, make_ptr(p, capacity_));
     335  if (ptr_ != data_)
     336    delete [] ptr_;
     337  ptr_ = p;
     338}
     339
     340template <typename T, std::size_t SIZE>
     341void Array<T, SIZE>::append(const T *begin, const T *end) {
     342  std::ptrdiff_t num_elements = end - begin;
     343  if (size_ + num_elements > capacity_)
     344    grow(size_ + num_elements);
     345  std::copy(begin, end, make_ptr(ptr_, capacity_) + size_);
     346  size_ += num_elements;
     347}
     348
     349template <typename Char>
     350class BasicCharTraits {
     351 public:
     352#if defined(_SECURE_SCL) && _SECURE_SCL
     353  typedef stdext::checked_array_iterator<Char*> CharPtr;
     354#else
     355  typedef Char *CharPtr;
     356#endif
     357};
     358
     359template <typename Char>
     360class CharTraits;
     361
     362template <>
     363class CharTraits<char> : public BasicCharTraits<char> {
     364 private:
     365  // Conversion from wchar_t to char is not allowed.
     366  static char convert(wchar_t);
     367
     368public:
     369  typedef const wchar_t *UnsupportedStrType;
     370
     371  static char convert(char value) { return value; }
     372
     373  // Formats a floating-point number.
     374  template <typename T>
     375  static int format_float(char *buffer, std::size_t size,
     376      const char *format, unsigned width, int precision, T value);
     377};
     378
     379template <>
     380class CharTraits<wchar_t> : public BasicCharTraits<wchar_t> {
     381 public:
     382  typedef const char *UnsupportedStrType;
     383
     384  static wchar_t convert(char value) { return value; }
     385  static wchar_t convert(wchar_t value) { return value; }
     386
     387  template <typename T>
     388  static int format_float(wchar_t *buffer, std::size_t size,
     389      const wchar_t *format, unsigned width, int precision, T value);
     390};
     391
     392// Selects uint32_t if FitsIn32Bits is true, uint64_t otherwise.
     393template <bool FitsIn32Bits>
     394struct TypeSelector { typedef uint32_t Type; };
     395
     396template <>
     397struct TypeSelector<false> { typedef uint64_t Type; };
     398
     399// Checks if a number is negative - used to avoid warnings.
     400template <bool IsSigned>
     401struct SignChecker {
     402  template <typename T>
     403  static bool is_negative(T) { return false; }
     404};
     405
     406template <>
     407struct SignChecker<true> {
     408  template <typename T>
     409  static bool is_negative(T value) { return value < 0; }
     410};
     411
     412// Returns true if value is negative, false otherwise.
     413// Same as (value < 0) but doesn't produce warnings if T is an unsigned type.
     414template <typename T>
     415inline bool is_negative(T value) {
     416  return SignChecker<std::numeric_limits<T>::is_signed>::is_negative(value);
     417}
     418
     419template <typename T>
     420struct IntTraits {
     421  // Smallest of uint32_t and uint64_t that is large enough to represent
     422  // all values of T.
     423  typedef typename
     424    TypeSelector<std::numeric_limits<T>::digits <= 32>::Type MainType;
     425};
     426
     427// MakeUnsigned<T>::Type gives an unsigned type corresponding to integer type T.
     428template <typename T>
     429struct MakeUnsigned { typedef T Type; };
     430
     431#define FMT_SPECIALIZE_MAKE_UNSIGNED(T, U) \
     432  template <> \
     433  struct MakeUnsigned<T> { typedef U Type; }
     434
     435FMT_SPECIALIZE_MAKE_UNSIGNED(char, unsigned char);
     436FMT_SPECIALIZE_MAKE_UNSIGNED(signed char, unsigned char);
     437FMT_SPECIALIZE_MAKE_UNSIGNED(short, unsigned short);
     438FMT_SPECIALIZE_MAKE_UNSIGNED(int, unsigned);
     439FMT_SPECIALIZE_MAKE_UNSIGNED(long, unsigned long);
     440FMT_SPECIALIZE_MAKE_UNSIGNED(LongLong, ULongLong);
     441
     442void report_unknown_type(char code, const char *type);
     443
     444extern const uint32_t POWERS_OF_10_32[];
     445extern const uint64_t POWERS_OF_10_64[];
     446
     447#if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clzll)
     448// Returns the number of decimal digits in n. Leading zeros are not counted
     449// except for n == 0 in which case count_digits returns 1.
     450inline unsigned count_digits(uint64_t n) {
     451  // Based on http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
     452  // and the benchmark https://github.com/localvoid/cxx-benchmark-count-digits.
     453  unsigned t = (64 - __builtin_clzll(n | 1)) * 1233 >> 12;
     454  return t - (n < POWERS_OF_10_64[t]) + 1;
     455}
     456# if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clz)
     457// Optional version of count_digits for better performance on 32-bit platforms.
     458inline unsigned count_digits(uint32_t n) {
     459  uint32_t t = (32 - __builtin_clz(n | 1)) * 1233 >> 12;
     460  return t - (n < POWERS_OF_10_32[t]) + 1;
     461}
     462# endif
     463#else
     464// Slower version of count_digits used when __builtin_clz is not available.
     465inline unsigned count_digits(uint64_t n) {
     466  unsigned count = 1;
     467  for (;;) {
     468    // Integer division is slow so do it for a group of four digits instead
     469    // of for every digit. The idea comes from the talk by Alexandrescu
     470    // "Three Optimization Tips for C++". See speed-test for a comparison.
     471    if (n < 10) return count;
     472    if (n < 100) return count + 1;
     473    if (n < 1000) return count + 2;
     474    if (n < 10000) return count + 3;
     475    n /= 10000u;
     476    count += 4;
     477  }
     478}
     479#endif
     480
     481extern const char DIGITS[];
     482
     483// Formats a decimal unsigned integer value writing into buffer.
     484template <typename UInt, typename Char>
     485inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) {
     486  --num_digits;
     487  while (value >= 100) {
     488    // Integer division is slow so do it for a group of two digits instead
     489    // of for every digit. The idea comes from the talk by Alexandrescu
     490    // "Three Optimization Tips for C++". See speed-test for a comparison.
     491    unsigned index = (value % 100) * 2;
     492    value /= 100;
     493    buffer[num_digits] = DIGITS[index + 1];
     494    buffer[num_digits - 1] = DIGITS[index];
     495    num_digits -= 2;
     496  }
     497  if (value < 10) {
     498    *buffer = static_cast<char>('0' + value);
     499    return;
     500  }
     501  unsigned index = static_cast<unsigned>(value * 2);
     502  buffer[1] = DIGITS[index + 1];
     503  buffer[0] = DIGITS[index];
     504}
     505
     506#ifdef _WIN32
     507// A converter from UTF-8 to UTF-16.
     508// It is only provided for Windows since other systems use UTF-8.
     509class UTF8ToUTF16 {
     510 private:
     511  Array<wchar_t, INLINE_BUFFER_SIZE> buffer_;
     512
     513 public:
     514  explicit UTF8ToUTF16(StringRef s);
     515  operator WStringRef() const { return WStringRef(&buffer_[0], size()); }
     516  size_t size() const { return buffer_.size() - 1; }
     517  const wchar_t *c_str() const { return &buffer_[0]; }
     518  std::wstring str() const { return std::wstring(&buffer_[0], size()); }
     519};
     520
     521// A converter from UTF-16 to UTF-8.
     522// It is only provided for Windows since other systems use UTF-8.
     523class UTF16ToUTF8 {
     524 private:
     525  Array<char, INLINE_BUFFER_SIZE> buffer_;
     526
     527 public:
     528  UTF16ToUTF8() {}
     529  explicit UTF16ToUTF8(WStringRef s);
     530  operator StringRef() const { return StringRef(&buffer_[0], size()); }
     531  size_t size() const { return buffer_.size() - 1; }
     532  const char *c_str() const { return &buffer_[0]; }
     533  std::string str() const { return std::string(&buffer_[0], size()); }
     534
     535  // Performs conversion returning a system error code instead of
     536  // throwing exception on error.
     537  int convert(WStringRef s);
     538};
     539#endif
     540
     541// Portable thread-safe version of strerror.
     542// Sets buffer to point to a string describing the error code.
     543// This can be either a pointer to a string stored in buffer,
     544// or a pointer to some static immutable string.
     545// Returns one of the following values:
     546//   0      - success
     547//   ERANGE - buffer is not large enough to store the error message
     548//   other  - failure
     549// Buffer should be at least of size 1.
     550int safe_strerror(int error_code,
     551    char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT(true);
     552
     553void format_system_error(
     554    fmt::Writer &out, int error_code, fmt::StringRef message);
     555
     556#ifdef _WIN32
     557void format_windows_error(
     558    fmt::Writer &out, int error_code, fmt::StringRef message);
     559#endif
     560
     561// Throws Exception(message) if format contains '}', otherwise throws
     562// FormatError reporting unmatched '{'. The idea is that unmatched '{'
     563// should override other errors.
     564template <typename Char>
     565struct FormatErrorReporter {
     566  int num_open_braces;
     567  void operator()(const Char *s, fmt::StringRef message) const;
     568};
     569
     570// Computes max(Arg, 1) at compile time. It is used to avoid errors about
     571// allocating an array of 0 size.
     572template <unsigned Arg>
     573struct NonZero {
     574  enum { VALUE = Arg };
     575};
     576
     577template <>
     578struct NonZero<0> {
     579  enum { VALUE = 1 };
     580};
     581
     582// A formatting argument. It is a POD type to allow storage in internal::Array.
     583struct Arg {
     584  enum Type {
     585    // Integer types should go first,
     586    INT, UINT, LONG_LONG, ULONG_LONG, CHAR, LAST_INTEGER_TYPE = CHAR,
     587    // followed by floating-point types.
     588    DOUBLE, LONG_DOUBLE, LAST_NUMERIC_TYPE = LONG_DOUBLE,
     589    STRING, WSTRING, POINTER, CUSTOM
     590  };
     591  Type type;
     592
     593  template <typename Char>
     594  struct StringValue {
     595    const Char *value;
     596    std::size_t size;
     597  };
     598
     599  typedef void (*FormatFunc)(
     600      void *formatter, const void *arg, const void *format_str);
     601
     602  struct CustomValue {
     603    const void *value;
     604    FormatFunc format;
     605  };
     606
     607  union {
     608    int int_value;
     609    unsigned uint_value;
     610    LongLong long_long_value;
     611    ULongLong ulong_long_value;
     612    double double_value;
     613    long double long_double_value;
     614    const void *pointer_value;
     615    StringValue<char> string;
     616    StringValue<wchar_t> wstring;
     617    CustomValue custom;
     618  };
     619};
     620
     621// Makes an Arg object from any type.
     622template <typename Char>
     623class MakeArg : public Arg {
     624 private:
     625  // The following two methods are private to disallow formatting of
     626  // arbitrary pointers. If you want to output a pointer cast it to
     627  // "void *" or "const void *". In particular, this forbids formatting
     628  // of "[const] volatile char *" which is printed as bool by iostreams.
     629  // Do not implement!
     630  template <typename T>
     631  MakeArg(const T *value);
     632  template <typename T>
     633  MakeArg(T *value);
     634
     635  void set_string(StringRef str) {
     636    type = STRING;
     637    string.value = str.c_str();
     638    string.size = str.size();
     639  }
     640
     641  void set_string(WStringRef str) {
     642    type = WSTRING;
     643    CharTraits<Char>::convert(wchar_t());
     644    wstring.value = str.c_str();
     645    wstring.size = str.size();
     646  }
     647
     648  // Formats an argument of a custom type, such as a user-defined class.
     649  template <typename T>
     650  static void format_custom_arg(
     651      void *formatter, const void *arg, const void *format_str) {
     652    format(*static_cast<BasicFormatter<Char>*>(formatter),
     653        static_cast<const Char*>(format_str), *static_cast<const T*>(arg));
     654  }
     655
     656public:
     657  MakeArg() {}
     658  MakeArg(bool value) { type = INT; int_value = value; }
     659  MakeArg(short value) { type = INT; int_value = value; }
     660  MakeArg(unsigned short value) { type = UINT; uint_value = value; }
     661  MakeArg(int value) { type = INT; int_value = value; }
     662  MakeArg(unsigned value) { type = UINT; uint_value = value; }
     663  MakeArg(long value) {
     664    // To minimize the number of types we need to deal with, long is
     665    // translated either to int or to long long depending on its size.
     666    if (sizeof(long) == sizeof(int)) {
     667      type = INT;
     668      int_value = static_cast<int>(value);
     669    } else {
     670      type = LONG_LONG;
     671      long_long_value = value;
     672    }
     673  }
     674  MakeArg(unsigned long value) {
     675    if (sizeof(unsigned long) == sizeof(unsigned)) {
     676      type = UINT;
     677      uint_value = static_cast<unsigned>(value);
     678    } else {
     679      type = ULONG_LONG;
     680      ulong_long_value = value;
     681    }
     682  }
     683  MakeArg(LongLong value) { type = LONG_LONG; long_long_value = value; }
     684  MakeArg(ULongLong value) { type = ULONG_LONG; ulong_long_value = value; }
     685  MakeArg(float value) { type = DOUBLE; double_value = value; }
     686  MakeArg(double value) { type = DOUBLE; double_value = value; }
     687  MakeArg(long double value) { type = LONG_DOUBLE; long_double_value = value; }
     688  MakeArg(signed char value) { type = CHAR; int_value = value; }
     689  MakeArg(unsigned char value) { type = CHAR; int_value = value; }
     690  MakeArg(char value) { type = CHAR; int_value = value; }
     691  MakeArg(wchar_t value) {
     692    type = CHAR;
     693    int_value = internal::CharTraits<Char>::convert(value);
     694  }
     695
     696  MakeArg(char *value) { set_string(value); }
     697  MakeArg(const char *value) { set_string(value); }
     698  MakeArg(const std::string &value) { set_string(value); }
     699  MakeArg(StringRef value) { set_string(value); }
     700
     701  MakeArg(wchar_t *value) { set_string(value); }
     702  MakeArg(const wchar_t *value) { set_string(value); }
     703  MakeArg(const std::wstring &value) { set_string(value); }
     704  MakeArg(WStringRef value) { set_string(value); }
     705
     706  MakeArg(void *value) { type = POINTER; pointer_value = value; }
     707  MakeArg(const void *value) { type = POINTER; pointer_value = value; }
     708
     709#if 0
     710  // WFG: Removed this because otherwise you can pass a CStr8 or an enum etc
     711  // into fmt::sprintf, and it will be interpreted as a CUSTOM type and then
     712  // will throw an exception at runtime, which is terrible behaviour.
     713  template <typename T>
     714  MakeArg(const T &value) {
     715    type = CUSTOM;
     716    custom.value = &value;
     717    custom.format = &format_custom_arg<T>;
     718  }
     719#endif
     720};
     721
     722#define FMT_DISPATCH(call) static_cast<Impl*>(this)->call
     723
     724// An argument visitor.
     725// To use ArgVisitor define a subclass that implements some or all of the
     726// visit methods with the same signatures as the methods in ArgVisitor,
     727// for example, visit_int(int).
     728// Specify the subclass name as the Impl template parameter. Then calling
     729// ArgVisitor::visit for some argument will dispatch to a visit method
     730// specific to the argument type. For example, if the argument type is
     731// double then visit_double(double) method of a subclass will be called.
     732// If the subclass doesn't contain a method with this signature, then
     733// a corresponding method of ArgVisitor will be called.
     734//
     735// Example:
     736//  class MyArgVisitor : public ArgVisitor<MyArgVisitor, void> {
     737//   public:
     738//    void visit_int(int value) { print("{}", value); }
     739//    void visit_double(double value) { print("{}", value ); }
     740//  };
     741//
     742// ArgVisitor uses the curiously recurring template pattern:
     743// http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
     744template <typename Impl, typename Result>
     745class ArgVisitor {
     746 public:
     747  Result visit_unhandled_arg() { return Result(); }
     748
     749  Result visit_int(int value) {
     750    return FMT_DISPATCH(visit_any_int(value));
     751  }
     752  Result visit_long_long(LongLong value) {
     753    return FMT_DISPATCH(visit_any_int(value));
     754  }
     755  Result visit_uint(unsigned value) {
     756    return FMT_DISPATCH(visit_any_int(value));
     757  }
     758  Result visit_ulong_long(ULongLong value) {
     759    return FMT_DISPATCH(visit_any_int(value));
     760  }
     761  Result visit_char(int value) {
     762    return FMT_DISPATCH(visit_any_int(value));
     763  }
     764  template <typename T>
     765  Result visit_any_int(T) {
     766    return FMT_DISPATCH(visit_unhandled_arg());
     767  }
     768
     769  Result visit_double(double value) {
     770    return FMT_DISPATCH(visit_any_double(value));
     771  }
     772  Result visit_long_double(long double value) {
     773    return FMT_DISPATCH(visit_any_double(value));
     774  }
     775  template <typename T>
     776  Result visit_any_double(T) {
     777    return FMT_DISPATCH(visit_unhandled_arg());
     778  }
     779
     780  Result visit_string(Arg::StringValue<char>) {
     781    return FMT_DISPATCH(visit_unhandled_arg());
     782  }
     783  Result visit_wstring(Arg::StringValue<wchar_t>) {
     784    return FMT_DISPATCH(visit_unhandled_arg());
     785  }
     786  Result visit_pointer(const void *) {
     787    return FMT_DISPATCH(visit_unhandled_arg());
     788  }
     789  Result visit_custom(Arg::CustomValue) {
     790    return FMT_DISPATCH(visit_unhandled_arg());
     791  }
     792
     793  Result visit(const Arg &arg) {
     794    switch (arg.type) {
     795    default:
     796      assert(false);
     797      // Fall through.
     798    case Arg::INT:
     799      return FMT_DISPATCH(visit_int(arg.int_value));
     800    case Arg::UINT:
     801      return FMT_DISPATCH(visit_uint(arg.uint_value));
     802    case Arg::LONG_LONG:
     803      return FMT_DISPATCH(visit_long_long(arg.long_long_value));
     804    case Arg::ULONG_LONG:
     805      return FMT_DISPATCH(visit_ulong_long(arg.ulong_long_value));
     806    case Arg::DOUBLE:
     807      return FMT_DISPATCH(visit_double(arg.double_value));
     808    case Arg::LONG_DOUBLE:
     809      return FMT_DISPATCH(visit_long_double(arg.long_double_value));
     810    case Arg::CHAR:
     811      return FMT_DISPATCH(visit_char(arg.int_value));
     812    case Arg::STRING:
     813      return FMT_DISPATCH(visit_string(arg.string));
     814    case Arg::WSTRING:
     815      return FMT_DISPATCH(visit_wstring(arg.wstring));
     816    case Arg::POINTER:
     817      return FMT_DISPATCH(visit_pointer(arg.pointer_value));
     818    case Arg::CUSTOM:
     819      return FMT_DISPATCH(visit_custom(arg.custom));
     820    }
     821  }
     822};
     823
     824class RuntimeError : public std::runtime_error {
     825 protected:
     826  RuntimeError() : std::runtime_error("") {}
     827};
     828
     829template <typename Char>
     830class ArgFormatter;
     831}  // namespace internal
     832
     833/**
     834  An argument list.
     835 */
     836class ArgList {
     837 private:
     838  const internal::Arg *args_;
     839  std::size_t size_;
     840
     841 public:
     842  ArgList() : size_(0) {}
     843  ArgList(const internal::Arg *args, std::size_t size)
     844  : args_(args), size_(size) {}
     845
     846  /**
     847    Returns the list size (the number of arguments).
     848   */
     849  std::size_t size() const { return size_; }
     850
     851  /**
     852    Returns the argument at specified index.
     853   */
     854  const internal::Arg &operator[](std::size_t index) const {
     855    return args_[index];
     856  }
     857};
     858
     859struct FormatSpec;
     860
     861namespace internal {
     862
     863class FormatterBase {
     864protected:
     865  ArgList args_;
     866  int next_arg_index_;
     867  const char *error_;
     868
     869  FormatterBase() : error_(0) {}
     870
     871  const Arg &next_arg();
     872
     873  const Arg &handle_arg_index(unsigned arg_index);
     874
     875  template <typename Char>
     876  void write(BasicWriter<Char> &w, const Char *start, const Char *end) {
     877    if (start != end)
     878      w << BasicStringRef<Char>(start, end - start);
     879  }
     880
     881  // TODO
     882};
     883
     884// A printf formatter.
     885template <typename Char>
     886class PrintfFormatter : private FormatterBase {
     887 private:
     888  void parse_flags(FormatSpec &spec, const Char *&s);
     889
     890  // Parses argument index, flags and width and returns the parsed
     891  // argument index.
     892  unsigned parse_header(const Char *&s, FormatSpec &spec);
     893
     894 public:
     895  void format(BasicWriter<Char> &writer,
     896    BasicStringRef<Char> format, const ArgList &args);
     897};
     898}  // namespace internal
     899
     900// A formatter.
     901template <typename Char>
     902class BasicFormatter : private internal::FormatterBase {
     903private:
     904  BasicWriter<Char> &writer_;
     905  const Char *start_;
     906  internal::FormatErrorReporter<Char> report_error_;
     907
     908  // Parses argument index and returns an argument with this index.
     909  const internal::Arg &parse_arg_index(const Char *&s);
     910
     911  void check_sign(const Char *&s, const internal::Arg &arg);
     912
     913public:
     914  explicit BasicFormatter(BasicWriter<Char> &w) : writer_(w) {}
     915
     916  BasicWriter<Char> &writer() { return writer_; }
     917
     918  void format(BasicStringRef<Char> format_str, const ArgList &args);
     919
     920  const Char *format(const Char *format_str, const internal::Arg &arg);
     921};
     922
     923enum Alignment {
     924  ALIGN_DEFAULT, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, ALIGN_NUMERIC
     925};
     926
     927// Flags.
     928enum {
     929  SIGN_FLAG = 1, PLUS_FLAG = 2, MINUS_FLAG = 4, HASH_FLAG = 8,
     930  CHAR_FLAG = 0x10  // Argument has char type - used in error reporting.
     931};
     932
     933// An empty format specifier.
     934struct EmptySpec {};
     935
     936// A type specifier.
     937template <char TYPE>
     938struct TypeSpec : EmptySpec {
     939  Alignment align() const { return ALIGN_DEFAULT; }
     940  unsigned width() const { return 0; }
     941  int precision() const { return -1; }
     942  bool flag(unsigned) const { return false; }
     943  char type() const { return TYPE; }
     944  char fill() const { return ' '; }
     945};
     946
     947// A width specifier.
     948struct WidthSpec {
     949  unsigned width_;
     950  // Fill is always wchar_t and cast to char if necessary to avoid having
     951  // two specialization of WidthSpec and its subclasses.
     952  wchar_t fill_;
     953
     954  WidthSpec(unsigned width, wchar_t fill) : width_(width), fill_(fill) {}
     955
     956  unsigned width() const { return width_; }
     957  wchar_t fill() const { return fill_; }
     958};
     959
     960// An alignment specifier.
     961struct AlignSpec : WidthSpec {
     962  Alignment align_;
     963
     964  AlignSpec(unsigned width, wchar_t fill, Alignment align = ALIGN_DEFAULT)
     965  : WidthSpec(width, fill), align_(align) {}
     966
     967  Alignment align() const { return align_; }
     968
     969  int precision() const { return -1; }
     970};
     971
     972// An alignment and type specifier.
     973template <char TYPE>
     974struct AlignTypeSpec : AlignSpec {
     975  AlignTypeSpec(unsigned width, wchar_t fill) : AlignSpec(width, fill) {}
     976
     977  bool flag(unsigned) const { return false; }
     978  char type() const { return TYPE; }
     979};
     980
     981// A full format specifier.
     982struct FormatSpec : AlignSpec {
     983  unsigned flags_;
     984  int precision_;
     985  char type_;
     986
     987  FormatSpec(
     988    unsigned width = 0, char type = 0, wchar_t fill = ' ')
     989  : AlignSpec(width, fill), flags_(0), precision_(-1), type_(type) {}
     990
     991  bool flag(unsigned f) const { return (flags_ & f) != 0; }
     992  int precision() const { return precision_; }
     993  char type() const { return type_; }
     994};
     995
     996// An integer format specifier.
     997template <typename T, typename SpecT = TypeSpec<0>, typename Char = char>
     998class IntFormatSpec : public SpecT {
     999 private:
     1000  T value_;
     1001
     1002 public:
     1003  IntFormatSpec(T value, const SpecT &spec = SpecT())
     1004  : SpecT(spec), value_(value) {}
     1005
     1006  T value() const { return value_; }
     1007};
     1008
     1009// A string format specifier.
     1010template <typename T>
     1011class StrFormatSpec : public AlignSpec {
     1012 private:
     1013  const T *str_;
     1014
     1015 public:
     1016  StrFormatSpec(const T *str, unsigned width, wchar_t fill)
     1017  : AlignSpec(width, fill), str_(str) {}
     1018
     1019  const T *str() const { return str_; }
     1020};
     1021
     1022/**
     1023  Returns an integer format specifier to format the value in base 2.
     1024 */
     1025IntFormatSpec<int, TypeSpec<'b'> > bin(int value);
     1026
     1027/**
     1028  Returns an integer format specifier to format the value in base 8.
     1029 */
     1030IntFormatSpec<int, TypeSpec<'o'> > oct(int value);
     1031
     1032/**
     1033  Returns an integer format specifier to format the value in base 16 using
     1034  lower-case letters for the digits above 9.
     1035 */
     1036IntFormatSpec<int, TypeSpec<'x'> > hex(int value);
     1037
     1038/**
     1039  Returns an integer formatter format specifier to format in base 16 using
     1040  upper-case letters for the digits above 9.
     1041 */
     1042IntFormatSpec<int, TypeSpec<'X'> > hexu(int value);
     1043
     1044/**
     1045  \rst
     1046  Returns an integer format specifier to pad the formatted argument with the
     1047  fill character to the specified width using the default (right) numeric
     1048  alignment.
     1049
     1050  **Example**::
     1051
     1052    Writer out;
     1053    out << pad(hex(0xcafe), 8, '0');
     1054    // out.str() == "0000cafe"
     1055
     1056  \endrst
     1057 */
     1058template <char TYPE_CODE, typename Char>
     1059IntFormatSpec<int, AlignTypeSpec<TYPE_CODE>, Char> pad(
     1060    int value, unsigned width, Char fill = ' ');
     1061
     1062#define FMT_DEFINE_INT_FORMATTERS(TYPE) \
     1063inline IntFormatSpec<TYPE, TypeSpec<'b'> > bin(TYPE value) { \
     1064  return IntFormatSpec<TYPE, TypeSpec<'b'> >(value, TypeSpec<'b'>()); \
     1065} \
     1066 \
     1067inline IntFormatSpec<TYPE, TypeSpec<'o'> > oct(TYPE value) { \
     1068  return IntFormatSpec<TYPE, TypeSpec<'o'> >(value, TypeSpec<'o'>()); \
     1069} \
     1070 \
     1071inline IntFormatSpec<TYPE, TypeSpec<'x'> > hex(TYPE value) { \
     1072  return IntFormatSpec<TYPE, TypeSpec<'x'> >(value, TypeSpec<'x'>()); \
     1073} \
     1074 \
     1075inline IntFormatSpec<TYPE, TypeSpec<'X'> > hexu(TYPE value) { \
     1076  return IntFormatSpec<TYPE, TypeSpec<'X'> >(value, TypeSpec<'X'>()); \
     1077} \
     1078 \
     1079template <char TYPE_CODE> \
     1080inline IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE> > pad( \
     1081    IntFormatSpec<TYPE, TypeSpec<TYPE_CODE> > f, unsigned width) { \
     1082  return IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE> >( \
     1083      f.value(), AlignTypeSpec<TYPE_CODE>(width, ' ')); \
     1084} \
     1085 \
     1086/* For compatibility with older compilers we provide two overloads for pad, */ \
     1087/* one that takes a fill character and one that doesn't. In the future this */ \
     1088/* can be replaced with one overload making the template argument Char      */ \
     1089/* default to char (C++11). */ \
     1090template <char TYPE_CODE, typename Char> \
     1091inline IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE>, Char> pad( \
     1092    IntFormatSpec<TYPE, TypeSpec<TYPE_CODE>, Char> f, \
     1093    unsigned width, Char fill) { \
     1094  return IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE>, Char>( \
     1095      f.value(), AlignTypeSpec<TYPE_CODE>(width, fill)); \
     1096} \
     1097 \
     1098inline IntFormatSpec<TYPE, AlignTypeSpec<0> > pad( \
     1099    TYPE value, unsigned width) { \
     1100  return IntFormatSpec<TYPE, AlignTypeSpec<0> >( \
     1101      value, AlignTypeSpec<0>(width, ' ')); \
     1102} \
     1103 \
     1104template <typename Char> \
     1105inline IntFormatSpec<TYPE, AlignTypeSpec<0>, Char> pad( \
     1106   TYPE value, unsigned width, Char fill) { \
     1107 return IntFormatSpec<TYPE, AlignTypeSpec<0>, Char>( \
     1108     value, AlignTypeSpec<0>(width, fill)); \
     1109}
     1110
     1111FMT_DEFINE_INT_FORMATTERS(int)
     1112FMT_DEFINE_INT_FORMATTERS(long)
     1113FMT_DEFINE_INT_FORMATTERS(unsigned)
     1114FMT_DEFINE_INT_FORMATTERS(unsigned long)
     1115FMT_DEFINE_INT_FORMATTERS(LongLong)
     1116FMT_DEFINE_INT_FORMATTERS(ULongLong)
     1117
     1118/**
     1119  \rst
     1120  Returns a string formatter that pads the formatted argument with the fill
     1121  character to the specified width using the default (left) string alignment.
     1122
     1123  **Example**::
     1124
     1125    std::string s = str(Writer() << pad("abc", 8));
     1126    // s == "abc     "
     1127
     1128  \endrst
     1129 */
     1130template <typename Char>
     1131inline StrFormatSpec<Char> pad(
     1132    const Char *str, unsigned width, Char fill = ' ') {
     1133  return StrFormatSpec<Char>(str, width, fill);
     1134}
     1135
     1136inline StrFormatSpec<wchar_t> pad(
     1137    const wchar_t *str, unsigned width, char fill = ' ') {
     1138  return StrFormatSpec<wchar_t>(str, width, fill);
     1139}
     1140
     1141// Generates a comma-separated list with results of applying f to numbers 0..n-1.
     1142# define FMT_GEN(n, f) FMT_GEN##n(f)
     1143# define FMT_GEN1(f)  f(0)
     1144# define FMT_GEN2(f)  FMT_GEN1(f), f(1)
     1145# define FMT_GEN3(f)  FMT_GEN2(f), f(2)
     1146# define FMT_GEN4(f)  FMT_GEN3(f), f(3)
     1147# define FMT_GEN5(f)  FMT_GEN4(f), f(4)
     1148# define FMT_GEN6(f)  FMT_GEN5(f), f(5)
     1149# define FMT_GEN7(f)  FMT_GEN6(f), f(6)
     1150# define FMT_GEN8(f)  FMT_GEN7(f), f(7)
     1151# define FMT_GEN9(f)  FMT_GEN8(f), f(8)
     1152# define FMT_GEN10(f) FMT_GEN9(f), f(9)
     1153
     1154# define FMT_MAKE_TEMPLATE_ARG(n) typename T##n
     1155# define FMT_MAKE_ARG(n) const T##n &v##n
     1156# define FMT_MAKE_REF_char(n) fmt::internal::MakeArg<char>(v##n)
     1157# define FMT_MAKE_REF_wchar_t(n) fmt::internal::MakeArg<wchar_t>(v##n)
     1158
     1159#if FMT_USE_VARIADIC_TEMPLATES
     1160// Defines a variadic function returning void.
     1161# define FMT_VARIADIC_VOID(func, arg_type) \
     1162  template<typename... Args> \
     1163  void func(arg_type arg1, const Args & ... args) { \
     1164    using fmt::internal::Arg; \
     1165    const Arg arg_array[fmt::internal::NonZero<sizeof...(Args)>::VALUE] = { \
     1166      fmt::internal::MakeArg<Char>(args)... \
     1167    }; \
     1168    func(arg1, ArgList(arg_array, sizeof...(Args))); \
     1169  }
     1170
     1171// Defines a variadic constructor.
     1172# define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \
     1173  template<typename... Args> \
     1174  ctor(arg0_type arg0, arg1_type arg1, const Args & ... args) { \
     1175    using fmt::internal::Arg; \
     1176    const Arg arg_array[fmt::internal::NonZero<sizeof...(Args)>::VALUE] = { \
     1177      fmt::internal::MakeArg<Char>(args)... \
     1178    }; \
     1179    func(arg0, arg1, ArgList(arg_array, sizeof...(Args))); \
     1180  }
     1181
     1182#else
     1183
     1184# define FMT_MAKE_REF(n) fmt::internal::MakeArg<Char>(v##n)
     1185// Defines a wrapper for a function taking one argument of type arg_type
     1186// and n additional arguments of arbitrary types.
     1187# define FMT_WRAP1(func, arg_type, n) \
     1188  template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
     1189  inline void func(arg_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \
     1190    const fmt::internal::Arg args[] = {FMT_GEN(n, FMT_MAKE_REF)}; \
     1191    func(arg1, fmt::ArgList(args, sizeof(args) / sizeof(*args))); \
     1192  }
     1193
     1194// Emulates a variadic function returning void on a pre-C++11 compiler.
     1195# define FMT_VARIADIC_VOID(func, arg_type) \
     1196  FMT_WRAP1(func, arg_type, 1) FMT_WRAP1(func, arg_type, 2) \
     1197  FMT_WRAP1(func, arg_type, 3) FMT_WRAP1(func, arg_type, 4) \
     1198  FMT_WRAP1(func, arg_type, 5) FMT_WRAP1(func, arg_type, 6) \
     1199  FMT_WRAP1(func, arg_type, 7) FMT_WRAP1(func, arg_type, 8) \
     1200  FMT_WRAP1(func, arg_type, 9) FMT_WRAP1(func, arg_type, 10)
     1201
     1202# define FMT_CTOR(ctor, func, arg0_type, arg1_type, n) \
     1203  template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
     1204  ctor(arg0_type arg0, arg1_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \
     1205    const fmt::internal::Arg args[] = {FMT_GEN(n, FMT_MAKE_REF)}; \
     1206    func(arg0, arg1, fmt::ArgList(args, sizeof(args) / sizeof(*args))); \
     1207  }
     1208
     1209// Emulates a variadic constructor on a pre-C++11 compiler.
     1210# define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \
     1211  FMT_CTOR(ctor, func, arg0_type, arg1_type, 1) \
     1212  FMT_CTOR(ctor, func, arg0_type, arg1_type, 2) \
     1213  FMT_CTOR(ctor, func, arg0_type, arg1_type, 3) \
     1214  FMT_CTOR(ctor, func, arg0_type, arg1_type, 4) \
     1215  FMT_CTOR(ctor, func, arg0_type, arg1_type, 5) \
     1216  FMT_CTOR(ctor, func, arg0_type, arg1_type, 6) \
     1217  FMT_CTOR(ctor, func, arg0_type, arg1_type, 7) \
     1218  FMT_CTOR(ctor, func, arg0_type, arg1_type, 8) \
     1219  FMT_CTOR(ctor, func, arg0_type, arg1_type, 9) \
     1220  FMT_CTOR(ctor, func, arg0_type, arg1_type, 10)
     1221#endif
     1222
     1223// Generates a comma-separated list with results of applying f to pairs
     1224// (argument, index).
     1225#define FMT_FOR_EACH1(f, x0) f(x0, 0)
     1226#define FMT_FOR_EACH2(f, x0, x1) \
     1227  FMT_FOR_EACH1(f, x0), f(x1, 1)
     1228#define FMT_FOR_EACH3(f, x0, x1, x2) \
     1229  FMT_FOR_EACH2(f, x0 ,x1), f(x2, 2)
     1230#define FMT_FOR_EACH4(f, x0, x1, x2, x3) \
     1231  FMT_FOR_EACH3(f, x0, x1, x2), f(x3, 3)
     1232#define FMT_FOR_EACH5(f, x0, x1, x2, x3, x4) \
     1233  FMT_FOR_EACH4(f, x0, x1, x2, x3), f(x4, 4)
     1234#define FMT_FOR_EACH6(f, x0, x1, x2, x3, x4, x5) \
     1235  FMT_FOR_EACH5(f, x0, x1, x2, x3, x4), f(x5, 5)
     1236#define FMT_FOR_EACH7(f, x0, x1, x2, x3, x4, x5, x6) \
     1237  FMT_FOR_EACH6(f, x0, x1, x2, x3, x4, x5), f(x6, 6)
     1238#define FMT_FOR_EACH8(f, x0, x1, x2, x3, x4, x5, x6, x7) \
     1239  FMT_FOR_EACH7(f, x0, x1, x2, x3, x4, x5, x6), f(x7, 7)
     1240#define FMT_FOR_EACH9(f, x0, x1, x2, x3, x4, x5, x6, x7, x8) \
     1241  FMT_FOR_EACH8(f, x0, x1, x2, x3, x4, x5, x6, x7), f(x8, 8)
     1242#define FMT_FOR_EACH10(f, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9) \
     1243  FMT_FOR_EACH9(f, x0, x1, x2, x3, x4, x5, x6, x7, x8), f(x9, 9)
     1244
     1245/**
     1246An error returned by an operating system or a language runtime,
     1247for example a file opening error.
     1248*/
     1249class SystemError : public internal::RuntimeError {
     1250 private:
     1251  void init(int error_code, StringRef format_str, const ArgList &args);
     1252
     1253 protected:
     1254  int error_code_;
     1255
     1256  typedef char Char;  // For FMT_VARIADIC_CTOR.
     1257
     1258  SystemError() {}
     1259
     1260 public:
     1261  /**
     1262   \rst
     1263   Constructs a :cpp:class:`fmt::SystemError` object with the description
     1264   of the form "*<message>*: *<system-message>*", where *<message>* is the
     1265   formatted message and *<system-message>* is the system message corresponding
     1266   to the error code.
     1267   *error_code* is a system error code as given by ``errno``.
     1268   \endrst
     1269  */
     1270  SystemError(int error_code, StringRef message) {
     1271    init(error_code, message, ArgList());
     1272  }
     1273  FMT_VARIADIC_CTOR(SystemError, init, int, StringRef)
     1274
     1275  int error_code() const { return error_code_; }
     1276};
     1277
     1278/**
     1279  \rst
     1280  This template provides operations for formatting and writing data into
     1281  a character stream. The output is stored in a memory buffer that grows
     1282  dynamically.
     1283
     1284  You can use one of the following typedefs for common character types:
     1285
     1286  +---------+----------------------+
     1287  | Type    | Definition           |
     1288  +=========+======================+
     1289  | Writer  | BasicWriter<char>    |
     1290  +---------+----------------------+
     1291  | WWriter | BasicWriter<wchar_t> |
     1292  +---------+----------------------+
     1293
     1294  **Example**::
     1295
     1296     Writer out;
     1297     out << "The answer is " << 42 << "\n";
     1298     out.write("({:+f}, {:+f})", -3.14, 3.14);
     1299
     1300  This will write the following output to the ``out`` object:
     1301
     1302  .. code-block:: none
     1303
     1304     The answer is 42
     1305     (-3.140000, +3.140000)
     1306
     1307  The output can be converted to an ``std::string`` with ``out.str()`` or
     1308  accessed as a C string with ``out.c_str()``.
     1309  \endrst
     1310 */
     1311template <typename Char>
     1312class BasicWriter {
     1313 private:
     1314  // Output buffer.
     1315  mutable internal::Array<Char, internal::INLINE_BUFFER_SIZE> buffer_;
     1316
     1317  typedef typename internal::CharTraits<Char>::CharPtr CharPtr;
     1318
     1319#if defined(_SECURE_SCL) && _SECURE_SCL
     1320  // Returns pointer value.
     1321  static Char *get(CharPtr p) { return p.base(); }
     1322#else
     1323  static Char *get(Char *p) { return p; }
     1324#endif
     1325
     1326  static CharPtr fill_padding(CharPtr buffer,
     1327      unsigned total_size, std::size_t content_size, wchar_t fill);
     1328
     1329  // Grows the buffer by n characters and returns a pointer to the newly
     1330  // allocated area.
     1331  CharPtr grow_buffer(std::size_t n) {
     1332    std::size_t size = buffer_.size();
     1333    buffer_.resize(size + n);
     1334    return internal::make_ptr(&buffer_[size], n);
     1335  }
     1336
     1337  // Prepare a buffer for integer formatting.
     1338  CharPtr prepare_int_buffer(unsigned num_digits,
     1339      const EmptySpec &, const char *prefix, unsigned prefix_size) {
     1340    unsigned size = prefix_size + num_digits;
     1341    CharPtr p = grow_buffer(size);
     1342    std::copy(prefix, prefix + prefix_size, p);
     1343    return p + size - 1;
     1344  }
     1345
     1346  template <typename Spec>
     1347  CharPtr prepare_int_buffer(unsigned num_digits,
     1348    const Spec &spec, const char *prefix, unsigned prefix_size);
     1349
     1350  // Formats an integer.
     1351  template <typename T, typename Spec>
     1352  void write_int(T value, const Spec &spec);
     1353
     1354  // Formats a floating-point number (double or long double).
     1355  template <typename T>
     1356  void write_double(T value, const FormatSpec &spec);
     1357
     1358  // Writes a formatted string.
     1359  template <typename StrChar>
     1360  CharPtr write_str(
     1361      const StrChar *s, std::size_t size, const AlignSpec &spec);
     1362
     1363  template <typename StrChar>
     1364  void write_str(
     1365      const internal::Arg::StringValue<StrChar> &str, const FormatSpec &spec);
     1366
     1367  // This method is private to disallow writing a wide string to a
     1368  // char stream and vice versa. If you want to print a wide string
     1369  // as a pointer as std::ostream does, cast it to const void*.
     1370  // Do not implement!
     1371  void operator<<(typename internal::CharTraits<Char>::UnsupportedStrType);
     1372
     1373  friend class internal::ArgFormatter<Char>;
     1374  friend class internal::PrintfFormatter<Char>;
     1375
     1376 public:
     1377  /**
     1378    Constructs a ``BasicWriter`` object.
     1379   */
     1380  BasicWriter() {}
     1381
     1382#if FMT_USE_RVALUE_REFERENCES
     1383  /**
     1384    Constructs a ``BasicWriter`` object moving the content of the other
     1385    object to it.
     1386   */
     1387  BasicWriter(BasicWriter &&other) : buffer_(std::move(other.buffer_)) {}
     1388
     1389  /**
     1390    Moves the content of the other ``BasicWriter`` object to this one.
     1391   */
     1392  BasicWriter& operator=(BasicWriter &&other) {
     1393    assert(this != &other);
     1394    buffer_ = std::move(other.buffer_);
     1395    return *this;
     1396  }
     1397#endif
     1398
     1399  /**
     1400    Returns the total number of characters written.
     1401   */
     1402  std::size_t size() const { return buffer_.size(); }
     1403
     1404  /**
     1405    Returns a pointer to the output buffer content. No terminating null
     1406    character is appended.
     1407   */
     1408  const Char *data() const { return &buffer_[0]; }
     1409
     1410  /**
     1411    Returns a pointer to the output buffer content with terminating null
     1412    character appended.
     1413   */
     1414  const Char *c_str() const {
     1415    std::size_t size = buffer_.size();
     1416    buffer_.reserve(size + 1);
     1417    buffer_[size] = '\0';
     1418    return &buffer_[0];
     1419  }
     1420
     1421  /**
     1422    Returns the content of the output buffer as an `std::string`.
     1423   */
     1424  std::basic_string<Char> str() const {
     1425    return std::basic_string<Char>(&buffer_[0], buffer_.size());
     1426  }
     1427
     1428  /**
     1429    \rst
     1430    Writes formatted data.
     1431   
     1432    *args* is an argument list representing arbitrary arguments.
     1433
     1434    **Example**::
     1435
     1436       Writer out;
     1437       out.write("Current point:\n");
     1438       out.write("({:+f}, {:+f})", -3.14, 3.14);
     1439
     1440    This will write the following output to the ``out`` object:
     1441
     1442    .. code-block:: none
     1443
     1444       Current point:
     1445       (-3.140000, +3.140000)
     1446
     1447    The output can be accessed using :meth:`data`, :meth:`c_str` or :meth:`str`
     1448    methods.
     1449
     1450    See also `Format String Syntax`_.
     1451    \endrst
     1452   */
     1453  void write(BasicStringRef<Char> format, const ArgList &args) {
     1454    BasicFormatter<Char>(*this).format(format, args);
     1455  }
     1456  FMT_VARIADIC_VOID(write, fmt::BasicStringRef<Char>)
     1457
     1458  BasicWriter &operator<<(int value) {
     1459    return *this << IntFormatSpec<int>(value);
     1460  }
     1461  BasicWriter &operator<<(unsigned value) {
     1462    return *this << IntFormatSpec<unsigned>(value);
     1463  }
     1464  BasicWriter &operator<<(long value) {
     1465    return *this << IntFormatSpec<long>(value);
     1466  }
     1467  BasicWriter &operator<<(unsigned long value) {
     1468    return *this << IntFormatSpec<unsigned long>(value);
     1469  }
     1470  BasicWriter &operator<<(LongLong value) {
     1471    return *this << IntFormatSpec<LongLong>(value);
     1472  }
     1473
     1474  /**
     1475    Formats *value* and writes it to the stream.
     1476   */
     1477  BasicWriter &operator<<(ULongLong value) {
     1478    return *this << IntFormatSpec<ULongLong>(value);
     1479  }
     1480
     1481  BasicWriter &operator<<(double value) {
     1482    write_double(value, FormatSpec());
     1483    return *this;
     1484  }
     1485
     1486  /**
     1487    Formats *value* using the general format for floating-point numbers
     1488    (``'g'``) and writes it to the stream.
     1489   */
     1490  BasicWriter &operator<<(long double value) {
     1491    write_double(value, FormatSpec());
     1492    return *this;
     1493  }
     1494
     1495  /**
     1496    Writes a character to the stream.
     1497   */
     1498  BasicWriter &operator<<(char value) {
     1499    buffer_.push_back(value);
     1500    return *this;
     1501  }
     1502
     1503  BasicWriter &operator<<(wchar_t value) {
     1504    buffer_.push_back(internal::CharTraits<Char>::convert(value));
     1505    return *this;
     1506  }
     1507
     1508  /**
     1509    Writes *value* to the stream.
     1510   */
     1511  BasicWriter &operator<<(fmt::BasicStringRef<Char> value) {
     1512    const Char *str = value.c_str();
     1513    buffer_.append(str, str + value.size());
     1514    return *this;
     1515  }
     1516
     1517  template <typename T, typename Spec, typename FillChar>
     1518  BasicWriter &operator<<(const IntFormatSpec<T, Spec, FillChar> &spec) {
     1519    internal::CharTraits<Char>::convert(FillChar());
     1520    write_int(spec.value(), spec);
     1521    return *this;
     1522  }
     1523
     1524  template <typename StrChar>
     1525  BasicWriter &operator<<(const StrFormatSpec<StrChar> &spec) {
     1526    const StrChar *s = spec.str();
     1527    // TODO: error if fill is not convertible to Char
     1528    write_str(s, std::char_traits<Char>::length(s), spec);
     1529    return *this;
     1530  }
     1531
     1532  void clear() { buffer_.clear(); }
     1533};
     1534
     1535template <typename Char>
     1536template <typename StrChar>
     1537typename BasicWriter<Char>::CharPtr BasicWriter<Char>::write_str(
     1538    const StrChar *s, std::size_t size, const AlignSpec &spec) {
     1539  CharPtr out = CharPtr();
     1540  if (spec.width() > size) {
     1541    out = grow_buffer(spec.width());
     1542    Char fill = static_cast<Char>(spec.fill());
     1543    if (spec.align() == ALIGN_RIGHT) {
     1544      std::fill_n(out, spec.width() - size, fill);
     1545      out += spec.width() - size;
     1546    } else if (spec.align() == ALIGN_CENTER) {
     1547      out = fill_padding(out, spec.width(), size, fill);
     1548    } else {
     1549      std::fill_n(out + size, spec.width() - size, fill);
     1550    }
     1551  } else {
     1552    out = grow_buffer(size);
     1553  }
     1554  std::copy(s, s + size, out);
     1555  return out;
     1556}
     1557
     1558template <typename Char>
     1559template <typename Spec>
     1560typename fmt::BasicWriter<Char>::CharPtr
     1561  fmt::BasicWriter<Char>::prepare_int_buffer(
     1562    unsigned num_digits, const Spec &spec,
     1563    const char *prefix, unsigned prefix_size) {
     1564  unsigned width = spec.width();
     1565  Alignment align = spec.align();
     1566  Char fill = static_cast<Char>(spec.fill());
     1567  if (spec.precision() > static_cast<int>(num_digits)) {
     1568    // Octal prefix '0' is counted as a digit, so ignore it if precision
     1569    // is specified.
     1570    if (prefix_size > 0 && prefix[prefix_size - 1] == '0')
     1571      --prefix_size;
     1572    unsigned number_size = prefix_size + spec.precision();
     1573    AlignSpec subspec(number_size, '0', ALIGN_NUMERIC);
     1574    if (number_size >= width)
     1575      return prepare_int_buffer(num_digits, subspec, prefix, prefix_size);
     1576    buffer_.reserve(width);
     1577    unsigned fill_size = width - number_size;
     1578    if (align != ALIGN_LEFT) {
     1579      CharPtr p = grow_buffer(fill_size);
     1580      std::fill(p, p + fill_size, fill);
     1581    }
     1582    CharPtr result = prepare_int_buffer(
     1583        num_digits, subspec, prefix, prefix_size);
     1584    if (align == ALIGN_LEFT) {
     1585      CharPtr p = grow_buffer(fill_size);
     1586      std::fill(p, p + fill_size, fill);
     1587    }
     1588    return result;
     1589  }
     1590  unsigned size = prefix_size + num_digits;
     1591  if (width <= size) {
     1592    CharPtr p = grow_buffer(size);
     1593    std::copy(prefix, prefix + prefix_size, p);
     1594    return p + size - 1;
     1595  }
     1596  CharPtr p = grow_buffer(width);
     1597  CharPtr end = p + width;
     1598  if (align == ALIGN_LEFT) {
     1599    std::copy(prefix, prefix + prefix_size, p);
     1600    p += size;
     1601    std::fill(p, end, fill);
     1602  } else if (align == ALIGN_CENTER) {
     1603    p = fill_padding(p, width, size, fill);
     1604    std::copy(prefix, prefix + prefix_size, p);
     1605    p += size;
     1606  } else {
     1607    if (align == ALIGN_NUMERIC) {
     1608      if (prefix_size != 0) {
     1609        p = std::copy(prefix, prefix + prefix_size, p);
     1610        size -= prefix_size;
     1611      }
     1612    } else {
     1613      std::copy(prefix, prefix + prefix_size, end - size);
     1614    }
     1615    std::fill(p, end - size, fill);
     1616    p = end;
     1617  }
     1618  return p - 1;
     1619}
     1620
     1621template <typename Char>
     1622template <typename T, typename Spec>
     1623void BasicWriter<Char>::write_int(T value, const Spec &spec) {
     1624  unsigned prefix_size = 0;
     1625  typedef typename internal::IntTraits<T>::MainType UnsignedType;
     1626  UnsignedType abs_value = value;
     1627  char prefix[4] = "";
     1628  if (internal::is_negative(value)) {
     1629    prefix[0] = '-';
     1630    ++prefix_size;
     1631    abs_value = 0 - abs_value;
     1632  } else if (spec.flag(SIGN_FLAG)) {
     1633    prefix[0] = spec.flag(PLUS_FLAG) ? '+' : ' ';
     1634    ++prefix_size;
     1635  }
     1636  switch (spec.type()) {
     1637  case 0: case 'd': {
     1638    unsigned num_digits = internal::count_digits(abs_value);
     1639    CharPtr p = prepare_int_buffer(
     1640      num_digits, spec, prefix, prefix_size) + 1 - num_digits;
     1641    internal::format_decimal(get(p), abs_value, num_digits);
     1642    break;
     1643  }
     1644  case 'x': case 'X': {
     1645    UnsignedType n = abs_value;
     1646    if (spec.flag(HASH_FLAG)) {
     1647      prefix[prefix_size++] = '0';
     1648      prefix[prefix_size++] = spec.type();
     1649    }
     1650    unsigned num_digits = 0;
     1651    do {
     1652      ++num_digits;
     1653    } while ((n >>= 4) != 0);
     1654    Char *p = get(prepare_int_buffer(
     1655      num_digits, spec, prefix, prefix_size));
     1656    n = abs_value;
     1657    const char *digits = spec.type() == 'x' ?
     1658        "0123456789abcdef" : "0123456789ABCDEF";
     1659    do {
     1660      *p-- = digits[n & 0xf];
     1661    } while ((n >>= 4) != 0);
     1662    break;
     1663  }
     1664  case 'b': case 'B': {
     1665    UnsignedType n = abs_value;
     1666    if (spec.flag(HASH_FLAG)) {
     1667      prefix[prefix_size++] = '0';
     1668      prefix[prefix_size++] = spec.type();
     1669    }
     1670    unsigned num_digits = 0;
     1671    do {
     1672      ++num_digits;
     1673    } while ((n >>= 1) != 0);
     1674    Char *p = get(prepare_int_buffer(num_digits, spec, prefix, prefix_size));
     1675    n = abs_value;
     1676    do {
     1677      *p-- = '0' + (n & 1);
     1678    } while ((n >>= 1) != 0);
     1679    break;
     1680  }
     1681  case 'o': {
     1682    UnsignedType n = abs_value;
     1683    if (spec.flag(HASH_FLAG))
     1684      prefix[prefix_size++] = '0';
     1685    unsigned num_digits = 0;
     1686    do {
     1687      ++num_digits;
     1688    } while ((n >>= 3) != 0);
     1689    Char *p = get(prepare_int_buffer(num_digits, spec, prefix, prefix_size));
     1690    n = abs_value;
     1691    do {
     1692      *p-- = '0' + (n & 7);
     1693    } while ((n >>= 3) != 0);
     1694    break;
     1695  }
     1696  default:
     1697    internal::report_unknown_type(
     1698      spec.type(), spec.flag(CHAR_FLAG) ? "char" : "integer");
     1699    break;
     1700  }
     1701}
     1702
     1703// Formats a value.
     1704template <typename Char, typename T>
     1705void format(BasicFormatter<Char> &f, const Char *format_str, const T &value) {
     1706  std::basic_ostringstream<Char> os;
     1707  os << value;
     1708  f.format(format_str, internal::MakeArg<Char>(os.str()));
     1709}
     1710
     1711// Reports a system error without throwing an exception.
     1712// Can be used to report errors from destructors.
     1713void report_system_error(int error_code, StringRef message) FMT_NOEXCEPT(true);
     1714
     1715#ifdef _WIN32
     1716
     1717/**
     1718 A Windows error.
     1719*/
     1720class WindowsError : public SystemError {
     1721 private:
     1722  void init(int error_code, StringRef format_str, const ArgList &args);
     1723
     1724 public:
     1725  /**
     1726   \rst
     1727   Constructs a :cpp:class:`fmt::WindowsError` object with the description
     1728   of the form "*<message>*: *<system-message>*", where *<message>* is the
     1729   formatted message and *<system-message>* is the system message corresponding
     1730   to the error code.
     1731   *error_code* is a Windows error code as given by ``GetLastError``.
     1732   \endrst
     1733  */
     1734  WindowsError(int error_code, StringRef message) {
     1735    init(error_code, message, ArgList());
     1736  }
     1737  FMT_VARIADIC_CTOR(WindowsError, init, int, StringRef)
     1738};
     1739
     1740// Reports a Windows error without throwing an exception.
     1741// Can be used to report errors from destructors.
     1742void report_windows_error(int error_code, StringRef message) FMT_NOEXCEPT(true);
     1743
     1744#endif
     1745
     1746enum Color { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE };
     1747
     1748/**
     1749  Formats a string and prints it to stdout using ANSI escape sequences
     1750  to specify color (experimental).
     1751  Example:
     1752    PrintColored(fmt::RED, "Elapsed time: {0:.2f} seconds") << 1.23;
     1753 */
     1754void print_colored(Color c, StringRef format, const ArgList &args);
     1755
     1756/**
     1757  \rst
     1758  Formats arguments and returns the result as a string.
     1759
     1760  **Example**::
     1761
     1762    std::string message = format("The answer is {}", 42);
     1763  \endrst
     1764*/
     1765inline std::string format(StringRef format_str, const ArgList &args) {
     1766  Writer w;
     1767  w.write(format_str, args);
     1768  return w.str();
     1769}
     1770
     1771inline std::wstring format(WStringRef format_str, const ArgList &args) {
     1772  WWriter w;
     1773  w.write(format_str, args);
     1774  return w.str();
     1775}
     1776
     1777/**
     1778  \rst
     1779  Prints formatted data to the file *f*.
     1780
     1781  **Example**::
     1782
     1783    print(stderr, "Don't {}!", "panic");
     1784  \endrst
     1785 */
     1786void print(std::FILE *f, StringRef format_str, const ArgList &args);
     1787
     1788/**
     1789  \rst
     1790  Prints formatted data to ``stdout``.
     1791
     1792  **Example**::
     1793
     1794    print("Elapsed time: {0:.2f} seconds", 1.23);
     1795  \endrst
     1796 */
     1797inline void print(StringRef format_str, const ArgList &args) {
     1798  print(stdout, format_str, args);
     1799}
     1800
     1801/**
     1802  \rst
     1803  Prints formatted data to the stream *os*.
     1804
     1805  **Example**::
     1806
     1807    print(cerr, "Don't {}!", "panic");
     1808  \endrst
     1809 */
     1810void print(std::ostream &os, StringRef format_str, const ArgList &args);
     1811
     1812template <typename Char>
     1813void printf(BasicWriter<Char> &w,
     1814    BasicStringRef<Char> format, const ArgList &args) {
     1815  internal::PrintfFormatter<Char>().format(w, format, args);
     1816}
     1817
     1818/**
     1819  \rst
     1820  Formats arguments and returns the result as a string.
     1821
     1822  **Example**::
     1823
     1824    std::string message = fmt::sprintf("The answer is %d", 42);
     1825  \endrst
     1826*/
     1827inline std::string sprintf(StringRef format, const ArgList &args) {
     1828  Writer w;
     1829  printf(w, format, args);
     1830  return w.str();
     1831}
     1832
     1833/**
     1834  \rst
     1835  Prints formatted data to the file *f*.
     1836
     1837  **Example**::
     1838
     1839    fmt::fprintf(stderr, "Don't %s!", "panic");
     1840  \endrst
     1841 */
     1842int fprintf(std::FILE *f, StringRef format, const ArgList &args);
     1843
     1844/**
     1845  \rst
     1846  Prints formatted data to ``stdout``.
     1847
     1848  **Example**::
     1849
     1850    fmt::printf("Elapsed time: %.2f seconds", 1.23);
     1851  \endrst
     1852 */
     1853inline int printf(StringRef format, const ArgList &args) {
     1854  return fprintf(stdout, format, args);
     1855}
     1856
     1857/**
     1858  Fast integer formatter.
     1859 */
     1860class FormatInt {
     1861 private:
     1862  // Buffer should be large enough to hold all digits (digits10 + 1),
     1863  // a sign and a null character.
     1864  enum {BUFFER_SIZE = std::numeric_limits<ULongLong>::digits10 + 3};
     1865  mutable char buffer_[BUFFER_SIZE];
     1866  char *str_;
     1867
     1868  // Formats value in reverse and returns the number of digits.
     1869  char *format_decimal(ULongLong value) {
     1870    char *buffer_end = buffer_ + BUFFER_SIZE - 1;
     1871    while (value >= 100) {
     1872      // Integer division is slow so do it for a group of two digits instead
     1873      // of for every digit. The idea comes from the talk by Alexandrescu
     1874      // "Three Optimization Tips for C++". See speed-test for a comparison.
     1875      unsigned index = (value % 100) * 2;
     1876      value /= 100;
     1877      *--buffer_end = internal::DIGITS[index + 1];
     1878      *--buffer_end = internal::DIGITS[index];
     1879    }
     1880    if (value < 10) {
     1881      *--buffer_end = static_cast<char>('0' + value);
     1882      return buffer_end;
     1883    }
     1884    unsigned index = static_cast<unsigned>(value * 2);
     1885    *--buffer_end = internal::DIGITS[index + 1];
     1886    *--buffer_end = internal::DIGITS[index];
     1887    return buffer_end;
     1888  }
     1889
     1890  void FormatSigned(LongLong value) {
     1891    ULongLong abs_value = static_cast<ULongLong>(value);
     1892    bool negative = value < 0;
     1893    if (negative)
     1894      abs_value = 0 - abs_value;
     1895    str_ = format_decimal(abs_value);
     1896    if (negative)
     1897      *--str_ = '-';
     1898  }
     1899
     1900 public:
     1901  explicit FormatInt(int value) { FormatSigned(value); }
     1902  explicit FormatInt(long value) { FormatSigned(value); }
     1903  explicit FormatInt(LongLong value) { FormatSigned(value); }
     1904  explicit FormatInt(unsigned value) : str_(format_decimal(value)) {}
     1905  explicit FormatInt(unsigned long value) : str_(format_decimal(value)) {}
     1906  explicit FormatInt(ULongLong value) : str_(format_decimal(value)) {}
     1907
     1908  /**
     1909    Returns the number of characters written to the output buffer.
     1910   */
     1911  std::size_t size() const { return buffer_ - str_ + BUFFER_SIZE - 1; }
     1912
     1913  /**
     1914    Returns a pointer to the output buffer content. No terminating null
     1915    character is appended.
     1916   */
     1917  const char *data() const { return str_; }
     1918
     1919  /**
     1920    Returns a pointer to the output buffer content with terminating null
     1921    character appended.
     1922   */
     1923  const char *c_str() const {
     1924    buffer_[BUFFER_SIZE - 1] = '\0';
     1925    return str_;
     1926  }
     1927
     1928  /**
     1929    Returns the content of the output buffer as an `std::string`.
     1930   */
     1931  std::string str() const { return std::string(str_, size()); }
     1932};
     1933
     1934// Formats a decimal integer value writing into buffer and returns
     1935// a pointer to the end of the formatted string. This function doesn't
     1936// write a terminating null character.
     1937template <typename T>
     1938inline void format_decimal(char *&buffer, T value) {
     1939  typename internal::IntTraits<T>::MainType abs_value = value;
     1940  if (internal::is_negative(value)) {
     1941    *buffer++ = '-';
     1942    abs_value = 0 - abs_value;
     1943  }
     1944  if (abs_value < 100) {
     1945    if (abs_value < 10) {
     1946      *buffer++ = static_cast<char>('0' + abs_value);
     1947      return;
     1948    }
     1949    unsigned index = static_cast<unsigned>(abs_value * 2);
     1950    *buffer++ = internal::DIGITS[index];
     1951    *buffer++ = internal::DIGITS[index + 1];
     1952    return;
     1953  }
     1954  unsigned num_digits = internal::count_digits(abs_value);
     1955  internal::format_decimal(buffer, abs_value, num_digits);
     1956  buffer += num_digits;
     1957}
     1958}
     1959
     1960#if FMT_GCC_VERSION
     1961// Use the system_header pragma to suppress warnings about variadic macros
     1962// because suppressing -Wvariadic-macros with the diagnostic pragma doesn't
     1963// work. It is used at the end because we want to suppress as little warnings
     1964// as possible.
     1965# pragma GCC system_header
     1966#endif
     1967
     1968// This is used to work around VC++ bugs in handling variadic macros.
     1969#define FMT_EXPAND(args) args
     1970
     1971// Returns the number of arguments.
     1972// Based on https://groups.google.com/forum/#!topic/comp.std.c/d-6Mj5Lko_s.
     1973#define FMT_NARG(...) FMT_NARG_(__VA_ARGS__, FMT_RSEQ_N())
     1974#define FMT_NARG_(...) FMT_EXPAND(FMT_ARG_N(__VA_ARGS__))
     1975#define FMT_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
     1976#define FMT_RSEQ_N() 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
     1977
     1978#define FMT_CONCAT(a, b) a##b
     1979#define FMT_FOR_EACH_(N, f, ...) \
     1980  FMT_EXPAND(FMT_CONCAT(FMT_FOR_EACH, N)(f, __VA_ARGS__))
     1981#define FMT_FOR_EACH(f, ...) \
     1982  FMT_EXPAND(FMT_FOR_EACH_(FMT_NARG(__VA_ARGS__), f, __VA_ARGS__))
     1983
     1984#define FMT_ADD_ARG_NAME(type, index) type arg##index
     1985#define FMT_GET_ARG_NAME(type, index) arg##index
     1986
     1987#if FMT_USE_VARIADIC_TEMPLATES
     1988# define FMT_VARIADIC_(Char, ReturnType, func, call, ...) \
     1989  template<typename... Args> \
     1990  ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
     1991      const Args & ... args) { \
     1992    using fmt::internal::Arg; \
     1993    const Arg array[fmt::internal::NonZero<sizeof...(Args)>::VALUE] = { \
     1994      fmt::internal::MakeArg<Char>(args)... \
     1995    }; \
     1996    call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \
     1997      fmt::ArgList(array, sizeof...(Args))); \
     1998  }
     1999#else
     2000// Defines a wrapper for a function taking __VA_ARGS__ arguments
     2001// and n additional arguments of arbitrary types.
     2002# define FMT_WRAP(Char, ReturnType, func, call, n, ...) \
     2003  template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
     2004  inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
     2005      FMT_GEN(n, FMT_MAKE_ARG)) { \
     2006    const fmt::internal::Arg args[] = {FMT_GEN(n, FMT_MAKE_REF_##Char)}; \
     2007    call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \
     2008      fmt::ArgList(args, sizeof(args) / sizeof(*args))); \
     2009  }
     2010
     2011# define FMT_VARIADIC_(Char, ReturnType, func, call, ...) \
     2012  inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__)) { \
     2013    call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList()); \
     2014  } \
     2015  FMT_WRAP(Char, ReturnType, func, call, 1, __VA_ARGS__) \
     2016  FMT_WRAP(Char, ReturnType, func, call, 2, __VA_ARGS__) \
     2017  FMT_WRAP(Char, ReturnType, func, call, 3, __VA_ARGS__) \
     2018  FMT_WRAP(Char, ReturnType, func, call, 4, __VA_ARGS__) \
     2019  FMT_WRAP(Char, ReturnType, func, call, 5, __VA_ARGS__) \
     2020  FMT_WRAP(Char, ReturnType, func, call, 6, __VA_ARGS__) \
     2021  FMT_WRAP(Char, ReturnType, func, call, 7, __VA_ARGS__) \
     2022  FMT_WRAP(Char, ReturnType, func, call, 8, __VA_ARGS__) \
     2023  FMT_WRAP(Char, ReturnType, func, call, 9, __VA_ARGS__) \
     2024  FMT_WRAP(Char, ReturnType, func, call, 10, __VA_ARGS__)
     2025#endif  // FMT_USE_VARIADIC_TEMPLATES
     2026
     2027/**
     2028  \rst
     2029  Defines a variadic function with the specified return type, function name
     2030  and argument types passed as variable arguments to this macro.
     2031
     2032  **Example**::
     2033
     2034    void print_error(const char *file, int line, const char *format,
     2035                     const fmt::ArgList &args) {
     2036      fmt::print("{}: {}: ", file, line);
     2037      fmt::print(format, args);
     2038    }
     2039    FMT_VARIADIC(void, print_error, const char *, int, const char *)
     2040
     2041  ``FMT_VARIADIC`` is used for compatibility with legacy C++ compilers that
     2042  don't implement variadic templates. You don't have to use this macro if
     2043  you don't need legacy compiler support and can use variadic templates
     2044  directly::
     2045
     2046    template<typename... Args>
     2047    void print_error(const char *file, int line, const char *format,
     2048                     const Args & ... args) {
     2049      fmt::print("{}: {}: ", file, line);
     2050      fmt::print(format, args...);
     2051    }
     2052  \endrst
     2053 */
     2054#define FMT_VARIADIC(ReturnType, func, ...) \
     2055  FMT_VARIADIC_(char, ReturnType, func, return func, __VA_ARGS__)
     2056
     2057#define FMT_VARIADIC_W(ReturnType, func, ...) \
     2058  FMT_VARIADIC_(wchar_t, ReturnType, func, return func, __VA_ARGS__)
     2059
     2060namespace fmt {
     2061FMT_VARIADIC(std::string, format, StringRef)
     2062FMT_VARIADIC_W(std::wstring, format, WStringRef)
     2063FMT_VARIADIC(void, print, StringRef)
     2064FMT_VARIADIC(void, print, std::FILE *, StringRef)
     2065FMT_VARIADIC(void, print, std::ostream &, StringRef)
     2066FMT_VARIADIC(void, print_colored, Color, StringRef)
     2067FMT_VARIADIC(std::string, sprintf, StringRef)
     2068FMT_VARIADIC(int, printf, StringRef)
     2069FMT_VARIADIC(int, fprintf, std::FILE *, StringRef)
     2070}
     2071
     2072// Restore warnings.
     2073#if FMT_GCC_VERSION >= 406
     2074# pragma GCC diagnostic pop
     2075#endif
     2076
     2077#endif  // FMT_FORMAT_H_
  • source/tools/atlas/GameInterface/GameLoop.cpp

    diff --git a/source/tools/atlas/GameInterface/GameLoop.cpp b/source/tools/atlas/GameInterface/GameLoop.cpp
    index cc2fa20..342f983 100644
    a b static void* RunEngine(void* data)  
    178178                    debug_warn(L"Unrecognised message");
    179179                    // CLogger might not be initialised, but this error will be sent
    180180                    // to the debug output window anyway so people can still see it
    181                     LOGERROR(L"Unrecognised message (%hs)", name.c_str());
     181                    LOGERROR("Unrecognised message (%s)", name.c_str());
    182182                }
    183183
    184184                if (msg->GetType() == IMessage::Query)
  • source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp

    diff --git a/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp
    index 38060ee..9a7c2e7 100644
    a b MESSAGEHANDLER(ImportHeightmap)  
    176176    File file;
    177177    if (file.Open(src, O_RDONLY) < 0)
    178178    {
    179         LOGERROR(L"Failed to load heightmap.");
     179        LOGERROR("Failed to load heightmap.");
    180180        return;
    181181    }
    182182   
    MESSAGEHANDLER(ImportHeightmap)  
    187187   
    188188    if (read(file.Descriptor(), fileData.get(), fileSize) < 0)
    189189    {
    190         LOGERROR(L"Failed to read heightmap image.");
     190        LOGERROR("Failed to read heightmap image.");
    191191        file.Close();
    192192        return;
    193193    }
    MESSAGEHANDLER(ImportHeightmap)  
    198198    Tex tex;
    199199    if (tex.decode(fileData, fileSize) < 0)
    200200    {
    201         LOGERROR(L"Failed to decode heightmap.");
     201        LOGERROR("Failed to decode heightmap.");
    202202        return;
    203203    }
    204204
    205205    // Convert to uncompressed BGRA with no mipmaps
    206206    if (tex.transform_to((tex.m_Flags | TEX_BGR | TEX_ALPHA) & ~(TEX_DXT | TEX_MIPMAPS)) < 0)
    207207    {
    208         LOGERROR(L"Failed to transform heightmap.");
     208        LOGERROR("Failed to transform heightmap.");
    209209        return;
    210210    }
    211211
  • source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp

    diff --git a/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp
    index a366503..368befd 100644
    a b BEGIN_COMMAND(DeleteObjects)  
    930930            entity_id_t ent = sim.AddEntity(oldObjects[i].templateName.FromUTF8(), oldObjects[i].entityID);
    931931            if (ent == INVALID_ENTITY)
    932932            {
    933                 LOGERROR(L"Failed to load entity template '%hs'", oldObjects[i].templateName.c_str());
     933                LOGERROR("Failed to load entity template '%s'", oldObjects[i].templateName.c_str());
    934934            }
    935935            else
    936936            {