Windows console is broken

Sergey Gromov snake.scaly at gmail.com
Thu Jan 31 16:05:42 PST 2008


Sean Kelly Wrote:
>  Perhaps this would be a good third-party project for someone so inclined?

Here's what I came to.

// Codepage-enabled console output functions for D and Phobos
// Copyright 2008 Sergey Gromov

module snake.cout;

import std.conv;
import std.stdio;
import std.format;
import std.c.windows.windows;

version (Windows)
{
    void cwrite(T, R...)(T t, R r)
    {
        foreach (ch; to!(dchar[])(to!(string)(t)))
            cout(ch);
        static if (r.length)
            cwrite(r);
    }

    void cwritef(...)
    {
        doFormat((dchar c){cout(c);}, _arguments, _argptr);
    }

    void cwriteln(T...)(T args)
    {
        cwrite(args, '\n');
    }

    void cwritefln(T...)(T args)
    {
        cwritef(args, '\n');
    }

    void cout(dchar c)
    {
        wchar src = c;
        char[4] buf;   // buffer for a converted char
        auto used = WideCharToMultiByte(GetOEMCP(), 0, &src, 1, buf.ptr, buf.length, "?", null);
        fwrite(buf.ptr, 1, used, stdout);
    }
}
else
{
    alias write cwrite;
    alias writef cwritef;
    alias writeln cwriteln;
    alias writefln cwritefln;
}

import std.file;
import std.contracts;

unittest
{
    auto testFileName = "cout-test-file.tmp";

    {
        FILE* save_stdout = stdout;
        scope(exit) stdout = save_stdout;
    
        stdout = enforce(fopen(testFileName, "wb"));
        scope(failure) remove(testFileName);
        scope(exit) fclose(stdout);
    
        cwriteln("This is %dth day", 14);
        cwritef("This is %dth day", 14);
    }

    scope(exit) remove(testFileName);

    string result = cast(string) read(testFileName);
    assert(result == "This is %dth day14\nThis is 14th day");
}

unittest
{
    auto testFileName = "cout-test-file.tmp";

    {
        FILE* save_stdout = stdout;
        scope(exit) stdout = save_stdout;
    
        stdout = enforce(fopen(testFileName, "wb"));
        scope(failure) remove(testFileName);
        scope(exit) fclose(stdout);
    
        cwrite("Ýòî ðóññêèÿ áóêâû");
    }

    scope(exit) remove(testFileName);

    invariant wchar[] mustBe = "Ýòî ðóññêèÿ áóêâû"w;
    auto required = WideCharToMultiByte(GetOEMCP(), 0, mustBe.ptr, mustBe.length, null, 0, "?", null);
    assert(required);
    auto mustBeConv = new char[required];
    WideCharToMultiByte(GetOEMCP(), 0, mustBe.ptr, mustBe.length, mustBeConv.ptr, mustBeConv.length, "?", null);

    string result = cast(string) read(testFileName);
    assert(result == mustBeConv);
}




More information about the Digitalmars-d mailing list