Files
pip/piconsole.h
2013-03-18 12:07:44 +04:00

282 lines
13 KiB
C++

/*
PIP - Platform Independent Primitives
Console output/input
Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICONSOLE_H
#define PICONSOLE_H
#include "pikbdlistener.h"
#include "piprotocol.h"
#include "pisystemmonitor.h"
#ifndef WINDOWS
# include <sys/ioctl.h>
# include <fcntl.h>
#endif
/// handlers:
/// void clearVariables(bool clearScreen = true)
/// void start(bool wait = false)
/// void stop(bool clear = false)
class PIConsole: public PIThread
{
public:
PIConsole(bool startNow = true, KBFunc slot = 0);
~PIConsole();
enum Format {Normal = 0x01,
Bold = 0x02,
Faint = 0x04,
Italic = 0x08,
Underline = 0x10,
Blink = 0x20,
Inverse = 0x40,
Black = 0x100,
Red = 0x200,
Green = 0x400,
Yellow = 0x800,
Blue = 0x1000,
Magenta = 0x2000,
Cyan = 0x4000,
White = 0x8000,
BackBlack = 0x10000,
BackRed = 0x20000,
BackGreen = 0x40000,
BackYellow = 0x80000,
BackBlue = 0x100000,
BackMagenta = 0x200000,
BackCyan = 0x400000,
BackWhite = 0x800000,
Dec = 0x1000000,
Hex = 0x2000000,
Oct = 0x4000000,
Bin = 0x8000000,
Scientific = 0x10000000};
enum Alignment {Nothing, Left, Right};
void addString(const PIString & name, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, const PIString * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, const char * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, const bool * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, const short * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, const int * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, const long * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, const llong * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, const uchar * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, const ushort * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, const uint * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, const ulong * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, const ullong * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, const float * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, const double * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, const PIProtocol * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, const PISystemMonitor * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addBitVariable(const PIString & name, const void * ptr, int fromBit, int bitCount, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addEmptyLine(int column = 1, uint count = 1);
PIString getString(int x, int y);
short getShort(int x, int y) {return getString(x, y).toShort();}
int getInt(int x, int y) {return getString(x, y).toInt();}
float getFloat(int x, int y) {return getString(x, y).toFloat();}
double getDouble(int x, int y) {return getString(x, y).toDouble();}
PIString getString(const PIString & name);
short getShort(const PIString & name) {return getString(name).toShort();}
int getInt(const PIString & name) {return getString(name).toInt();}
float getFloat(const PIString & name) {return getString(name).toFloat();}
double getDouble(const PIString & name) {return getString(name).toDouble();}
uint tabsCount() const {return tabs.size();}
PIString currentTab() const {return tabs[cur_tab].name;}
int addTab(const PIString & name, char bind_key = 0);
void removeTab(uint index);
void removeTab(const PIString & name);
bool setTab(uint index);
bool setTab(const PIString & name);
bool setTabBindKey(uint index, char bind_key);
bool setTabBindKey(const PIString & name, char bind_key);
void clearTabs(bool clearScreen = true) {if (clearScreen && isRunning()) {toUpperLeft(); clearScreenLower();} tabs.clear();}
void addCustomStatus(const PIString & str) {tabs[cur_tab].status = str;}
void clearCustomStatus() {tabs[cur_tab].status.clear();}
Alignment defaultAlignment() const {return def_align;}
void setDefaultAlignment(Alignment align) {def_align = align;}
void setColumnAlignment(int col, Alignment align) {if (col < 0 || col >= columns().size_s()) return; column(col).alignment = align;}
void setColumnAlignmentToAll(Alignment align) {piForeach (Tab & i, tabs) piForeach (Column & j, i.columns) j.alignment = align; fillLabels();}
EVENT_HANDLER0(PIConsole, void, clearVariables) {clearVariables(true);}
EVENT_HANDLER1(PIConsole, void, clearVariables, bool, clearScreen) {if (clearScreen && isRunning()) {toUpperLeft(); clearScreenLower();} columns().clear();}
EVENT_HANDLER0(PIConsole, void, waitForFinish) {WAIT_FOR_EXIT}
EVENT_HANDLER0(PIConsole, void, start) {start(false);}
EVENT_HANDLER1(PIConsole, void, start, bool, wait) {PIThread::start(40); if (wait) waitForFinish();}
EVENT_HANDLER0(PIConsole, void, stop) {stop(false);}
EVENT_HANDLER1(PIConsole, void, stop, bool, clear);
PIString fstr(PIFlags<PIConsole::Format> f);
void enableExitCapture(char key = 'Q') {listener->enableExitCapture(key);}
void disableExitCapture() {listener->disableExitCapture();}
bool exitCaptured() const {return listener->exitCaptured();}
char exitKey() const {return listener->exitKey();}
private:
void begin();
void run();
void fillLabels();
#ifdef WINDOWS
void getWinCurCoord() {GetConsoleScreenBufferInfo(hOut, &csbi); ccoord = csbi.dwCursorPosition;}
COORD & getWinCoord(int dx = 0, int dy = 0) {getWinCurCoord(); ccoord.X += dx; ccoord.Y += dy; return ccoord;}
void toUpperLeft() {SetConsoleCursorPosition(hOut, ulcoord);}
void moveRight(int n = 1) {SetConsoleCursorPosition(hOut, getWinCoord(n));}
void moveLeft(int n = 1) {SetConsoleCursorPosition(hOut, getWinCoord(-n));}
void moveTo(int x = 0, int y = 0) {ccoord.X = x; ccoord.Y = y; SetConsoleCursorPosition(hOut, ccoord);}
void clearScreen() {FillConsoleOutputAttribute(hOut, dattr, width * (height + 1), ulcoord, &written);
FillConsoleOutputCharacter(hOut, ' ', width * (height + 1), ulcoord, &written);}
void clearScreenLower() {getWinCurCoord(); FillConsoleOutputAttribute(hOut, dattr, width * height - width * ccoord.Y + ccoord.X, ccoord, &written);
FillConsoleOutputCharacter(hOut, ' ', width * height - width * ccoord.Y + ccoord.X, ccoord, &written);}
void clearLine() {getWinCurCoord(); FillConsoleOutputAttribute(hOut, dattr, width - ccoord.X, ccoord, &written);
FillConsoleOutputCharacter(hOut, ' ', width - ccoord.X, ccoord, &written);}
void newLine() {getWinCurCoord(); ccoord.X = 0; ccoord.Y++; SetConsoleCursorPosition(hOut, ccoord);}
void hideCursor() {curinfo.bVisible = false; SetConsoleCursorInfo(hOut, &curinfo);}
void showCursor() {curinfo.bVisible = true; SetConsoleCursorInfo(hOut, &curinfo);}
#else
void toUpperLeft() {printf("\e[H");}
void moveRight(int n = 1) {if (n > 0) printf("\e[%dC", n);}
void moveLeft(int n = 1) {if (n > 0) printf("\e[%dD", n);}
void moveTo(int x = 0, int y = 0) {printf("\e[%d;%dH", y, x);}
void clearScreen() {printf("\e[H\e[J");}
void clearScreenLower() {printf("\e[J");}
void clearLine() {printf("\e[K");}
void newLine() {printf("\eE");}
void hideCursor() {printf("\e[?25l");}
void showCursor() {printf("\e[?25h");}
#endif
void status();
void checkColumn(uint col) {while (columns().size() < col) columns().push_back(Column(def_align));}
int bitsValue(const void * src, int offset, int count);
const char * toBin(const void * d, int s);
inline void printLine(const PIString & str, int dx = 0, PIFlags<PIConsole::Format> format = PIConsole::Normal);
inline int printValue(const PIString & str, PIFlags<PIConsole::Format> format = PIConsole::Normal);
inline int printValue(const char * str, PIFlags<PIConsole::Format> format = PIConsole::Normal);
inline int printValue(const bool value, PIFlags<PIConsole::Format> format = PIConsole::Normal);
inline int printValue(const int value, PIFlags<PIConsole::Format> format = PIConsole::Normal);
inline int printValue(const long value, PIFlags<PIConsole::Format> format = PIConsole::Normal);
inline int printValue(const llong value, PIFlags<PIConsole::Format> format = PIConsole::Normal);
inline int printValue(const float value, PIFlags<PIConsole::Format> format = PIConsole::Normal);
inline int printValue(const double value, PIFlags<PIConsole::Format> format = PIConsole::Normal);
inline int printValue(const char value, PIFlags<PIConsole::Format> format = PIConsole::Normal);
inline int printValue(const short value, PIFlags<PIConsole::Format> format = PIConsole::Normal);
inline int printValue(const uchar value, PIFlags<PIConsole::Format> format = PIConsole::Normal);
inline int printValue(const ushort value, PIFlags<PIConsole::Format> format = PIConsole::Normal);
inline int printValue(const uint value, PIFlags<PIConsole::Format> format = PIConsole::Normal);
inline int printValue(const ulong value, PIFlags<PIConsole::Format> format = PIConsole::Normal);
inline int printValue(const ullong value, PIFlags<PIConsole::Format> format = PIConsole::Normal);
static void key_event(char key, void * t);
struct Variable {
PIString name;
PIFlags<PIConsole::Format> format;
int nx;
int ny;
int type;
int offset;
int bitFrom;
int bitCount;
union {
const PIString * s;
const bool * b;
const short * sh;
const int * i;
const long * l;
const llong * ll;
const float * f;
const double * d;
const char * c;
const uchar * uc;
const ushort * ush;
const uint * ui;
const ulong * ul;
const ullong * ull;
const void * ptr;
};
void operator =(const Variable & src) {name = src.name; format = src.format; type = src.type; offset = src.offset;
bitFrom = src.bitFrom; bitCount = src.bitCount; ptr = src.ptr; nx = src.nx; ny = src.ny;}
};
struct Column {
PIVector<Variable> variables;
Alignment alignment;
Column(Alignment align = PIConsole::Right) { alignment = align;}
uint size() const {return variables.size();}
Variable & operator [](int index) {return variables[index];}
const Variable & operator [](int index) const {return variables[index];}
void push_back(const Variable & v) {variables.push_back(v);}
void operator =(const Column & src) {variables = src.variables; alignment = src.alignment;}
};
struct Tab {
PIVector<Column> columns;
PIString name;
PIString status;
char key;
Tab() {}
Tab(PIString n, char k) {name = n; key = k;}
~Tab() {;}
};
PIVector<Column> & columns() {return tabs[cur_tab].columns;}
Column & column(int index) {return tabs[cur_tab].columns[index - 1];}
inline int couts(const PIString & v);
inline int couts(const char * v);
inline int couts(const bool v);
inline int couts(const char v);
inline int couts(const short v);
inline int couts(const int v);
inline int couts(const long v);
inline int couts(const llong v);
inline int couts(const uchar v);
inline int couts(const ushort v);
inline int couts(const uint v);
inline int couts(const ulong v);
inline int couts(const ullong v);
inline int couts(const float v);
inline int couts(const double v);
#ifdef WINDOWS
void * hOut;
CONSOLE_SCREEN_BUFFER_INFO sbi, csbi;
CONSOLE_CURSOR_INFO curinfo;
COORD ccoord, ulcoord;
WORD dattr;
DWORD smode, written;
#else
struct termios sterm, vterm;
#endif
PIVector<Tab> tabs;
PIString binstr;
Variable tv;
PIKbdListener * listener;
Alignment def_align;
KBFunc ret_func;
int width, height, pwidth, pheight, ret, col_wid, num_format;
uint my;
uint cur_tab, col_cnt;
};
#endif // PICONSOLE_H