19

How we can convert a multi language string or unicode string to upper/lower case in C or C++.

Kyle_the_hacker
  • 1,394
  • 1
  • 11
  • 27
Pankaj
  • 346
  • 1
  • 3
  • 15

9 Answers9

12

If your system is already in UTF-8, by using std::use_facet, you can write:

#include <iostream>
#include <locale.h>

int main() {
    std::locale::global(std::locale(""));  // (*)
    std::wcout.imbue(std::locale());
    auto& f = std::use_facet<std::ctype<wchar_t>>(std::locale());

    std::wstring str = L"Zoë Saldaña played in La maldición del padre Cardona.";

    f.toupper(&str[0], &str[0] + str.size());
    std::wcout << str << std::endl;

    return 0;
}

And you get (http://ideone.com/AFHoHC):

ZOË SALDAÑA PLAYED IN LA MALDICIÓN DEL PADRE CARDONA.

If it don't work you will have to change (*) into std::locale::global(std::locale("en_US.UTF8")); or an UTF-8 locale you actually have on the plateform.

Kyle_the_hacker
  • 1,394
  • 1
  • 11
  • 27
  • This is if your stdlib has locale support, and your UTF-8 locale is named "en_US.UTF8". It's a good C++ solution, but that C++ solution is in itself quite unportable. – rubenvb Aug 01 '13 at 12:33
  • @rubenvb: Yes, of course you have to check if the UTF-8 locale exist. Actually wouldn't `std::locale::global(std::locale(""))` do the job? – Kyle_the_hacker Aug 01 '13 at 13:14
  • @Kyle_the_hacker This code is works if I set std::locale::global(std::locale("en_US.UTF-8")); on Apple LLVM 4.2 Compiler but not on LLVM GCC 4.2 compiler. I think 'auto' is not supported in LLVM GCC. – Pankaj Aug 02 '13 at 07:21
  • 1
    @Pankaj: Wow, that's an old compiler! Try to replace `auto&` with `const std::ctype&`. – Kyle_the_hacker Aug 02 '13 at 09:46
4

I found 2 solution of that problem_

1. setlocale(LC_CTYPE, "en_US.UTF-8"); // the locale will be the UTF-8 enabled English

std::wstring str = L"Zoë Saldaña played in La maldición del padre Cardona.ëèñ";

std::wcout << str << std::endl;

for (wstring::iterator it = str.begin(); it != str.end(); ++it)
    *it = towupper(*it);

std::wcout << "toUpper_onGCC_LLVM_1 :: "<< str << std::endl;

this is working on LLVM GCC 4.2 Compiler.

2. std::locale::global(std::locale("en_US.UTF-8")); // the locale will be the UTF-8 enabled English

std::wcout.imbue(std::locale());
const std::ctype<wchar_t>& f = std::use_facet< std::ctype<wchar_t> >(std::locale());

std::wstring str = L"Chloëè";//"Zoë Saldaña played in La maldición del padre Cardona.";

f.toupper(&str[0], &str[0] + str.size());   

std::wcout << str << std::endl;

This is working in Apple LLVM 4.2.

Both case i ran on Xocde. But I am finding a way to run this code in Eclipse with g++ Compiler.

Pankaj
  • 346
  • 1
  • 3
  • 15
4

If you want a sane and mature solution, look at IBM's ICU. Here's an example:

#include <iostream>
#include <unicode/unistr.h>
#include <string>

int main(){
    icu::UnicodeString us("óóßChloë");
    us.toUpper(); //convert to uppercase in-place
    std::string s;
    us.toUTF8String(s);
    std::cout<<"Upper: "<<s<<"\n";

    us.toLower(); //convert to lowercase in-place
    s.clear();
    us.toUTF8String(s);
    std::cout<<"Lower: "<<s<<"\n";
    return 0;
}

Output:

Upper: ÓÓSSCHLOË
Lower: óósschloë

Note: In the later step SS isn't being treated as capital of German ß

Jahid
  • 21,542
  • 10
  • 90
  • 108
  • That does look like a nice library. However, it clocks in at almost 30MB. My entire app is 21MB. – Pierre Dec 20 '17 at 12:54
3

With quite a lot of difficulty if you're going to do it right.

The usual use-case for this is for comparison purposes, but the problem is more general than that.

There is a fairly detailed paper from C++ Report circa 2000 from Matt Austern here (PDF)

SteveLove
  • 3,137
  • 15
  • 17
  • 3
    Uppercasing for case-insensitive comparison is just the wrong approach. The right approach is to get rid *only* of the case differences (there's an operation known as "casefolding" that can be used for this) and then compare. Uppercasing does not get rid of *only* the case differences. – R. Martinho Fernandes Aug 01 '13 at 10:54
  • I'd even disagree with that statement. You want to get rid of all differences that are irrelevant to the comparison. Sure, `Æ = æ`, but that probably is equal to AE, ae and AE as well. – MSalters Aug 01 '13 at 11:35
  • 1
    This is not an answer – Purefan Feb 15 '16 at 22:21
2

You can iterate through a wstring and use towupper / towlower

for (wstring::iterator it = a.begin(); it != a.end(); ++it)
        *it = towupper(*it);
mewa
  • 1,532
  • 1
  • 12
  • 20
2

Set the locale first, example :

setlocale(LC_ALL, "German")); /*This won't work as per comments below */

setlocale(LC_ALL, "English"));

setlocale( LC_MONETARY, "French" );

setlocale( LC_ALL, "" ); //default locale 

Then use

std::use_facet std::locale as follows:-

typedef std::string::value_type char_t;
char_t upcase( char_t ch )
{
 return std::use_facet< std::ctype< char_t > >( std::locale() ).toupper( ch );
}

std::string toupper( const std::string &src )
{
 std::string result;
 std::transform( src.begin(), src.end(), std::back_inserter( result ), upcase );
 return result;
}

const std::string src  = "Hello World!";
std::cout << toupper( src );
P0W
  • 46,614
  • 9
  • 72
  • 119
  • 5
    Funny that you mention the German locale, and then proceed to use a method that won't work for proper German uppercasing, because it uses a 1-to-1 map (`transform`), but uppercasing ß results in two characters. – R. Martinho Fernandes Aug 01 '13 at 11:19
  • Actually I want to convert french text so I am using setlocale( LC_MONETARY, "French" ); But getting CHLOë as output when I converting chloë to upper case. – Pankaj Aug 01 '13 at 11:24
  • 3
    @Pankaj please, please, please, stop programming by accident. What do you think `setlocale(LC_MONETARY, "French")` does? Do you think uppercasing "Chloë" has any monetary concerns in it? If your problem is finding the documentation, it's here http://en.cppreference.com/w/cpp/locale/setlocale and here http://en.cppreference.com/w/cpp/locale/LC_categories – R. Martinho Fernandes Aug 01 '13 at 11:42
  • 3
    @Pankaj what you exactly want from "Chloë ? please leave her alone ;) – P0W Aug 01 '13 at 11:54
  • @P0W Cholë should be come like CHOLË after changing to uppercase. – Pankaj Aug 01 '13 at 12:00
2

In Windows, consider CharUpperBuffW and CharLowerBuffW for mixed-language applications where locale is unknown. These functions handle diacritics where toupper() does not.

Pierre
  • 4,114
  • 2
  • 34
  • 39
  • 1
    There are only downsides to using platform specific functions to manipulate text -- it binds your code to that platform and doesn't do you any good. Considering that there are many good text manipulation libraries that are not platform specific, you're just hurting yourself by doing this. – Clearer Dec 19 '17 at 08:13
  • 1
    It is naïve to assume that it is beneficial or profitable to run all applications on all platforms. – Pierre Dec 20 '17 at 12:57
  • 2
    It's naive to assume that your program will never run on any other platform than the one you're developing on right now. It's downright stupid to tie yourself to a platform by using an inferior API, when a superior non-platform specific API exists. – Clearer Jan 02 '18 at 13:53
0

For C I would use toupper after adjusting the C locale in the current thread.

setlocale(LC_CTYPE, "en_US.UTF8");

For C++ I would use the toupper method of std::ctype<char>:

std::locale loc;

auto& f = std::use_facet<std::ctype<char>>(loc);

char str[80] = "Hello World";

f.toupper(str, str+strlen(str));
David G
  • 94,763
  • 41
  • 167
  • 253
  • my code is:- setlocale(LC_CTYPE, "en_US.UTF8"); std::locale loc; auto& f = std::use_facet>(loc); char str[80] = "pièces"; f.toupper(str, str+strlen(str)); cout< – Pankaj Aug 01 '13 at 11:05
  • 1
    @Pankaj that's because the en_US locale doesn't have uppercase forms for anything that isn't in a-z. – R. Martinho Fernandes Aug 01 '13 at 11:20
  • @R.MartinhoFernandes So what i have to do for that,actually I am very new to CPP and I even dont know hello world programme properly in CPP. some how I managing that.. – Pankaj Aug 01 '13 at 11:28
  • 1
    @Pankaj: Use the appropriate locale. For instance, in Turkish the uppercase of i is İ (keeping the dot above). The Turkish locale knows this, the US knows that uppercase i is I without a dot. Both are right, of course. – MSalters Aug 01 '13 at 11:39
  • @Kyle_the_hacker oh, I missed how Pankaj was using cout to print stuff. Good point. – R. Martinho Fernandes Aug 01 '13 at 12:11
  • @MSalters so what is setlocale(LC_CTYPE, "en_US.UTF8"); locale of Turkish then please? – gokturk Dec 26 '15 at 10:47
  • @gokturk: Probably `"tr_TR.UTF8"`. – MSalters Dec 27 '15 at 15:09
0

Based on Kyle_the_hacker's -----> answer with my extras.

Ubuntu

In terminal List all locales
locale -a

Install all locales
sudo apt-get install -y locales locales-all

Compile main.cpp
$ g++ main.cpp

Run compiled program
$ ./a.out

Results

Zoë Saldaña played in La maldición del padre Cardona. ëèñ αω óóChloë
Zoë Saldaña played in La maldición del padre Cardona. ëèñ αω óóChloë
ZOË SALDAÑA PLAYED IN LA MALDICIÓN DEL PADRE CARDONA. ËÈÑ ΑΩ ÓÓCHLOË
ZOË SALDAÑA PLAYED IN LA MALDICIÓN DEL PADRE CARDONA. ËÈÑ ΑΩ ÓÓCHLOË
zoë saldaña played in la maldición del padre cardona. ëèñ αω óóchloë
zoë saldaña played in la maldición del padre cardona. ëèñ αω óóchloë

Ubuntu Linux - WSL from VSCODE

Ubuntu Linux - WSL

Windows

In cmd run VCVARS developer tools
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"

Compile main.cpp
> cl /EHa main.cpp /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /std:c++17 /DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /MTd

Compilador de optimización de C/C++ de Microsoft (R) versión 19.27.29111 para x64
(C) Microsoft Corporation. Todos los derechos reservados.

main.cpp
Microsoft (R) Incremental Linker Version 14.27.29111.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:main.exe
main.obj
kernel32.lib
user32.lib
gdi32.lib
winspool.lib
comdlg32.lib
advapi32.lib
shell32.lib
ole32.lib
oleaut32.lib
uuid.lib
odbc32.lib
odbccp32.lib

Run main.exe
>main.exe

Results

Zoë Saldaña played in La maldición del padre Cardona. ëèñ αω óóChloë
Zoë Saldaña played in La maldición del padre Cardona. ëèñ αω óóChloë
ZOË SALDAÑA PLAYED IN LA MALDICIÓN DEL PADRE CARDONA. ËÈÑ ΑΩ ÓÓCHLOË
ZOË SALDAÑA PLAYED IN LA MALDICIÓN DEL PADRE CARDONA. ËÈÑ ΑΩ ÓÓCHLOË
zoë saldaña played in la maldición del padre cardona. ëèñ αω óóchloë
zoë saldaña played in la maldición del padre cardona. ëèñ αω óóchloë

Windows

The code - main.cpp

This code was only tested on Windows x64 and Ubuntu Linux x64.

/*
 * Filename: c:\Users\x\Cpp\main.cpp
 * Path: c:\Users\x\Cpp
 * Filename: /home/x/Cpp/main.cpp
 * Path: /home/x/Cpp
 * Created Date: Saturday, October 17th 2020, 10:43:31 pm
 * Author: Joma
 *
 * No Copyright 2020
 */


#include <iostream>
#include <set>
#include <string>
#include <locale>

// WINDOWS
#if (_WIN32)
#include <Windows.h>
#include <conio.h>
#define WINDOWS_PLATFORM 1
#define DLLCALL STDCALL
#define DLLIMPORT _declspec(dllimport)
#define DLLEXPORT _declspec(dllexport)
#define DLLPRIVATE
#define NOMINMAX

//EMSCRIPTEN
#elif defined(__EMSCRIPTEN__)
#include <emscripten/emscripten.h>
#include <emscripten/bind.h>
#include <unistd.h>
#include <termios.h>
#define EMSCRIPTEN_PLATFORM 1
#define DLLCALL
#define DLLIMPORT
#define DLLEXPORT __attribute__((visibility("default")))
#define DLLPRIVATE __attribute__((visibility("hidden")))

// LINUX - Ubuntu, Fedora, , Centos, Debian, RedHat
#elif (__LINUX__ || __gnu_linux__ || __linux__ || __linux || linux)
#define LINUX_PLATFORM 1
#include <unistd.h>
#include <termios.h>
#define DLLCALL CDECL
#define DLLIMPORT
#define DLLEXPORT __attribute__((visibility("default")))
#define DLLPRIVATE __attribute__((visibility("hidden")))
#define CoTaskMemAlloc(p) malloc(p)
#define CoTaskMemFree(p) free(p)

//ANDROID
#elif (__ANDROID__ || ANDROID)
#define ANDROID_PLATFORM 1
#define DLLCALL
#define DLLIMPORT
#define DLLEXPORT __attribute__((visibility("default")))
#define DLLPRIVATE __attribute__((visibility("hidden")))

//MACOS
#elif defined(__APPLE__)
#include <unistd.h>
#include <termios.h>
#define DLLCALL
#define DLLIMPORT
#define DLLEXPORT __attribute__((visibility("default")))
#define DLLPRIVATE __attribute__((visibility("hidden")))
#include "TargetConditionals.h"
#if TARGET_OS_IPHONE && TARGET_IPHONE_SIMULATOR
#define IOS_SIMULATOR_PLATFORM 1
#elif TARGET_OS_IPHONE
#define IOS_PLATFORM 1
#elif TARGET_OS_MAC
#define MACOS_PLATFORM 1
#else

#endif

#endif



typedef std::string String;
typedef std::wstring WString;

#define EMPTY_STRING u8""s
#define EMPTY_WSTRING L""s

using namespace std::literals::string_literals;

class Strings
{
public:
    static String WideStringToString(const WString& wstr)
    {
        if (wstr.empty())
        {
            return String();
        }
        size_t pos;
        size_t begin = 0;
        String ret;

#if WINDOWS_PLATFORM
        int size;
        pos = wstr.find(static_cast<wchar_t>(0), begin);
        while (pos != WString::npos && begin < wstr.length())
        {
            WString segment = WString(&wstr[begin], pos - begin);
            size = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, &segment[0], segment.size(), NULL, 0, NULL, NULL);
            String converted = String(size, 0);
            WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, &segment[0], segment.size(), &converted[0], converted.size(), NULL, NULL);
            ret.append(converted);
            ret.append({ 0 });
            begin = pos + 1;
            pos = wstr.find(static_cast<wchar_t>(0), begin);
        }
        if (begin <= wstr.length())
        {
            WString segment = WString(&wstr[begin], wstr.length() - begin);
            size = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, &segment[0], segment.size(), NULL, 0, NULL, NULL);
            String converted = String(size, 0);
            WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, &segment[0], segment.size(), &converted[0], converted.size(), NULL, NULL);
            ret.append(converted);
        }
#elif LINUX_PLATFORM || MACOS_PLATFORM || EMSCRIPTEN_PLATFORM
        size_t size;
        pos = wstr.find(static_cast<wchar_t>(0), begin);
        while (pos != WString::npos && begin < wstr.length())
        {
            WString segment = WString(&wstr[begin], pos - begin);
            size = wcstombs(nullptr, segment.c_str(), 0);
            String converted = String(size, 0);
            wcstombs(&converted[0], segment.c_str(), converted.size());
            ret.append(converted);
            ret.append({ 0 });
            begin = pos + 1;
            pos = wstr.find(static_cast<wchar_t>(0), begin);
        }
        if (begin <= wstr.length())
        {
            WString segment = WString(&wstr[begin], wstr.length() - begin);
            size = wcstombs(nullptr, segment.c_str(), 0);
            String converted = String(size, 0);
            wcstombs(&converted[0], segment.c_str(), converted.size());
            ret.append(converted);
        }
#else
        static_assert(false, "Unknown Platform");
#endif
        return ret;
    }

    static WString StringToWideString(const String& str)
    {
        if (str.empty())
        {
            return WString();
        }

        size_t pos;
        size_t begin = 0;
        WString ret;
#ifdef WINDOWS_PLATFORM
        int size = 0;
        pos = str.find(static_cast<char>(0), begin);
        while (pos != std::string::npos) {
            std::string segment = std::string(&str[begin], pos - begin);
            std::wstring converted = std::wstring(segment.size() + 1, 0);
            size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, &segment[0], segment.size(), &converted[0], converted.length());
            converted.resize(size);
            ret.append(converted);
            ret.append({ 0 });
            begin = pos + 1;
            pos = str.find(static_cast<char>(0), begin);
        }
        if (begin < str.length()) {
            std::string segment = std::string(&str[begin], str.length() - begin);
            std::wstring converted = std::wstring(segment.size() + 1, 0);
            size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, segment.c_str(), segment.size(), &converted[0], converted.length());
            converted.resize(size);
            ret.append(converted);
        }

#elif LINUX_PLATFORM || MACOS_PLATFORM || EMSCRIPTEN_PLATFORM
        size_t size;
        pos = str.find(static_cast<char>(0), begin);
        while (pos != String::npos)
        {
            String segment = String(&str[begin], pos - begin);
            WString converted = WString(segment.size(), 0);
            size = mbstowcs(&converted[0], &segment[0], converted.size());
            converted.resize(size);
            ret.append(converted);
            ret.append({ 0 });
            begin = pos + 1;
            pos = str.find(static_cast<char>(0), begin);
        }
        if (begin < str.length())
        {
            String segment = String(&str[begin], str.length() - begin);
            WString converted = WString(segment.size(), 0);
            size = mbstowcs(&converted[0], &segment[0], converted.size());
            converted.resize(size);
            ret.append(converted);
        }
#else
        static_assert(false, "Unknown Platform");
#endif
        return ret;
    }


    static WString ToUpper(const WString& data)
    {
        WString result = data;
        auto& f = std::use_facet<std::ctype<wchar_t>>(std::locale());

        f.toupper(&result[0], &result[0] + result.size());
        return result;
    }

    static String  ToUpper(const String& data)
    {
        return WideStringToString(ToUpper(StringToWideString(data)));
    }

    static WString ToLower(const WString& data)
    {
        WString result = data;
        auto& f = std::use_facet<std::ctype<wchar_t>>(std::locale());
        f.tolower(&result[0], &result[0] + result.size());
        return result;
    }

    static String ToLower(const String& data)
    {
        return WideStringToString(ToLower(StringToWideString(data)));
    }

};

enum class ConsoleTextStyle
{
    DEFAULT = 0,
    BOLD = 1,
    FAINT = 2,
    ITALIC = 3,
    UNDERLINE = 4,
    SLOW_BLINK = 5,
    RAPID_BLINK = 6,
    REVERSE = 7,
};

enum class ConsoleForeground
{
    DEFAULT = 39,
    BLACK = 30,
    DARK_RED = 31,
    DARK_GREEN = 32,
    DARK_YELLOW = 33,
    DARK_BLUE = 34,
    DARK_MAGENTA = 35,
    DARK_CYAN = 36,
    GRAY = 37,
    DARK_GRAY = 90,
    RED = 91,
    GREEN = 92,
    YELLOW = 93,
    BLUE = 94,
    MAGENTA = 95,
    CYAN = 96,
    WHITE = 97
};

enum class ConsoleBackground
{
    DEFAULT = 49,
    BLACK = 40,
    DARK_RED = 41,
    DARK_GREEN = 42,
    DARK_YELLOW = 43,
    DARK_BLUE = 44,
    DARK_MAGENTA = 45,
    DARK_CYAN = 46,
    GRAY = 47,
    DARK_GRAY = 100,
    RED = 101,
    GREEN = 102,
    YELLOW = 103,
    BLUE = 104,
    MAGENTA = 105,
    CYAN = 106,
    WHITE = 107
};

class Console
{
private:
    static void EnableVirtualTermimalProcessing()
    {
#if defined WINDOWS_PLATFORM
        HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
        DWORD dwMode = 0;
        GetConsoleMode(hOut, &dwMode);
        if (!(dwMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING))
        {
            dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
            SetConsoleMode(hOut, dwMode);
        }
#endif
    }

    static void ResetTerminalFormat()
    {
        std::cout << u8"\033[0m";
    }

    static void SetVirtualTerminalFormat(ConsoleForeground foreground, ConsoleBackground background, std::set<ConsoleTextStyle> styles)
    {
        String format = u8"\033[";
        format.append(std::to_string(static_cast<int>(foreground)));
        format.append(u8";");
        format.append(std::to_string(static_cast<int>(background)));
        if (styles.size() > 0)
        {
            for (auto it = styles.begin(); it != styles.end(); ++it)
            {
                format.append(u8";");
                format.append(std::to_string(static_cast<int>(*it)));
            }
        }
        format.append(u8"m");
        std::cout << format;
    }
public:
    static void Clear()
    {

#ifdef WINDOWS_PLATFORM
        std::system(u8"cls");
#elif LINUX_PLATFORM || defined MACOS_PLATFORM
        std::system(u8"clear");
#elif EMSCRIPTEN_PLATFORM
        emscripten::val::global()["console"].call<void>(u8"clear");
#else
        static_assert(false, "Unknown Platform");
#endif
    }

    static void Write(const String& s, ConsoleForeground foreground = ConsoleForeground::DEFAULT, ConsoleBackground background = ConsoleBackground::DEFAULT, std::set<ConsoleTextStyle> styles = {})
    {
#ifndef EMSCRIPTEN_PLATFORM
        EnableVirtualTermimalProcessing();
        SetVirtualTerminalFormat(foreground, background, styles);
#endif
        String str = s;
#ifdef WINDOWS_PLATFORM
        WString unicode = Strings::StringToWideString(str);
        WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), unicode.c_str(), static_cast<DWORD>(unicode.length()), nullptr, nullptr);
#elif defined LINUX_PLATFORM || defined MACOS_PLATFORM || EMSCRIPTEN_PLATFORM
        std::cout << str;
#else
        static_assert(false, "Unknown Platform");
#endif

#ifndef EMSCRIPTEN_PLATFORM
        ResetTerminalFormat();
#endif
    }

    static void WriteLine(const String& s, ConsoleForeground foreground = ConsoleForeground::DEFAULT, ConsoleBackground background = ConsoleBackground::DEFAULT, std::set<ConsoleTextStyle> styles = {})
    {
        Write(s, foreground, background, styles);
        std::cout << std::endl;
    }

    static void Write(const WString& s, ConsoleForeground foreground = ConsoleForeground::DEFAULT, ConsoleBackground background = ConsoleBackground::DEFAULT, std::set<ConsoleTextStyle> styles = {})
    {
#ifndef EMSCRIPTEN_PLATFORM
        EnableVirtualTermimalProcessing();
        SetVirtualTerminalFormat(foreground, background, styles);
#endif
        WString str = s;

#ifdef WINDOWS_PLATFORM
        WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), str.c_str(), static_cast<DWORD>(str.length()), nullptr, nullptr);
#elif LINUX_PLATFORM || MACOS_PLATFORM || EMSCRIPTEN_PLATFORM
        std::cout << Strings::WideStringToString(str);
#else
        static_assert(false, "Unknown Platform");
#endif

#ifndef EMSCRIPTEN_PLATFORM
        ResetTerminalFormat();
#endif
    }

    static void WriteLine(const WString& s, ConsoleForeground foreground = ConsoleForeground::DEFAULT, ConsoleBackground background = ConsoleBackground::DEFAULT, std::set<ConsoleTextStyle> styles = {})
    {
        Write(s, foreground, background, styles);
        std::cout << std::endl;
    }

    static void WriteLine()
    {
        std::cout << std::endl;
    }

    static void Pause()
    {
        char c;
        do
        {
            c = getchar();
            std::cout << "Press Key " << std::endl;
        } while (c != 64);
        std::cout << "KeyPressed" << std::endl;
    }

    static int PauseAny(bool printWhenPressed = false, ConsoleForeground foreground = ConsoleForeground::DEFAULT, ConsoleBackground background = ConsoleBackground::DEFAULT, std::set<ConsoleTextStyle> styles = {})
    {
        int ch;
#ifdef WINDOWS_PLATFORM
        ch = _getch();
#elif LINUX_PLATFORM || MACOS_PLATFORM || EMSCRIPTEN_PLATFORM
        struct termios oldt, newt;
        tcgetattr(STDIN_FILENO, &oldt);
        newt = oldt;
        newt.c_lflag &= ~(ICANON | ECHO);
        tcsetattr(STDIN_FILENO, TCSANOW, &newt);
        ch = getchar();
        tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
#else
        static_assert(false, "Unknown Platform");
#endif
        if (printWhenPressed)
        {
            Console::Write(String(1, ch), foreground, background, styles);
        }
        return ch;
    }
};



int main()
{
    std::locale::global(std::locale(u8"en_US.UTF-8"));
    String dataStr = u8"Zoë Saldaña played in La maldición del padre Cardona. ëèñ αω óóChloë";
    WString dataWStr = L"Zoë Saldaña played in La maldición del padre Cardona. ëèñ αω óóChloë";
    std::string locale = u8"";
    //std::string locale = u8"de_DE.UTF-8";
    //std::string locale = u8"en_US.UTF-8";
    Console::WriteLine(dataStr);
    Console::WriteLine(dataWStr);
    dataStr = Strings::ToUpper(dataStr);
    dataWStr = Strings::ToUpper(dataWStr);
    Console::WriteLine(dataStr);
    Console::WriteLine(dataWStr);
    dataStr = Strings::ToLower(dataStr);
    dataWStr = Strings::ToLower(dataWStr);
    Console::WriteLine(dataStr);
    Console::WriteLine(dataWStr);
    
    
    Console::WriteLine(u8"Press any key to exit"s, ConsoleForeground::DARK_GRAY);
    Console::PauseAny();

    return 0;
}

Joma
  • 3,520
  • 1
  • 29
  • 32