0

I just read Joel's blog post on unicode, and found the characters the I want to use to draw boxes in the console in this pdf from the unicode website.

Displaying these characters is simple enough when done directly with cout, i.e. the following does what it is supposed to do..

    cout << u8"\u256C";

However, I am doing some overloading as shown in the following snippets, and I cannot figure out how to get the box characters to display correctly.

I render my data like so ...

// This is the main rendering code
ostream& operator<<(ostream& os, const DataGrid& dg)
{
    for(auto row : dg.data)
    {
        string tmp; //Make empty string
        for(auto col : row)
            tmp.append(   1, dg.gfxString[col]  );
        os << tmp << endl;
    }

    return os;
}

Make it friends with my data model...

class DataGrid
{
public:
    friend ostream& operator<<(ostream& os, const DataGrid& dg);

    //EDIT: rest of class added on request
    DataGrid(Rectangle _rect = Rectangle(Point(0,0), Point(5,5))) :
    rect(_rect),
    data ( vector<vector<p_t>> (_rect.getHeight(), vector<p_t>(_rect.getWidth(), p_t::EMPTY))  ){}

    void addPoint(Point p, p_t type)
    { 
        data[p.getY()][p.getX()] = type;
    }

    void addBorder()
    {
        //Top and bottom
        fill_n(data[0].begin()+1, rect.getWidth()-2, p_t::BORDER_T);
        fill_n(data[rect.getBtm()].begin()+1, rect.getWidth()-2, p_t::BORDER_B);

        //Left and right hand border edges
        for (int nn=1; nn<rect.getHeight()-1; ++nn){
            addPoint(Point(rect.getLeft(), nn), p_t::BORDER_L);
            addPoint(Point(rect.getRight(), nn), p_t::BORDER_R);
        }

        //Corners
        addPoint(rect.getTL(), p_t::BORDER_TL);
        addPoint(rect.getTR(), p_t::BORDER_TR);
        addPoint(rect.getBL(), p_t::BORDER_BL);
        addPoint(rect.getBR(), p_t::BORDER_BR);
    }


private:
    Rectangle rect;
     vector<vector<p_t>> data; //p_t is an enum

    //string gfxString = " abcdefghijklmnop"; //This works fine
    string gfxString = u8"\u256C\u256C\u256C\u256C\u256C\u256C\u256C\u256C"; //Nope     
};

Then attempt to render it with the following, but get gibberish ...

DataGrid p = DataGrid(Rectangle(Point(0,0), 40, 10));
p.addBorder();
cout << p;

If anyone can spot a fix, then that would be great. Thanks for reading.

learnvst
  • 15,455
  • 16
  • 74
  • 121
  • 1
    Instead of "BLAH", please present an actual testcase so we can see what you're doing and therefore what you're doing wrong. – Lightness Races in Orbit Dec 18 '12 at 23:37
  • First stop: [stop using `std::endl`](http://kuhllib.com/2012/01/14/stop-excessive-use-of-stdendl/)! It definitely never ever has any place in an output operator! Won't fix you problem but improve your code still. – Dietmar Kühl Dec 18 '12 at 23:48
  • Added as requested ( ugly as it is ;] ) – learnvst Dec 18 '12 at 23:48
  • It is going through a transform on the way. The chars in the string are being selected depending on the contents of `dg.data`. THis is just a very early play anyway ;) – learnvst Dec 19 '12 at 00:00
  • Despite using wstrings, use `\x` instead of `\u` for numeric escapes and `SetConsoleOutputCP()` if you run this on windows (if so, also take a look at `WideCharToMultiByte()`. http://stackoverflow.com/q/2492077/1175253 – Sam Dec 19 '12 at 00:05
  • @Sam Eeek. Now platform dependencies in the mix. I swear these box characters were so easy to draw in C project I did a looooong time back. Pretty sure I just pasted them into a char array and they drew just fine. – learnvst Dec 19 '12 at 00:11
  • xD. Well, at least I did finally end up with that Windows API stuff while porting a linux project to windows. – Sam Dec 19 '12 at 00:17
  • @Sam .The old favorites ... `+-|` are looking like an increasingly attractive solution to draw boxes! I'm only doing it for (1980s style) eye candy, not foreign char sets! – learnvst Dec 19 '12 at 00:21
  • No offense meant. Its just that all that CP850 stuff and so on caused me some headache, thus using wide chars. Plain C++ brought me portability until the linker finished its job. What I haven't done so far is looking into the windows port of ncurses to draw these boxes without reinventing the wheel. – Sam Dec 19 '12 at 00:48
  • I assume that string is std::string, not a wide string. Each of those box characters occupies three bytes, so you can't just say gfxString[col], even if col were the correct offset. – rici Dec 19 '12 at 01:23

1 Answers1

1

I'd change gfxString to a vector of std::strings (or even a std::array):

// Probably in the final code, these are not all the same value
std::array<std::string, 8> gfxString = {
   { u8"\u256C"
   , u8"\u256C"
   , u8"\u256C"
   , u8"\u256C"
   , u8"\u256C"
   , u8"\u256C"
   , u8"\u256C"
   , u8"\u256C"
   }};

Or even just an array of const char*.

rici
  • 234,347
  • 28
  • 237
  • 341