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")();
}
}
|