689 lines
22 KiB
C++
689 lines
22 KiB
C++
/*
|
||
PIP - Platform Independent Primitives
|
||
Universal output to console class
|
||
Ivan Pelipenko peri4ko@yandex.ru
|
||
|
||
This program is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU Lesser General Public License as published by
|
||
the Free Software Foundation, either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
This program is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU Lesser General Public License for more details.
|
||
|
||
You should have received a copy of the GNU Lesser General Public License
|
||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
#include "piincludes_p.h"
|
||
#include "picout.h"
|
||
#include "pibytearray.h"
|
||
#include "pistack.h"
|
||
#include "piobject.h"
|
||
#include "pistring_std.h"
|
||
#ifdef HAS_LOCALE
|
||
# include <locale>
|
||
# include <codecvt>
|
||
#endif
|
||
#ifdef WINDOWS
|
||
# include <windows.h>
|
||
# include <wingdi.h>
|
||
# include <wincon.h>
|
||
# define COMMON_LVB_UNDERSCORE 0x8000
|
||
#endif
|
||
|
||
|
||
//! \~\class PICout picout.h
|
||
//! \~\details
|
||
//! \~english \section PICout_sec0 Synopsis
|
||
//! \~russian \section PICout_sec0 Краткий обзор
|
||
//! \~english
|
||
//! This class provide many stream operators for output with some features.
|
||
//! Output to %PICout is thread-sequential, i.e. doesn`t mixed from parallel
|
||
//! threads.
|
||
//!
|
||
//! \~russian
|
||
//! Данный класс предоставляет множество операторов для вывода в консоль.
|
||
//! Вывод в %PICout потоково-последовательный, т.е. не смешивается из параллельных
|
||
//! потоков.
|
||
//!
|
||
//! \~english \section PICout_sec1 Features
|
||
//! \~russian \section PICout_sec1 Особенности
|
||
//! \~english
|
||
//! * support text formatting (color, style)
|
||
//! * insertion spaces between entries
|
||
//! * insertion new line at the end of output
|
||
//! * strings are quoted
|
||
//! * custom output operator can be easily written
|
||
//! * can outpur to console, internal buffer or both
|
||
//!
|
||
//! \~russian
|
||
//! * поддержка форматирования (цвет, стиль)
|
||
//! * вставка пробелов между выводами
|
||
//! * вставка новой строки после последнего вывода
|
||
//! * строки обрамляются кавычками
|
||
//! * легко создавать сови операторы вывода
|
||
//! * может выводить в консоль, внутренний буфер или в оба места
|
||
//!
|
||
//! \~english \section PICout_ex0 Usage
|
||
//! \~russian \section PICout_ex0 Использование
|
||
//! \~\snippet picout.cpp 0
|
||
//!
|
||
//! \~english \section PICout_ex1 Writing your own output operator
|
||
//! \~russian \section PICout_ex1 Создание своего оператора вывода
|
||
//! \~\snippet picout.cpp own
|
||
//!
|
||
|
||
|
||
//! \addtogroup Core
|
||
//! \{
|
||
//! \~\class PICout::Notifier picout.h
|
||
//! \~\brief
|
||
//! \~english Class for emit notifications of PICout
|
||
//! \~russian Класс для посылки событий от PICout
|
||
//!
|
||
//! \~english \section PICoutNotifier_sec0 Synopsis
|
||
//! \~russian \section PICoutNotifier_sec0 Краткий обзор
|
||
//! \~english
|
||
//! This class used as PICout events emitter. When
|
||
//! PICout constructs with external PIString* buffer
|
||
//! and some ID, last copy of this PICout on delete
|
||
//! emit event "finished()" on object Notifier::object().
|
||
//! Sample:
|
||
//!
|
||
//! \~russian
|
||
//! Этот класс используется как источник событий PICout.
|
||
//! Когда PICout сконструирован с внешним буфером PIString*
|
||
//! и каким-то ID, последняя копия этого PICout при уничтожении
|
||
//! посылает событие "finished()" у объекта Notifier::object().
|
||
//! Пример:
|
||
//!
|
||
//! \~\snippet picout.cpp notifier
|
||
//!
|
||
//! \}
|
||
|
||
|
||
class NotifierObject: public PIObject {
|
||
PIOBJECT(NotifierObject)
|
||
public:
|
||
NotifierObject() {}
|
||
EVENT2(finished, int, id, PIString*, buffer);
|
||
};
|
||
|
||
|
||
|
||
PICout::Notifier::Notifier() {
|
||
o = new NotifierObject();
|
||
}
|
||
|
||
|
||
PICout::Notifier * PICout::Notifier::instance() {
|
||
static PICout::Notifier * ret = new PICout::Notifier();
|
||
return ret;
|
||
}
|
||
|
||
|
||
PIObject * PICout::Notifier::object() {
|
||
return instance()->o;
|
||
}
|
||
|
||
|
||
|
||
|
||
using namespace PICoutManipulators;
|
||
|
||
PIMutex & PICout::__mutex__() {static PIMutex * ret = new PIMutex(); return *ret;}
|
||
PIString & PICout::__string__() {static PIString * ret = new PIString(); return *ret;}
|
||
|
||
PICout::OutputDevices PICout::devs = PICout::StdOut;
|
||
|
||
PRIVATE_DEFINITION_START(PICout)
|
||
PIStack<PICoutControls> cos_;
|
||
#ifdef WINDOWS
|
||
static void * hOut;
|
||
static WORD dattr;
|
||
static DWORD smode;
|
||
#endif
|
||
PRIVATE_DEFINITION_END(PICout)
|
||
|
||
#ifdef WINDOWS
|
||
void * PICout::__Private__::hOut = 0;
|
||
WORD PICout::__Private__::dattr = 0;
|
||
DWORD PICout::__Private__::smode = 0;
|
||
#endif
|
||
|
||
PICout::PICout(int controls): fo_(true), cc_(false), fc_(false), act_(true), cnb_(10), co_(controls) {
|
||
init();
|
||
}
|
||
|
||
PICout::PICout(bool active): fo_(true), cc_(false), fc_(false), act_(active), cnb_(10), co_(PICoutManipulators::DefaultControls) {
|
||
buffer_ = nullptr;
|
||
if (act_)
|
||
init();
|
||
}
|
||
|
||
|
||
PICout::PICout(PIString * buffer, int id, PIFlags<PICoutManipulators::PICoutControl> controls): fo_(true), cc_(false),
|
||
fc_(false), act_(true), cnb_(10), co_(controls) {
|
||
init();
|
||
buffer_ = buffer;
|
||
id_ = id;
|
||
}
|
||
|
||
|
||
PICout::PICout(const PICout & other): fo_(other.fo_), cc_(true), fc_(false), act_(other.act_), cnb_(other.cnb_), attr_(other.attr_),
|
||
id_(other.id_), buffer_(other.buffer_), co_(other.co_) {
|
||
}
|
||
|
||
|
||
PICout::~PICout() {
|
||
if (!act_) return;
|
||
if (fc_) applyFormat(PICoutManipulators::Default);
|
||
if (cc_) return;
|
||
newLine();
|
||
if ((co_ & NoLock) != NoLock)
|
||
PICout::__mutex__().unlock();
|
||
if (buffer_)
|
||
((NotifierObject*)Notifier::object())->finished(id_, buffer_);
|
||
}
|
||
|
||
|
||
PICout PICout::operator <<(const PICoutAction v) {
|
||
if (!act_) return *this;
|
||
#ifdef WINDOWS
|
||
CONSOLE_SCREEN_BUFFER_INFO sbi;
|
||
COORD coord;
|
||
CONSOLE_CURSOR_INFO curinfo;
|
||
#endif
|
||
switch (v) {
|
||
case PICoutManipulators::Flush:
|
||
if (!buffer_ && isOutputDeviceActive(StdOut))
|
||
std::cout << std::flush;
|
||
break;
|
||
case PICoutManipulators::Backspace:
|
||
if (isOutputDeviceActive(StdOut)) {
|
||
#ifdef WINDOWS
|
||
GetConsoleScreenBufferInfo(__Private__::hOut, &sbi);
|
||
coord = sbi.dwCursorPosition;
|
||
coord.X = piMax<int>(0, int(coord.X) - 1);
|
||
SetConsoleCursorPosition(__Private__::hOut, coord);
|
||
printf(" ");
|
||
SetConsoleCursorPosition(__Private__::hOut, coord);
|
||
#else
|
||
printf("\e[1D \e[1D");
|
||
#endif
|
||
}
|
||
break;
|
||
case PICoutManipulators::ShowCursor:
|
||
if (isOutputDeviceActive(StdOut)) {
|
||
#ifdef WINDOWS
|
||
GetConsoleCursorInfo(__Private__::hOut, &curinfo);
|
||
curinfo.bVisible = true;
|
||
SetConsoleCursorInfo(__Private__::hOut, &curinfo);
|
||
#else
|
||
printf("\e[?25h");
|
||
#endif
|
||
}
|
||
break;
|
||
case PICoutManipulators::HideCursor:
|
||
if (isOutputDeviceActive(StdOut)) {
|
||
#ifdef WINDOWS
|
||
GetConsoleCursorInfo(__Private__::hOut, &curinfo);
|
||
curinfo.bVisible = false;
|
||
SetConsoleCursorInfo(__Private__::hOut, &curinfo);
|
||
#else
|
||
printf("\e[?25l");
|
||
#endif
|
||
}
|
||
break;
|
||
case PICoutManipulators::ClearLine:
|
||
if (isOutputDeviceActive(StdOut)) {
|
||
#ifdef WINDOWS
|
||
GetConsoleScreenBufferInfo(__Private__::hOut, &sbi);
|
||
coord = sbi.dwCursorPosition;
|
||
int dx = coord.X;
|
||
coord.X = 0;
|
||
SetConsoleCursorPosition(__Private__::hOut, coord);
|
||
if (dx > 0) {
|
||
char * line = new char[dx + 1];
|
||
memset(line, ' ', dx);
|
||
line[dx] = 0;
|
||
printf("%s", line);
|
||
delete[] line;
|
||
}
|
||
SetConsoleCursorPosition(__Private__::hOut, coord);
|
||
#else
|
||
printf("\e[0G\e[K");
|
||
#endif
|
||
}
|
||
break;
|
||
case PICoutManipulators::ClearScreen:
|
||
if (isOutputDeviceActive(StdOut)) {
|
||
#ifdef WINDOWS
|
||
/// TODO : wondows ClearScreen !!!
|
||
#else
|
||
printf("\e[H\e[J");
|
||
#endif
|
||
}
|
||
break;
|
||
case PICoutManipulators::SaveContol: saveControls(); break;
|
||
case PICoutManipulators::RestoreControl: restoreControls(); break;
|
||
default: break;
|
||
};
|
||
return *this;
|
||
}
|
||
|
||
|
||
PICout PICout::operator <<(const PICoutManipulators::PICoutFormat v) {
|
||
switch (v) {
|
||
case PICoutManipulators::Bin: cnb_ = 2; break;
|
||
case PICoutManipulators::Oct: cnb_ = 8; break;
|
||
case PICoutManipulators::Dec: cnb_ = 10; break;
|
||
case PICoutManipulators::Hex: cnb_ = 16; break;
|
||
default: applyFormat(v);
|
||
};
|
||
return *this;
|
||
}
|
||
|
||
|
||
PICout PICout::operator <<(const PIFlags<PICoutManipulators::PICoutFormat> & v) {
|
||
if (v[PICoutManipulators::Bin]) cnb_ = 2;
|
||
if (v[PICoutManipulators::Oct]) cnb_ = 8;
|
||
if (v[PICoutManipulators::Dec]) cnb_ = 10;
|
||
if (v[PICoutManipulators::Hex]) cnb_ = 16;
|
||
if (v[PICoutManipulators::Bold]) applyFormat(PICoutManipulators::Bold);
|
||
if (v[PICoutManipulators::Faint]) applyFormat(PICoutManipulators::Faint);
|
||
if (v[PICoutManipulators::Italic]) applyFormat(PICoutManipulators::Italic);
|
||
if (v[PICoutManipulators::Underline]) applyFormat(PICoutManipulators::Underline);
|
||
if (v[PICoutManipulators::Blink]) applyFormat(PICoutManipulators::Blink);
|
||
if (v[PICoutManipulators::Black]) applyFormat(PICoutManipulators::Black);
|
||
if (v[PICoutManipulators::Red]) applyFormat(PICoutManipulators::Red);
|
||
if (v[PICoutManipulators::Green]) applyFormat(PICoutManipulators::Green);
|
||
if (v[PICoutManipulators::Blue]) applyFormat(PICoutManipulators::Blue);
|
||
if (v[PICoutManipulators::Yellow]) applyFormat(PICoutManipulators::Yellow);
|
||
if (v[PICoutManipulators::Magenta]) applyFormat(PICoutManipulators::Magenta);
|
||
if (v[PICoutManipulators::Cyan]) applyFormat(PICoutManipulators::Cyan);
|
||
if (v[PICoutManipulators::White]) applyFormat(PICoutManipulators::White);
|
||
if (v[PICoutManipulators::BackBlack]) applyFormat(PICoutManipulators::BackBlack);
|
||
if (v[PICoutManipulators::BackRed]) applyFormat(PICoutManipulators::BackRed);
|
||
if (v[PICoutManipulators::BackGreen]) applyFormat(PICoutManipulators::BackGreen);
|
||
if (v[PICoutManipulators::BackBlue]) applyFormat(PICoutManipulators::BackBlue);
|
||
if (v[PICoutManipulators::BackYellow]) applyFormat(PICoutManipulators::BackYellow);
|
||
if (v[PICoutManipulators::BackMagenta]) applyFormat(PICoutManipulators::BackMagenta);
|
||
if (v[PICoutManipulators::BackCyan]) applyFormat(PICoutManipulators::BackCyan);
|
||
if (v[PICoutManipulators::BackWhite]) applyFormat(PICoutManipulators::BackWhite);
|
||
if (v[PICoutManipulators::Default]) applyFormat(PICoutManipulators::Default);
|
||
return *this;
|
||
}
|
||
|
||
#define PIINTCOUT(v) { \
|
||
if (!act_) return *this; \
|
||
space(); \
|
||
if (cnb_ == 10) {\
|
||
if (buffer_) {\
|
||
(*buffer_) += PIString::fromNumber(v);\
|
||
} else {\
|
||
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << (v);\
|
||
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() += PIString::fromNumber(v);\
|
||
}\
|
||
} else write(PIString::fromNumber(v, cnb_)); \
|
||
return *this; \
|
||
}
|
||
|
||
#define PIFLOATCOUT(v) { \
|
||
if (buffer_) {\
|
||
(*buffer_) += PIString::fromNumber(v, 'g');\
|
||
} else {\
|
||
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << (v);\
|
||
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() += PIString::fromNumber(v, 'g');\
|
||
}\
|
||
}
|
||
|
||
|
||
PICout PICout::operator <<(const char * v) {if (!act_ || !v) return *this; if (v[0] == '\0') return *this; space(); quote(); write(v); quote(); return *this;}
|
||
|
||
PICout PICout::operator <<(const bool v) {if (!act_) return *this; space(); if (v) write("true"); else write("false"); return *this;}
|
||
|
||
PICout PICout::operator <<(const char v) {if (!act_) return *this; space(); write(v); return *this;}
|
||
|
||
PICout PICout::operator <<(const uchar v) {PIINTCOUT(ushort(v))}
|
||
|
||
PICout PICout::operator <<(const short int v) {PIINTCOUT(v)}
|
||
|
||
PICout PICout::operator <<(const ushort v) {PIINTCOUT(v)}
|
||
|
||
PICout PICout::operator <<(const int v) {PIINTCOUT(v)}
|
||
|
||
PICout PICout::operator <<(const uint v) {PIINTCOUT(v)}
|
||
|
||
PICout PICout::operator <<(const long v) {PIINTCOUT(v)}
|
||
|
||
PICout PICout::operator <<(const ulong v) {PIINTCOUT(v)}
|
||
|
||
PICout PICout::operator <<(const llong v) {PIINTCOUT(v)}
|
||
|
||
PICout PICout::operator <<(const ullong v) {PIINTCOUT(v)}
|
||
|
||
PICout PICout::operator <<(const float v) {if (!act_) return *this; space(); PIFLOATCOUT(v) return *this;}
|
||
|
||
PICout PICout::operator <<(const double v) {if (!act_) return *this; space(); PIFLOATCOUT(v) return *this;}
|
||
|
||
PICout PICout::operator <<(const void * v) {if (!act_) return *this; space(); write("0x" + PIString::fromNumber(ullong(v), 16)); return *this;}
|
||
|
||
PICout PICout::operator <<(const PIObject * v) {
|
||
if (!act_) return *this;
|
||
space();
|
||
if (v == 0) write("PIObject*(0x0)");
|
||
else {
|
||
write(v->className());
|
||
write("*(0x" + PIString::fromNumber(ullong(v), 16) + ", \"" + v->name() + "\")");
|
||
}
|
||
return *this;
|
||
}
|
||
|
||
PICout PICout::operator <<(const PICoutSpecialChar v) {
|
||
if (!act_) return *this;
|
||
switch (v) {
|
||
case Null:
|
||
if (buffer_) {
|
||
(*buffer_) += PIChar();
|
||
} else {
|
||
if (isOutputDeviceActive(StdOut)) std::cout << char(0);
|
||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += PIChar();
|
||
}
|
||
break;
|
||
case NewLine:
|
||
if (buffer_) {
|
||
(*buffer_) += "\n";
|
||
} else {
|
||
if (isOutputDeviceActive(StdOut)) std::cout << '\n';
|
||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\n";
|
||
}
|
||
fo_ = true;
|
||
break;
|
||
case Tab:
|
||
if (buffer_) {
|
||
(*buffer_) += "\t";
|
||
} else {
|
||
if (isOutputDeviceActive(StdOut)) std::cout << '\t';
|
||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\t";
|
||
}
|
||
break;
|
||
case Esc:
|
||
#ifdef CC_VC
|
||
if (buffer_) {
|
||
(*buffer_) += PIChar(27);
|
||
} else {
|
||
if (isOutputDeviceActive(StdOut)) std::cout << char(27);
|
||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += PIChar(27);
|
||
}
|
||
#else
|
||
if (buffer_) {
|
||
(*buffer_) += "\e";
|
||
} else {
|
||
if (isOutputDeviceActive(StdOut)) std::cout << '\e';
|
||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\e";
|
||
}
|
||
#endif
|
||
break;
|
||
case Quote:
|
||
if (buffer_) {
|
||
(*buffer_) += "\"";
|
||
} else {
|
||
if (isOutputDeviceActive(StdOut)) std::cout << '"';
|
||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\"";
|
||
}
|
||
break;
|
||
};
|
||
return *this;
|
||
}
|
||
|
||
|
||
PICout & PICout::saveControls() {
|
||
if (!act_) return *this;
|
||
PRIVATE->cos_.push(co_);
|
||
return *this;
|
||
}
|
||
|
||
|
||
PICout & PICout::restoreControls() {
|
||
if (!act_) return *this;
|
||
if (!PRIVATE->cos_.isEmpty()) {
|
||
co_ = PRIVATE->cos_.top();
|
||
PRIVATE->cos_.pop();
|
||
}
|
||
return *this;
|
||
}
|
||
|
||
|
||
|
||
//! \details
|
||
//! \~english
|
||
//! If it is not a first output and control \a AddSpaces is set space character is put
|
||
//! \~russian
|
||
//! Добавляет пробел если это не первый вывод и установлен флаг \a AddSpaces
|
||
//! \~\sa \a quote(), \a newLine()
|
||
PICout & PICout::space() {
|
||
if (!act_) return *this;
|
||
if (!fo_ && co_[AddSpaces]) {
|
||
if (buffer_) {
|
||
(*buffer_) += " ";
|
||
} else {
|
||
if (isOutputDeviceActive(StdOut)) std::cout << ' ';
|
||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += " ";
|
||
}
|
||
}
|
||
fo_ = false;
|
||
return *this;
|
||
}
|
||
|
||
//! \details
|
||
//! \~english
|
||
//! If control \a AddQuotes is set quote character is put
|
||
//! \~russian
|
||
//! Добавляет кавычки если установлен флаг \a AddQuotes
|
||
//! \~\sa \a space(), \a newLine()
|
||
PICout & PICout::quote() {
|
||
if (!act_) return *this;
|
||
if (co_[AddQuotes]) {
|
||
if (buffer_) {
|
||
(*buffer_) += "\"";
|
||
} else {
|
||
if (isOutputDeviceActive(StdOut)) std::cout << '"';
|
||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\"";
|
||
}
|
||
}
|
||
fo_ = false;
|
||
return *this;
|
||
}
|
||
|
||
//! \details
|
||
//! \~english
|
||
//! If control \a AddNewLine is set new line character is put
|
||
//! \~russian
|
||
//! Добавляет новую строку если установлен флаг \a AddNewLine
|
||
//! \~\sa \a space(), \a quote()
|
||
PICout & PICout::newLine() {
|
||
if (!act_) return *this;
|
||
if (co_[AddNewLine]) {
|
||
if (buffer_) {
|
||
(*buffer_) += "\n";
|
||
} else {
|
||
if (isOutputDeviceActive(StdOut)) std::cout << std::endl;
|
||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\n";
|
||
}
|
||
}
|
||
fo_ = false;
|
||
return *this;
|
||
}
|
||
|
||
|
||
PICout & PICout::write(char c) {
|
||
if (!act_) return *this;
|
||
if (buffer_) {
|
||
buffer_->append(c);
|
||
} else {
|
||
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << c;
|
||
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__().append(c);
|
||
}
|
||
return *this;
|
||
}
|
||
|
||
|
||
PICout & PICout::write(const char * str) {
|
||
if (!act_ || !str) return *this;
|
||
return write(str, strlen(str));
|
||
}
|
||
|
||
|
||
PICout & PICout::write(const char * str, int len) {
|
||
if (!act_ || !str) return *this;
|
||
if (buffer_) {
|
||
buffer_->append(PIString(str, len));
|
||
} else {
|
||
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout.write(str, len);
|
||
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__().append(PIString(str, len));
|
||
}
|
||
return *this;
|
||
}
|
||
|
||
|
||
PICout & PICout::write(const PIString & s) {
|
||
if (!act_) return *this;
|
||
if (buffer_) {
|
||
buffer_->append(s);
|
||
} else {
|
||
if (PICout::isOutputDeviceActive(PICout::StdOut)) stdoutPIString(s);
|
||
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__().append(s);
|
||
}
|
||
return *this;
|
||
}
|
||
|
||
|
||
void PICout::stdoutPIString(const PIString & s) {
|
||
#ifdef HAS_LOCALE
|
||
std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> utf8conv;
|
||
std::cout << utf8conv.to_bytes((char16_t*)&(const_cast<PIString&>(s).front()), (char16_t*)&(const_cast<PIString&>(s).front()) + s.size());
|
||
#else
|
||
for (PIChar c: s) std::wcout.put(c.toWChar());
|
||
#endif
|
||
}
|
||
|
||
|
||
void PICout::init() {
|
||
#ifdef WINDOWS
|
||
if (__Private__::hOut == 0) {
|
||
__Private__::hOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||
CONSOLE_SCREEN_BUFFER_INFO sbi;
|
||
GetConsoleScreenBufferInfo(__Private__::hOut, &sbi);
|
||
__Private__::dattr = sbi.wAttributes;
|
||
}
|
||
attr_ = __Private__::dattr;
|
||
#endif
|
||
buffer_ = nullptr;
|
||
id_ = 0;
|
||
if ((co_ & NoLock) != NoLock)
|
||
PICout::__mutex__().lock();
|
||
}
|
||
|
||
|
||
void PICout::applyFormat(PICoutFormat f) {
|
||
if (!act_) return;
|
||
if (buffer_ || !isOutputDeviceActive(StdOut)) return;
|
||
fc_ = true;
|
||
#ifdef WINDOWS
|
||
static int mask_fore = ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||
static int mask_back = ~(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
|
||
switch (f) {
|
||
case Bin: case Oct: case Dec: case Hex: break;
|
||
case PICoutManipulators::Bold: attr_ |= FOREGROUND_INTENSITY; break;
|
||
case PICoutManipulators::Underline: attr_ |= COMMON_LVB_UNDERSCORE; break;
|
||
case PICoutManipulators::Black: attr_ = (attr_ & mask_fore); break;
|
||
case PICoutManipulators::Red: attr_ = (attr_ & mask_fore) | FOREGROUND_RED; break;
|
||
case PICoutManipulators::Green: attr_ = (attr_ & mask_fore) | FOREGROUND_GREEN; break;
|
||
case PICoutManipulators::Blue: attr_ = (attr_ & mask_fore) | FOREGROUND_BLUE; break;
|
||
case PICoutManipulators::Yellow: attr_ = (attr_ & mask_fore) | FOREGROUND_RED | FOREGROUND_GREEN; break;
|
||
case PICoutManipulators::Magenta: attr_ = (attr_ & mask_fore) | FOREGROUND_RED | FOREGROUND_BLUE; break;
|
||
case PICoutManipulators::Cyan: attr_ = (attr_ & mask_fore) | FOREGROUND_GREEN | FOREGROUND_BLUE; break;
|
||
case PICoutManipulators::White: attr_ = (attr_ & mask_fore) | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; break;
|
||
case PICoutManipulators::BackBlack: attr_ = (attr_ & mask_back); break;
|
||
case PICoutManipulators::BackRed: attr_ = (attr_ & mask_back) | BACKGROUND_RED; break;
|
||
case PICoutManipulators::BackGreen: attr_ = (attr_ & mask_back) | BACKGROUND_GREEN; break;
|
||
case PICoutManipulators::BackBlue: attr_ = (attr_ & mask_back) | BACKGROUND_BLUE; break;
|
||
case PICoutManipulators::BackYellow: attr_ = (attr_ & mask_back) | BACKGROUND_RED | BACKGROUND_GREEN; break;
|
||
case PICoutManipulators::BackMagenta: attr_ = (attr_ & mask_back) | BACKGROUND_RED | BACKGROUND_BLUE; break;
|
||
case PICoutManipulators::BackCyan: attr_ = (attr_ & mask_back) | BACKGROUND_GREEN | BACKGROUND_BLUE; break;
|
||
case PICoutManipulators::BackWhite: attr_ = (attr_ & mask_back) | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE; break;
|
||
case PICoutManipulators::Default: attr_ = __Private__::dattr; break;
|
||
default: break;
|
||
}
|
||
SetConsoleTextAttribute(__Private__::hOut, attr_);
|
||
#else
|
||
switch (f) {
|
||
case Bin: case Oct: case Dec: case Hex: break;
|
||
case PICoutManipulators::Bold: printf("\e[1m"); break;
|
||
case PICoutManipulators::Faint: printf("\e[2m"); break;
|
||
case PICoutManipulators::Italic: printf("\e[3m"); break;
|
||
case PICoutManipulators::Underline: printf("\e[4m"); break;
|
||
case PICoutManipulators::Blink: printf("\e[5m"); break;
|
||
case PICoutManipulators::Black: printf("\e[30m"); break;
|
||
case PICoutManipulators::Red: printf("\e[31m"); break;
|
||
case PICoutManipulators::Green: printf("\e[32m"); break;
|
||
case PICoutManipulators::Blue: printf("\e[34m"); break;
|
||
case PICoutManipulators::Yellow: printf("\e[33m"); break;
|
||
case PICoutManipulators::Magenta: printf("\e[35m"); break;
|
||
case PICoutManipulators::Cyan: printf("\e[36m"); break;
|
||
case PICoutManipulators::White: printf("\e[37m"); break;
|
||
case PICoutManipulators::BackBlack: printf("\e[40m"); break;
|
||
case PICoutManipulators::BackRed: printf("\e[41m"); break;
|
||
case PICoutManipulators::BackGreen: printf("\e[42m"); break;
|
||
case PICoutManipulators::BackBlue: printf("\e[44m"); break;
|
||
case PICoutManipulators::BackYellow: printf("\e[43m"); break;
|
||
case PICoutManipulators::BackMagenta: printf("\e[45m"); break;
|
||
case PICoutManipulators::BackCyan: printf("\e[46m"); break;
|
||
case PICoutManipulators::BackWhite: printf("\e[47m"); break;
|
||
case PICoutManipulators::Default: printf("\e[0m"); break;
|
||
default: break;
|
||
}
|
||
#endif
|
||
}
|
||
|
||
|
||
PIString PICout::getBuffer() {
|
||
PIMutexLocker ml(PICout::__mutex__());
|
||
PIString ret = PICout::__string__();
|
||
return ret;
|
||
}
|
||
|
||
|
||
PIString PICout::getBufferAndClear() {
|
||
PIMutexLocker ml(PICout::__mutex__());
|
||
PIString ret = PICout::__string__();
|
||
PICout::__string__().clear();
|
||
return ret;
|
||
}
|
||
|
||
|
||
void PICout::clearBuffer() {
|
||
PIMutexLocker ml(PICout::__mutex__());
|
||
PICout::__string__().clear();
|
||
}
|
||
|
||
|
||
bool PICout::setOutputDevice(PICout::OutputDevice d, bool on) {
|
||
bool ret = devs[d];
|
||
devs.setFlag(d, on);
|
||
return ret;
|
||
}
|
||
|
||
|
||
void PICout::setOutputDevices(PICout::OutputDevices d) {
|
||
devs = d;
|
||
}
|
||
|
||
|
||
bool PICout::isOutputDeviceActive(PICout::OutputDevice d) {
|
||
return devs[d];
|
||
}
|