Files
pip/piconsole.cpp
2011-10-09 22:23:52 +04:00

501 lines
19 KiB
C++

#include "piconsole.h"
PIConsole::PIConsole(bool startNow, KBFunc slot): PIThread() {
setPriority(piLow);
needLockRun(true);
ret_func = slot;
num_format = 0;
cur_tab = width = height = pwidth = pheight = my = 0;
#ifdef WINDOWS
ulcoord.X = ulcoord.Y = 0;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hOut, &sbi);
dattr = sbi.wAttributes;
width = sbi.srWindow.Right - sbi.srWindow.Left;
height = sbi.srWindow.Bottom - sbi.srWindow.Top;
GetConsoleMode(hOut, &smode);
GetConsoleCursorInfo(hOut, &curinfo);
#endif
addTab("main");
listener = new PIKbdListener(key_event, this);
if (startNow) start();
}
PIConsole::~PIConsole() {
if (isRunning())
stop();
clearTabs(false);
delete listener;
#ifdef WINDOWS
SetConsoleMode(hOut, smode);
SetConsoleTextAttribute(hOut, dattr);
#endif
}
int PIConsole::addTab(const PIString & name, char bind_key) {
tabs.push_back(Tab(name, bind_key));
cur_tab = tabs.size() - 1;
return tabs.size();
}
void PIConsole::removeTab(uint index) {
if (index >= tabs.size()) return;
tabs.remove(index);
if (cur_tab >= tabs.size()) cur_tab = tabs.size() - 1;
}
void PIConsole::removeTab(const PIString & name) {
uint index = tabs.size() + 1;
for (uint i = 0; i < tabs.size(); ++i) {
if (tabs[i].name == name) {
index = i;
break;
}
}
removeTab(index);
}
bool PIConsole::setTab(uint index) {
if (index >= tabs.size())
return false;
cur_tab = index;
if (!isRunning()) return true;
lock();
clearScreen();
fillLabels();
unlock();
return true;
}
bool PIConsole::setTab(const PIString & name) {
uint index = tabs.size() + 1;
for (uint i = 0; i < tabs.size(); ++i) {
if (tabs[i].name == name) {
index = i;
break;
}
}
return setTab(index);
}
bool PIConsole::setTabBindKey(uint index, char bind_key) {
if (index >= tabs.size())
return false;
tabs[index].key = bind_key;
return true;
}
bool PIConsole::setTabBindKey(const PIString & name, char bind_key) {
uint index =tabs.size() + 1;
for (uint i = 0; i < tabs.size(); ++i) {
if (tabs[i].name == name) {
index = i;
break;
}
}
return setTabBindKey(index, bind_key);
}
void PIConsole::key_event(char key, void * t) {
PIConsole * p = (PIConsole * )t;
for (uint i = 0; i < p->tabsCount(); ++i) {
if (p->tabs[i].key == key) {
p->setTab(i);
return;
}
}
if (p->ret_func != 0) p->ret_func(key, t);
}
void PIConsole::stop(bool clear) {
PIThread::stop(true);
if (clear) clearScreen();
moveTo(0, my + 4);
showCursor();
couts(fstr(Normal).stdString());
#ifdef WINDOWS
SetConsoleMode(hOut, smode);
SetConsoleTextAttribute(hOut, dattr);
#endif
fflush(0);
}
PIString PIConsole::fstr(PIFlags<PIConsole::Format> f) {
if (f[PIConsole::Dec]) num_format = 0;
if (f[PIConsole::Hex]) num_format = 1;
if (f[PIConsole::Oct]) num_format = 2;
if (f[PIConsole::Scientific]) num_format = 3;
#ifdef WINDOWS
WORD attr = 0;
if (f[PIConsole::Inverse]) {
if (f[PIConsole::Red]) attr |= BACKGROUND_RED;
if (f[PIConsole::Green]) attr |= BACKGROUND_GREEN;
if (f[PIConsole::Blue]) attr |= BACKGROUND_BLUE;
if (f[PIConsole::Yellow]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN);
if (f[PIConsole::Magenta]) attr |= (BACKGROUND_RED | BACKGROUND_BLUE);
if (f[PIConsole::Cyan]) attr |= (BACKGROUND_GREEN | BACKGROUND_BLUE);
if (f[PIConsole::White]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
if (f[PIConsole::BackRed]) attr |= FOREGROUND_RED;
if (f[PIConsole::BackGreen]) attr |= FOREGROUND_GREEN;
if (f[PIConsole::BackBlue]) attr |= FOREGROUND_BLUE;
if (f[PIConsole::BackYellow]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN);
if (f[PIConsole::BackMagenta]) attr |= (FOREGROUND_RED | FOREGROUND_BLUE);
if (f[PIConsole::BackCyan]) attr |= (FOREGROUND_GREEN | FOREGROUND_BLUE);
if (f[PIConsole::BackWhite]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
} else {
if (f[PIConsole::Red]) attr |= FOREGROUND_RED;
if (f[PIConsole::Green]) attr |= FOREGROUND_GREEN;
if (f[PIConsole::Blue]) attr |= FOREGROUND_BLUE;
if (f[PIConsole::Yellow]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN);
if (f[PIConsole::Magenta]) attr |= (FOREGROUND_RED | FOREGROUND_BLUE);
if (f[PIConsole::Cyan]) attr |= (FOREGROUND_GREEN | FOREGROUND_BLUE);
if (f[PIConsole::White]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
if (f[PIConsole::BackRed]) attr |= BACKGROUND_RED;
if (f[PIConsole::BackGreen]) attr |= BACKGROUND_GREEN;
if (f[PIConsole::BackBlue]) attr |= BACKGROUND_BLUE;
if (f[PIConsole::BackYellow]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN);
if (f[PIConsole::BackMagenta]) attr |= (BACKGROUND_RED | BACKGROUND_BLUE);
if (f[PIConsole::BackCyan]) attr |= (BACKGROUND_GREEN | BACKGROUND_BLUE);
if (f[PIConsole::BackWhite]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
}
if (f[PIConsole::Bold]) attr |= FOREGROUND_INTENSITY;
SetConsoleTextAttribute(hOut, attr);
return PIString();
#else
PIString ts("\e[0");
if (f[PIConsole::Bold]) ts += ";1";
if (f[PIConsole::Faint]) ts += ";2";
if (f[PIConsole::Italic]) ts += ";3";
if (f[PIConsole::Underline]) ts += ";4";
if (f[PIConsole::Blink]) ts += ";5";
if (f[PIConsole::Inverse]) ts += ";7";
if (f[PIConsole::Black]) ts += ";30";
if (f[PIConsole::Red]) ts += ";31";
if (f[PIConsole::Green]) ts += ";32";
if (f[PIConsole::Yellow]) ts += ";33";
if (f[PIConsole::Blue]) ts += ";34";
if (f[PIConsole::Magenta]) ts += ";35";
if (f[PIConsole::Cyan]) ts += ";36";
if (f[PIConsole::White]) ts += ";37";
if (f[PIConsole::BackBlack]) ts += ";40";
if (f[PIConsole::BackRed]) ts += ";41";
if (f[PIConsole::BackGreen]) ts += ";42";
if (f[PIConsole::BackYellow]) ts += ";43";
if (f[PIConsole::BackBlue]) ts += ";44";
if (f[PIConsole::BackMagenta]) ts += ";45";
if (f[PIConsole::BackCyan]) ts += ";46";
if (f[PIConsole::BackWhite]) ts += ";47";
return ts + "m";
#endif
}
#define siprint(x) switch (num_format) {case (1): return printf("0x%.4hX", x); break; case (2): return printf("%o", x); break; default: return printf("%hd", x); break;}
#define iprint(x) switch (num_format) {case (1): return printf("0x%.8X", x); break; case (2): return printf("%o", x); break; default: return printf("%d", x); break;}
#define liprint(x) switch (num_format) {case (1): return printf("0x%.16lX", x); break; case (2): return printf("%lo", x); break; default: return printf("%ld", x); break;}
#define lliprint(x) switch (num_format) {case (1): return printf("0x%.16llX", x); break; case (2): return printf("%llo", x); break; default: return printf("%lld", x); break;}
#define cuprint(x) switch (num_format) {case (1): return printf("0x%.2X", x); break; case (2): return printf("%o", x); break; default: return printf("%u", x); break;}
#define suprint(x) switch (num_format) {case (1): return printf("0x%.4hX", x); break; case (2): return printf("%o", x); break; default: return printf("%hd", x); break;}
#define uprint(x) switch (num_format) {case (1): return printf("0x%.8X", x); break; case (2): return printf("%o", x); break; default: return printf("%u", x); break;}
#define luprint(x) switch (num_format) {case (1): return printf("0x%.16lX", x); break; case (2): return printf("%lo", x); break; default: return printf("%lu", x); break;}
#define lluprint(x) switch (num_format) {case (1): return printf("0x%.16llX", x); break; case (2): return printf("%llo", x); break; default: return printf("%llu", x); break;}
#define fprint(x) switch (num_format) {case (3): return printf("%e", x); break; default: return printf("%.5g", x); break;}
#define dprint(x) switch (num_format) {case (3): return printf("%le", x); break; default: return printf("%.5lg", x); break;}
inline int PIConsole::couts(const string v) {return printf("%s", v.c_str());}
inline int PIConsole::couts(const char * v) {return printf("%s", v);}
inline int PIConsole::couts(const bool v) {return (v ? printf("true") : printf("false"));}
inline int PIConsole::couts(const char v) {return printf("%c", v);}
inline int PIConsole::couts(const short v) {siprint(v);}
inline int PIConsole::couts(const int v) {iprint(v);}
inline int PIConsole::couts(const long v) {liprint(v);}
inline int PIConsole::couts(const llong v) {lliprint(v);}
inline int PIConsole::couts(const uchar v) {cuprint(v);}
inline int PIConsole::couts(const ushort v) {suprint(v);}
inline int PIConsole::couts(const uint v) {uprint(v);}
inline int PIConsole::couts(const ulong v) {luprint(v);}
inline int PIConsole::couts(const ullong v) {lluprint(v);}
inline int PIConsole::couts(const float v) {fprint(v);}
inline int PIConsole::couts(const double v) {dprint(v);}
void PIConsole::begin() {
#ifdef WINDOWS
SetConsoleMode(hOut, ENABLE_WRAP_AT_EOL_OUTPUT);
#endif
clearScreen();
hideCursor();
fillLabels();
}
void PIConsole::run() {
uint cx, clen = 0;
#ifdef WINDOWS
GetConsoleScreenBufferInfo(hOut, &sbi);
width = sbi.srWindow.Right - sbi.srWindow.Left;
height = sbi.srWindow.Bottom - sbi.srWindow.Top;
#else
winsize ws;
ioctl(0, TIOCGWINSZ, &ws);
width = ws.ws_col;
height = ws.ws_row;
#endif
if (pwidth != width || pheight != height) {
clearScreen();
fillLabels();
}
pwidth = width;
pheight = height;
col_cnt = vars().size();
col_wid = (col_cnt > 0) ? width / col_cnt : width;
for (uint i = 0; i < col_cnt; ++i) {
cx = col_wid * i;
toUpperLeft();
if (my < vars()[i].size()) my = vars()[i].size();
piForeachC (Variable & tv, vars()[i]) {
moveRight(cx);
if (tv.type == 0 && tv.s == 0) {
newLine();
continue;
}
moveRight(tv.offset);
switch (tv.type) {
case 0: clen = printValue(tv.s != 0 ? *tv.s : "", tv.format); break;
case 1: clen = printValue(tv.b != 0 ? *tv.b : false, tv.format); break;
case 2: clen = printValue(tv.i != 0 ? *tv.i : 0, tv.format); break;
case 3: clen = printValue(tv.l != 0 ? *tv.l : 0l, tv.format); break;
case 4: clen = printValue(tv.c != 0 ? *tv.c : 0, tv.format); break;
case 5: clen = printValue(tv.f != 0 ? *tv.f : 0.f, tv.format); break;
case 6: clen = printValue(tv.d != 0 ? *tv.d : 0., tv.format); break;
case 7: clen = printValue(tv.sh != 0 ? *tv.sh : 0, tv.format); break;
case 8: clen = printValue(tv.ui != 0 ? *tv.ui : 0u, tv.format); break;
case 9: clen = printValue(tv.ul != 0 ? *tv.ul : 0ul, tv.format); break;
case 10: clen = printValue(tv.ush != 0 ? *tv.ush : 0u, tv.format); break;
case 11: clen = printValue(tv.uc != 0 ? *tv.uc : 0u, tv.format); break;
case 12: clen = printValue(tv.ll != 0 ? *tv.ll : 0l, tv.format); break;
case 13: clen = printValue(tv.ull != 0 ? *tv.ull : 0ull, tv.format); break;
case 14: clen = printValue(bitsValue(tv.ptr, tv.bitFrom, tv.bitCount), tv.format); break;
}
if (clen + tv.offset < (uint)col_wid) {
string ts = PIString(col_wid - clen - tv.offset, ' ').stdString();
printf("%s", ts.c_str());
}
newLine();
}
}
fflush(0);
}
void PIConsole::fillLabels() {
uint cx, cy, my = 0;
#ifdef WINDOWS
GetConsoleScreenBufferInfo(hOut, &sbi);
width = sbi.srWindow.Right - sbi.srWindow.Left;
height = sbi.srWindow.Bottom - sbi.srWindow.Top;
#else
winsize ws;
ioctl(0, TIOCGWINSZ, &ws);
width = ws.ws_col;
height = ws.ws_row;
#endif
col_cnt = vars().size();
col_wid = (col_cnt > 0) ? width / col_cnt : width;
for (uint i = 0; i < col_cnt; ++i) {
cx = col_wid * i;
cy = 1;
toUpperLeft();
for (uint j = 0; j < vars()[i].size(); ++j) {
if (my < j) my = j;
moveRight(cx);
tv = vars()[i][j];
vars()[i][j].nx = cx;
vars()[i][j].ny = cy;
if (tv.name.size() == 0) {
vars()[i][j].offset = 0;
clearLine();
newLine();
cy++;
continue;
}
clearLine();
if (tv.type == 0 && tv.s == 0) {
vars()[i][j].offset = vars()[i][j].name.length();
vars()[i][j].nx += vars()[i][j].offset;
printLine(tv.name, cx, tv.format);
newLine();
cy++;
continue;
}
vars()[i][j].offset = (tv.name + ": ").length();
vars()[i][j].nx += vars()[i][j].offset;
printValue(tv.name + ": ", tv.format);
newLine();
cy++;
}
}
#ifdef WINDOWS
moveTo(0, my + 1);
#else
moveTo(0, my + 2);
#endif
if (!tabs[cur_tab].status.isEmpty()) {
printValue(tabs[cur_tab].status);
newLine();
}
status();
//fflush(0);
}
void PIConsole::status() {
Tab * ctab;
//clearLine();
for (uint i = 0; i < tabsCount(); ++i) {
ctab = &tabs[i];
if (ctab->key == 0) continue;
printValue(ctab->key, PIConsole::White | PIConsole::Bold);
printValue(ctab->name + " ", PIConsole::Cyan | PIConsole::Inverse);
printValue(" ");
}
newLine();
}
int PIConsole::bitsValue(void * src, int offset, int count) {
int ret = 0, stbyte = offset / 8, cbit = offset - stbyte * 8;
char cbyte = reinterpret_cast<char * >(src)[stbyte];
for (int i = 0; i < count; i++) {
ret |= ((cbyte >> cbit & 1) << i);
cbit++;
if (cbit == 8) {
cbit = 0;
stbyte++;
cbyte = reinterpret_cast<char * >(src)[stbyte];
}
}
return ret;
}
#define ADD_VAR_BODY tv.name = name; tv.bitFrom = tv.bitCount = 0; tv.format = format; checkColumn(column);
void PIConsole::addString(const PIString & name, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 0; tv.s = 0; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, PIString* ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 0; tv.s = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, bool * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 1; tv.b = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, int * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 2; tv.i = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, long * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 3; tv.l = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, char * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 4; tv.c = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, float * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 5; tv.f = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, double * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 6; tv.d = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, short * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 7; tv.sh = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, uint * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 8; tv.ui = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, ulong * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 9; tv.ul = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, ushort * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 10; tv.ush = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, uchar * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 11; tv.uc = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, llong * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 12; tv.ll = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, ullong * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 13; tv.ull = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addBitVariable(const PIString & name, void * ptr, int fromBit, int bitCount, int column, PIFlags<PIConsole::Format> format) {
tv.name = name; tv.bitFrom = fromBit; tv.bitCount = bitCount; tv.type = 14; tv.ptr = ptr; tv.format = format;
checkColumn(column); vars()[column - 1].push_back(tv);}
void PIConsole::addEmptyLine(int column, uint count) {
tv.name = ""; tv.type = 0; tv.d = 0; tv.format = Normal;
for (uint i = 0; i < count; ++i) {
checkColumn(column);
vars()[column - 1].push_back(tv);
}
}
PIString PIConsole::getString(int x, int y) {
bool run = isRunning();
if (run) PIThread::stop(true);
listener->setActive(false);
moveTo(x, y);
showCursor();
PIByteArray ba(4096);
int ret = scanf(" %s", ba.data());
listener->setActive(true);
if (run) start();
if (ret >= 1) return PIString(ba);
else return PIString();
}
PIString PIConsole::getString(const PIString & name) {
piForeachC (PIVector<Variable> & i, tabs[cur_tab].variables)
piForeachC (Variable & j, i)
if (j.name == name)
return getString(j.nx + 1, j.ny);
return PIString();
}
#define PRINT_VAR_BODY couts(fstr(format).stdString()); int ret = couts(value); couts(fstr(PIConsole::Dec).stdString()); return ret;
inline void PIConsole::printLine(const PIString & value, int dx, PIFlags<PIConsole::Format> format) {
int i = width - value.length() - dx;
#ifdef QNX
--i;
#endif
PIString ts = fstr(format);
couts(ts.stdString());
if (i >= 0) ts = value + PIString(i, ' ');
else ts = value.left(value.size() + i);
couts(ts.stdString());
couts(fstr(Dec).stdString());
}
inline int PIConsole::printValue(const PIString & value, PIFlags<PIConsole::Format> format) {
couts(fstr(format).stdString());
int ret = couts(value.stdString());
fstr(PIConsole::Dec);
return ret;
}
inline int PIConsole::printValue(const char * value, PIFlags<PIConsole::Format> format) {PRINT_VAR_BODY}
inline int PIConsole::printValue(const bool value, PIFlags<PIConsole::Format> format) {PRINT_VAR_BODY}
inline int PIConsole::printValue(const int value, PIFlags<PIConsole::Format> format) {PRINT_VAR_BODY}
inline int PIConsole::printValue(const long value, PIFlags<PIConsole::Format> format) {PRINT_VAR_BODY}
inline int PIConsole::printValue(const llong value, PIFlags<PIConsole::Format> format) {PRINT_VAR_BODY}
inline int PIConsole::printValue(const float value, PIFlags<PIConsole::Format> format) {PRINT_VAR_BODY}
inline int PIConsole::printValue(const double value, PIFlags<PIConsole::Format> format) {PRINT_VAR_BODY}
inline int PIConsole::printValue(const char value, PIFlags<PIConsole::Format> format) {PRINT_VAR_BODY}
inline int PIConsole::printValue(const short value, PIFlags<PIConsole::Format> format) {PRINT_VAR_BODY}
inline int PIConsole::printValue(const uchar value, PIFlags<PIConsole::Format> format) {PRINT_VAR_BODY}
inline int PIConsole::printValue(const ushort value, PIFlags<PIConsole::Format> format) {PRINT_VAR_BODY}
inline int PIConsole::printValue(const uint value, PIFlags<PIConsole::Format> format) {PRINT_VAR_BODY}
inline int PIConsole::printValue(const ulong value, PIFlags<PIConsole::Format> format) {PRINT_VAR_BODY}
inline int PIConsole::printValue(const ullong value, PIFlags<PIConsole::Format> format) {PRINT_VAR_BODY}