Console revamp - linux part.
parent
b41ab40bb6
commit
f8cdd95b09
@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
https://github.com/peterix/dfhack
|
||||||
|
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any
|
||||||
|
damages arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any
|
||||||
|
purpose, including commercial applications, and to alter it and
|
||||||
|
redistribute it freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must
|
||||||
|
not claim that you wrote the original software. If you use this
|
||||||
|
software in a product, an acknowledgment in the product documentation
|
||||||
|
would be appreciated but is not required.
|
||||||
|
|
||||||
|
2. Altered source versions must be plainly marked as such, and
|
||||||
|
must not be misrepresented as being the original software.
|
||||||
|
|
||||||
|
3. This notice may not be removed or altered from any source
|
||||||
|
distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dfhack/Console.h"
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <sstream>
|
||||||
|
using namespace DFHack;
|
||||||
|
|
||||||
|
duthomhas::stdiostream dfout;
|
||||||
|
FILE * dfout_C = 0;
|
||||||
|
duthomhas::stdiobuf * stream_o = 0;
|
||||||
|
|
||||||
|
// FIXME: prime candidate for being a singleton...
|
||||||
|
Console::Console()
|
||||||
|
{
|
||||||
|
// make our own weird streams so our IO isn't redirected
|
||||||
|
dfout_C = fopen("/dev/tty", "w");
|
||||||
|
stream_o = new duthomhas::stdiobuf(dfout_C);
|
||||||
|
dfout.rdbuf(stream_o);
|
||||||
|
std::cin.tie(&dfout);
|
||||||
|
clear();
|
||||||
|
// result is a terminal controlled by the parasitic code!
|
||||||
|
}
|
||||||
|
Console::~Console()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
void Console::clear()
|
||||||
|
{
|
||||||
|
dfout << "\033c";
|
||||||
|
dfout << "\033[3J\033[H";
|
||||||
|
}
|
||||||
|
void Console::gotoxy(int x, int y)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "\033[" << y << ";" << x << "H";
|
||||||
|
dfout << oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * ANSI_CLS = "\033[2J";
|
||||||
|
const char * ANSI_BLACK = "\033[22;30m";
|
||||||
|
const char * ANSI_RED = "\033[22;31m";
|
||||||
|
const char * ANSI_GREEN = "\033[22;32m";
|
||||||
|
const char * ANSI_BROWN = "\033[22;33m";
|
||||||
|
const char * ANSI_BLUE = "\033[22;34m";
|
||||||
|
const char * ANSI_MAGENTA = "\033[22;35m";
|
||||||
|
const char * ANSI_CYAN = "\033[22;36m";
|
||||||
|
const char * ANSI_GREY = "\033[22;37m";
|
||||||
|
const char * ANSI_DARKGREY = "\033[01;30m";
|
||||||
|
const char * ANSI_LIGHTRED = "\033[01;31m";
|
||||||
|
const char * ANSI_LIGHTGREEN = "\033[01;32m";
|
||||||
|
const char * ANSI_YELLOW = "\033[01;33m";
|
||||||
|
const char * ANSI_LIGHTBLUE = "\033[01;34m";
|
||||||
|
const char * ANSI_LIGHTMAGENTA = "\033[01;35m";
|
||||||
|
const char * ANSI_LIGHTCYAN = "\033[01;36m";
|
||||||
|
const char * ANSI_WHITE = "\033[01;37m";
|
||||||
|
|
||||||
|
const char * getANSIColor(const int c)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 0 : return ANSI_BLACK;
|
||||||
|
case 1 : return ANSI_BLUE; // non-ANSI
|
||||||
|
case 2 : return ANSI_GREEN;
|
||||||
|
case 3 : return ANSI_CYAN; // non-ANSI
|
||||||
|
case 4 : return ANSI_RED; // non-ANSI
|
||||||
|
case 5 : return ANSI_MAGENTA;
|
||||||
|
case 6 : return ANSI_BROWN;
|
||||||
|
case 7 : return ANSI_GREY;
|
||||||
|
case 8 : return ANSI_DARKGREY;
|
||||||
|
case 9 : return ANSI_LIGHTBLUE; // non-ANSI
|
||||||
|
case 10: return ANSI_LIGHTGREEN;
|
||||||
|
case 11: return ANSI_LIGHTCYAN; // non-ANSI;
|
||||||
|
case 12: return ANSI_LIGHTRED; // non-ANSI;
|
||||||
|
case 13: return ANSI_LIGHTMAGENTA;
|
||||||
|
case 14: return ANSI_YELLOW; // non-ANSI
|
||||||
|
case 15: return ANSI_WHITE;
|
||||||
|
default: return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Console::color(int index)
|
||||||
|
{
|
||||||
|
dfout << getANSIColor(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Console::cursor(bool enable)
|
||||||
|
{
|
||||||
|
if(enable)
|
||||||
|
{
|
||||||
|
dfout <<"\033[?25h";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dfout <<"\033[?25l";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
https://github.com/peterix/dfhack
|
||||||
|
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any
|
||||||
|
damages arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any
|
||||||
|
purpose, including commercial applications, and to alter it and
|
||||||
|
redistribute it freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must
|
||||||
|
not claim that you wrote the original software. If you use this
|
||||||
|
software in a product, an acknowledgment in the product documentation
|
||||||
|
would be appreciated but is not required.
|
||||||
|
|
||||||
|
2. Altered source versions must be plainly marked as such, and
|
||||||
|
must not be misrepresented as being the original software.
|
||||||
|
|
||||||
|
3. This notice may not be removed or altered from any source
|
||||||
|
distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "dfhack/Pragma.h"
|
||||||
|
#include "dfhack/Export.h"
|
||||||
|
#include "dfhack/Core.h"
|
||||||
|
#include "dfhack/extra/stdiostream.h"
|
||||||
|
|
||||||
|
extern DFHACK_EXPORT duthomhas::stdiostream dfout;
|
||||||
|
extern DFHACK_EXPORT FILE * dfout_C;
|
||||||
|
|
||||||
|
namespace DFHack
|
||||||
|
{
|
||||||
|
class DFHACK_EXPORT Console
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Console();
|
||||||
|
~Console();
|
||||||
|
void clear();
|
||||||
|
void gotoxy(int x, int y);
|
||||||
|
void color(int index);
|
||||||
|
void cursor(bool enable = true);
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,302 @@
|
|||||||
|
// stdiostream.hpp
|
||||||
|
//
|
||||||
|
// Copyright (c) 2010 Michael Thomas Greer
|
||||||
|
// Distributed under the Boost Software License, Version 1.0
|
||||||
|
// (See http://www.boost.org/LICENSE_1_0.txt )
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef DUTHOMHAS_STDIOSTREAM_HPP
|
||||||
|
#define DUTHOMHAS_STDIOSTREAM_HPP
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <iostream>
|
||||||
|
#include <streambuf>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace duthomhas
|
||||||
|
{
|
||||||
|
|
||||||
|
/* /////////////////////////////////////////////////////////////////////////
|
||||||
|
basic_stdiobuf
|
||||||
|
///////////////////////////////////////////////////////////////////////// */
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename CharType,
|
||||||
|
typename CharTraits = std::char_traits <CharType>
|
||||||
|
>
|
||||||
|
class basic_stdiobuf: public std::basic_streambuf <CharType, CharTraits>
|
||||||
|
{
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
public:
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
typedef CharType char_type;
|
||||||
|
typedef CharTraits traits_type;
|
||||||
|
typedef typename traits_type::int_type int_type;
|
||||||
|
typedef typename traits_type::pos_type pos_type;
|
||||||
|
typedef typename traits_type::off_type off_type;
|
||||||
|
|
||||||
|
typedef basic_stdiobuf <char_type, traits_type> this_type;
|
||||||
|
|
||||||
|
//......................................................................
|
||||||
|
basic_stdiobuf( FILE* fp = NULL ):
|
||||||
|
fp( fp )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
//......................................................................
|
||||||
|
//BUG 1: Hey! I never get called! (How is that?)
|
||||||
|
~basic_stdiobuf()
|
||||||
|
{
|
||||||
|
this->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
//......................................................................
|
||||||
|
bool is_open() const throw()
|
||||||
|
{
|
||||||
|
return fp != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//......................................................................
|
||||||
|
this_type* open( const char* filename, std::ios_base::openmode mode )
|
||||||
|
{
|
||||||
|
if (is_open()) return NULL;
|
||||||
|
|
||||||
|
// Figure out the open mode flags . . . . . . . . . . . . . . . . . .
|
||||||
|
std::string fmode;
|
||||||
|
|
||||||
|
bool is_ate = mode & std::ios_base::ate;
|
||||||
|
bool is_bin = mode & std::ios_base::binary;
|
||||||
|
mode &= ~(std::ios_base::ate | std::ios_base::binary);
|
||||||
|
|
||||||
|
#define _(flag) std::ios_base::flag
|
||||||
|
if (mode == ( _(in) )) fmode = "r";
|
||||||
|
else if (mode == ( _(out) & _(trunc))) fmode = "w";
|
||||||
|
else if (mode == (_(app) & _(out) )) fmode = "a";
|
||||||
|
else if (mode == ( _(in) & _(out) )) fmode = "r+";
|
||||||
|
else if (mode == ( _(in) & _(out) & _(trunc))) fmode = "w+";
|
||||||
|
else if (mode == (_(app) & _(in) & _(out) )) fmode = "a+";
|
||||||
|
// I would prefer to throw an exception here,
|
||||||
|
// but the standard only wants a NULL result.
|
||||||
|
else return NULL;
|
||||||
|
#undef _
|
||||||
|
if (is_bin) fmode.insert( 1, 1, 'b' );
|
||||||
|
|
||||||
|
// Try opening the file . . . . . . . . . . . . . . . . . . . . . . .
|
||||||
|
fp = std::fopen( filename, fmode.c_str() );
|
||||||
|
if (!fp) return NULL;
|
||||||
|
|
||||||
|
// Reposition to EOF if wanted . . . . . . . . . . . . . . . . . . . .
|
||||||
|
if (is_ate) std::fseek( fp, 0, SEEK_END );
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//......................................................................
|
||||||
|
this_type* close()
|
||||||
|
{
|
||||||
|
if (fp)
|
||||||
|
{
|
||||||
|
std::fclose( fp );
|
||||||
|
fp = NULL;
|
||||||
|
}
|
||||||
|
pushbacks.clear();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//......................................................................
|
||||||
|
FILE* stdiofile() const
|
||||||
|
{
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
protected:
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//......................................................................
|
||||||
|
// Get the CURRENT character without advancing the file pointer
|
||||||
|
virtual int_type underflow()
|
||||||
|
{
|
||||||
|
// Return anything previously pushed-back
|
||||||
|
if (pushbacks.size())
|
||||||
|
return pushbacks.back();
|
||||||
|
|
||||||
|
// Else do the right thing
|
||||||
|
fpos_t pos;
|
||||||
|
if (std::fgetpos( fp, &pos ) != 0)
|
||||||
|
return traits_type::eof();
|
||||||
|
|
||||||
|
int c = std::fgetc( fp );
|
||||||
|
std::fsetpos( fp, &pos );
|
||||||
|
|
||||||
|
return maybe_eof( c );
|
||||||
|
}
|
||||||
|
|
||||||
|
//......................................................................
|
||||||
|
// Get the CURRENT character AND advance the file pointer
|
||||||
|
virtual int_type uflow()
|
||||||
|
{
|
||||||
|
// Return anything previously pushed-back
|
||||||
|
if (pushbacks.size())
|
||||||
|
{
|
||||||
|
int_type c = pushbacks.back();
|
||||||
|
pushbacks.pop_back();
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Else do the right thing
|
||||||
|
return maybe_eof( std::fgetc( fp ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
//......................................................................
|
||||||
|
virtual int_type pbackfail( int_type c = traits_type::eof() )
|
||||||
|
{
|
||||||
|
if (!is_open())
|
||||||
|
return traits_type::eof();
|
||||||
|
|
||||||
|
// If the argument c is EOF and the file pointer is not at the
|
||||||
|
// beginning of the character sequence, it is decremented by one.
|
||||||
|
if (traits_type::eq_int_type( c, traits_type::eof() ))
|
||||||
|
{
|
||||||
|
pushbacks.clear();
|
||||||
|
return std::fseek( fp, -1L, SEEK_CUR )
|
||||||
|
? traits_type::eof()
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, make the argument the next value to be returned by
|
||||||
|
// underflow() or uflow()
|
||||||
|
pushbacks.push_back( c );
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
//......................................................................
|
||||||
|
virtual int_type overflow( int_type c = traits_type::eof() )
|
||||||
|
{
|
||||||
|
pushbacks.clear();
|
||||||
|
|
||||||
|
// Do nothing
|
||||||
|
if (traits_type::eq_int_type( c, traits_type::eof() ))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Else write a character
|
||||||
|
return maybe_eof( std::fputc( c, fp ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
//......................................................................
|
||||||
|
virtual this_type* setbuf( char* s, std::streamsize n )
|
||||||
|
{
|
||||||
|
return std::setvbuf( fp, s, (s and n) ? _IOLBF : _IONBF, (size_t)n )
|
||||||
|
? NULL
|
||||||
|
: this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//......................................................................
|
||||||
|
virtual pos_type seekoff(
|
||||||
|
off_type offset,
|
||||||
|
std::ios_base::seekdir direction,
|
||||||
|
std::ios_base::openmode which = std::ios_base::in | std::ios_base::out
|
||||||
|
) {
|
||||||
|
pushbacks.clear();
|
||||||
|
return std::fseek( fp, offset,
|
||||||
|
(direction == std::ios_base::beg) ? SEEK_SET :
|
||||||
|
(direction == std::ios_base::cur) ? SEEK_CUR :
|
||||||
|
SEEK_END
|
||||||
|
) ? (-1) : std::ftell( fp );
|
||||||
|
}
|
||||||
|
|
||||||
|
//......................................................................
|
||||||
|
virtual pos_type seekpos(
|
||||||
|
pos_type position,
|
||||||
|
std::ios_base::openmode which = std::ios_base::in | std::ios_base::out
|
||||||
|
) {
|
||||||
|
pushbacks.clear();
|
||||||
|
return std::fseek( fp, position, SEEK_SET )
|
||||||
|
? (-1)
|
||||||
|
: std::ftell( fp );
|
||||||
|
}
|
||||||
|
|
||||||
|
//......................................................................
|
||||||
|
virtual int sync()
|
||||||
|
{
|
||||||
|
pushbacks.clear();
|
||||||
|
return std::fflush( fp )
|
||||||
|
? traits_type::eof()
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
private:
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
FILE* fp;
|
||||||
|
std::vector <int_type> pushbacks; // we'll treat this like a stack
|
||||||
|
|
||||||
|
//......................................................................
|
||||||
|
// Utility function to make sure EOF gets translated to the proper value
|
||||||
|
inline int_type maybe_eof( int value ) const
|
||||||
|
{
|
||||||
|
return (value == EOF) ? traits_type::eof() : value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* /////////////////////////////////////////////////////////////////////////
|
||||||
|
basic_stdiostream
|
||||||
|
///////////////////////////////////////////////////////////////////////// */
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename CharType,
|
||||||
|
typename CharTraits = std::char_traits <CharType>
|
||||||
|
>
|
||||||
|
struct basic_stdiostream: public std::basic_iostream <CharType, CharTraits>
|
||||||
|
{
|
||||||
|
typedef CharType char_type;
|
||||||
|
typedef CharTraits traits_type;
|
||||||
|
|
||||||
|
typedef basic_stdiobuf <char_type, traits_type> sbuf_type;
|
||||||
|
typedef basic_stdiostream <char_type, traits_type> this_type;
|
||||||
|
typedef std::basic_iostream <char_type, traits_type> base_type;
|
||||||
|
|
||||||
|
//......................................................................
|
||||||
|
basic_stdiostream( FILE* fp = NULL ):
|
||||||
|
base_type( new sbuf_type( fp ) )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
//......................................................................
|
||||||
|
basic_stdiostream( const char* filename, std::ios_base::openmode mode ):
|
||||||
|
//BUG 2: Oops! This is a potential memory leak!
|
||||||
|
base_type( (new sbuf_type)->open( filename, mode ) )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
//......................................................................
|
||||||
|
void open(
|
||||||
|
const char* filename,
|
||||||
|
std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out
|
||||||
|
) {
|
||||||
|
sbuf_type* buf = static_cast <sbuf_type*> ( this->rdbuf() );
|
||||||
|
if (!(buf->open( filename, mode )))
|
||||||
|
this->setstate( std::ios_base::badbit );
|
||||||
|
}
|
||||||
|
|
||||||
|
//......................................................................
|
||||||
|
void close()
|
||||||
|
{
|
||||||
|
sbuf_type* buf = static_cast <sbuf_type*> ( this->rdbuf() );
|
||||||
|
buf->close();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* /////////////////////////////////////////////////////////////////////////
|
||||||
|
Useful typedefs
|
||||||
|
///////////////////////////////////////////////////////////////////////// */
|
||||||
|
|
||||||
|
typedef basic_stdiobuf <char> stdiobuf;
|
||||||
|
typedef basic_stdiostream <char> stdiostream;
|
||||||
|
|
||||||
|
} // namespace duthomhas
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// end stdiostream.hpp
|
Loading…
Reference in New Issue