Skip to content

Instantly share code, notes, and snippets.

@M-griffin
Created March 21, 2015 05:58
Show Gist options
  • Save M-griffin/716f7b5d2c17201cc1a5 to your computer and use it in GitHub Desktop.
Save M-griffin/716f7b5d2c17201cc1a5 to your computer and use it in GitHub Desktop.
Display CP437 Artwork in UTF-8 Console
/*
ANSI Art to UTF-8 Translation
(c) Michael Griffin <mrmisticismo@hotmail.com> 2014-02-05
telnet://htc.zapto.org
Based loosely on CP437.py by Wijnand Modderman-Lenstra.
To Compile GNU GCC
use: g++ -o u8 u8.cpp -std=c++0x
*/
#include <iostream> // cout
#include <clocale> // locale
#include <cwchar> // wchar_t wide characters
#include <string> // string and wstring
#include <fstream> // ifstream file streams.
using namespace std;
wchar_t CP437TABLE[] = {
L'\u0000', L'\u0001', L'\u0002', L'\u0003', L'\u0004', L'\u0005',
L'\u0006', L'\u0007', L'\u0008', L'\u0009', L'\u000A', L'\u000B',
L'\u000C', L'\u000D', L'\u000E', L'\u000F', L'\u0010', L'\u0011',
L'\u0012', L'\u0013', L'\u0014', L'\u0015', L'\u0016', L'\u0017',
L'\u0018', L'\u0019', L'\u001A', L'\u001B', L'\u001C', L'\u001D',
L'\u001E', L'\u001F', L'\u0020', L'\u0021', L'\u0022', L'\u0023',
L'\u0024', L'\u0025', L'\u0026', L'\u0027', L'\u0028', L'\u0029',
L'\u002A', L'\u002B', L'\u002C', L'\u002D', L'\u002E', L'\u002F',
L'\u0030', L'\u0031', L'\u0032', L'\u0033', L'\u0034', L'\u0035',
L'\u0036', L'\u0037', L'\u0038', L'\u0039', L'\u003A', L'\u003B',
L'\u003C', L'\u003D', L'\u003E', L'\u003F', L'\u0040', L'\u0041',
L'\u0042', L'\u0043', L'\u0044', L'\u0045', L'\u0046', L'\u0047',
L'\u0048', L'\u0049', L'\u004A', L'\u004B', L'\u004C', L'\u004D',
L'\u004E', L'\u004F', L'\u0050', L'\u0051', L'\u0052', L'\u0053',
L'\u0054', L'\u0055', L'\u0056', L'\u0057', L'\u0058', L'\u0059',
L'\u005A', L'\u005B', L'\u005C', L'\u005D', L'\u005E', L'\u005F',
L'\u0060', L'\u0061', L'\u0062', L'\u0063', L'\u0064', L'\u0065',
L'\u0066', L'\u0067', L'\u0068', L'\u0069', L'\u006A', L'\u006B',
L'\u006C', L'\u006D', L'\u006E', L'\u006F', L'\u0070', L'\u0071',
L'\u0072', L'\u0073', L'\u0074', L'\u0075', L'\u0076', L'\u0077',
L'\u0078', L'\u0079', L'\u007A', L'\u007B', L'\u007C', L'\u007D',
L'\u007E', L'\u007F', L'\u00C7', L'\u00FC', L'\u00E9', L'\u00E2',
L'\u00E4', L'\u00E0', L'\u00E5', L'\u00E7', L'\u00EA', L'\u00EB',
L'\u00E8', L'\u00EF', L'\u00EE', L'\u00EC', L'\u00C4', L'\u00C5',
L'\u00C9', L'\u00E6', L'\u00C6', L'\u00F4', L'\u00F6', L'\u00F2',
L'\u00FB', L'\u00F9', L'\u00FF', L'\u00D6', L'\u00DC', L'\u00A2',
L'\u00A3', L'\u00A5', L'\u20A7', L'\u0192', L'\u00E1', L'\u00ED',
L'\u00F3', L'\u00FA', L'\u00F1', L'\u00D1', L'\u00AA', L'\u00BA',
L'\u00BF', L'\u2310', L'\u00AC', L'\u00BD', L'\u00BC', L'\u00A1',
L'\u00AB', L'\u00BB', L'\u2591', L'\u2592', L'\u2593', L'\u2502',
L'\u2524', L'\u2561', L'\u2562', L'\u2556', L'\u2555', L'\u2563',
L'\u2551', L'\u2557', L'\u255D', L'\u255C', L'\u255B', L'\u2510',
L'\u2514', L'\u2534', L'\u252C', L'\u251C', L'\u2500', L'\u253C',
L'\u255E', L'\u255F', L'\u255A', L'\u2554', L'\u2569', L'\u2566',
L'\u2560', L'\u2550', L'\u256C', L'\u2567', L'\u2568', L'\u2564',
L'\u2565', L'\u2559', L'\u2558', L'\u2552', L'\u2553', L'\u256B',
L'\u256A', L'\u2518', L'\u250C', L'\u2588', L'\u2584', L'\u258C',
L'\u2590', L'\u2580', L'\u03B1', L'\u00DF', L'\u0393', L'\u03C0',
L'\u03A3', L'\u03C3', L'\u00B5', L'\u03C4', L'\u03A6', L'\u0398',
L'\u03A9', L'\u03B4', L'\u221E', L'\u03C6', L'\u03B5', L'\u2229',
L'\u2261', L'\u00B1', L'\u2265', L'\u2264', L'\u2320', L'\u2321',
L'\u00F7', L'\u2248', L'\u00B0', L'\u2219', L'\u00B7', L'\u221A',
L'\u207F', L'\u00B2', L'\u25A0', L'\u00A0'};
// Used for printing multibyte (UTF-8) Characters
void print_wide(const std::wstring& wstr)
{
std::mbstate_t state = std::mbstate_t();
for(wchar_t wc : wstr)
{
std::string mb(MB_CUR_MAX, '\0');
int ret = std::wcrtomb(&mb[0], wc, &state);
std::cout << mb << flush;
}
}
// TEST - Used for printing multibyte (UTF-8) Characters
// And Also looking at the ASCII value of the multibyte char.
void print_wide_diag(const std::wstring& wstr)
{
std::mbstate_t state = std::mbstate_t();
for(wchar_t wc : wstr)
{
std::string mb(MB_CUR_MAX, '\0');
int ret = std::wcrtomb(&mb[0], wc, &state);
//Static cast to int doesn't give real ascii value on high-ascii charactes!
std::cout << "multibyte char " << mb << " is " << ret << " bytes " <<
std::char_traits<char>().to_int_type(wc) << " value" << endl;
}
}
// Main Translation loop.
void cp437toUTF8(std::string cp347)
{
std::wstring wstr;
int ascii_value = 0;
// Loop and wirte out after translation to UTF-8
for (int i = 0; i < cp347.size(); i++)
{
ascii_value = std::char_traits<char>().to_int_type(cp347[i]);
wstr = CP437TABLE[ascii_value];
print_wide(wstr); // Normal UTF8 Output
//print_wide_diag(wstr); // Output of Ascii Value per Char.
}
}
int main()
{
std::setlocale(LC_ALL, "en_US.utf8");
// UTF-8 narrow multibyte encoding Pre Test.
//std::wstring wstr = L"z\u00df\u6c34\U0001d10b"; // or L"zß???"
//print_wide_diag(wstr);
// Terminal ESC Sequence to set encoding to UTF-8
// Not needed unless ESC(U was called prior for CP437.
// Otherwise we do have to reset back to UTF-8.
write(1, "\x1b" , 1); // Set to UTF8 Char Encoding.
write(1, "%G" , 2); // Set to UTF8 Char Encoding.
std::string myCP437;
// Reading Test ANSI File.
ifstream inStream;
inStream.open( "ret-htc.ans" ); // default test filename.
if (!inStream.is_open()) // Could add command argument for this.
{
cout << "\r\nError no ansi file to translate: " << endl;
return 0;
}
while (!inStream.eof())
{
std::getline(inStream,myCP437,'\n');
}
inStream.close();
// Write out first as normal test just like: cat myFile.txt
cout << myCP437 << flush;
// Run Translation with output to console.
cp437toUTF8(myCP437);
// Reset the Console, also clears everything!?!?!
// Can manually type $ echo -e "\033c" to reset the console back to default.
//write(1, "\x1b" , 1); // Reset console back to Normal when done.
//write(1, "c" , 1); // Reset console back to Normal when done.
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment