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