| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 | /******************************************************************************* copyright: Copyright (c) 2009 Kris Bell. All rights reserved license: BSD style: $(LICENSE) version: rewritten: Nov 2009 Various low-level console oriented utilities *******************************************************************************/ module tango.core.util.console; private import tango.core.util.string; /******************************************************************************* External functions *******************************************************************************/ version (Windows) { enum {UTF8 = 65001}; private extern (Windows) int GetStdHandle (int); private extern (Windows) int WriteFile (int, in char*, int, int*, void*); private extern (Windows) bool GetConsoleMode (int, int*); private extern (Windows) bool WriteConsoleW (int, in wchar*, int, int*, void*); private extern (Windows) int MultiByteToWideChar (int, int, in char*, int, wchar*, int); } else version (Posix) extern(C) ptrdiff_t write (int, in void*, size_t); /******************************************************************************* Emit an integer to the console *******************************************************************************/ extern(C) void consoleInteger (ulong i) { char[25] tmp = void; consoleString (ulongToUtf8 (tmp, i)); } /******************************************************************************* Emit a utf8 string to the console. Codepages are not supported *******************************************************************************/ extern(C) void consoleString (const(char)[] s) { version (Windows) { int mode, count; auto handle = GetStdHandle (0xfffffff5); if (handle != -1 && GetConsoleMode (handle, &mode)) { wchar[512] utf; while (s.length) { // crop to last complete utf8 sequence auto t = crop (s[0 .. (s.length > utf.length) ? utf.length : s.length]); // convert into output buffer and emit auto i = MultiByteToWideChar (UTF8, 0, s.ptr, t.length, utf.ptr, utf.length); WriteConsoleW (handle, utf.ptr, i, &count, null); // process next chunk s = s [t.length .. $]; } } else // output is probably redirected (we assume utf8 output) WriteFile (handle, s.ptr, s.length, &count, null); } version (Posix) write (2, s.ptr, s.length); } /******************************************************************************* Support for chained console (pseudo formatting) output *******************************************************************************/ struct Console { alias newline opCall; alias emit opCall; /// emit a utf8 string to the console Console emit (const(char)[] s) { consoleString (s); return this; } /// emit an unsigned integer to the console Console emit (ulong i) { consoleInteger (i); return this; } /// emit a newline to the console Console newline () { version (Windows) const eol = "\r\n"; version (Posix) const eol = "\n"; return emit (eol); } } public Console console; version (Windows) { /******************************************************************************* Adjust the content such that no partial encodings exist on the right side of the provided text. Returns a slice of the input *******************************************************************************/ private inout(char)[] crop (inout(char)[] s) { if (s.length) { auto i = s.length - 1; while (i && (s[i] & 0x80)) if ((s[i] & 0xc0) is 0xc0) { // located the first byte of a sequence ubyte b = s[i]; int d = s.length - i; // is it a 3 byte sequence? if (b & 0x20) --d; // or a four byte sequence? if (b & 0x10) --d; // is the sequence complete? if (d is 2) i = s.length; return s [0..i]; } else --i; } return s; } } /******************************************************************************* *******************************************************************************/ debug (console) { void main() { console ("hello world \u263a")(); } } |