diff --git a/main_udp_filetransfer.cpp b/main_udp_filetransfer.cpp new file mode 100644 index 00000000..1a895669 --- /dev/null +++ b/main_udp_filetransfer.cpp @@ -0,0 +1,153 @@ +#include "pip.h" +#include "pifiletransfer.h" +#include "pidatatransfer.h" + +class Ob: public PIObject { + PIOBJECT(Ob) +public: + Ob() { + srand(PISystemTime::current().toMicroseconds()); + bytes_from = bytes_to = 0; + + sft.setName("sft"); + //sft.setDirectory(sft.directory().cd("..\\")); + //piCout << "Send File Transfer DIrectory" << sft.directory().absolutePath(); + CONNECTU(&sft, sendRequest, this, ssend); + + rft.setName("rft"); + //rft.setDirectory(rft.directory().cd("..\\1")); + //piCout << "Receive File Transfer DIrectory" << rft.directory().absolutePath(); + CONNECTU(&rft, sendRequest, this, rsend); + } + + void startsend() { +// PIDir dir = PIDir::current(); +// dir.cd("..\\"); +// piCout << dir.absolutePath(); +// PIVector des = dir.allEntries(); +// piCout << "all entries" << des.size(); +// PIFile::FileInfo sde; +// piForeachC(PIFile::FileInfo de, des) { +// piCout << (de.isDir() ? "dir:" : "file") << de.name << de.size; +// if (de.name() == "0") sde = de; +// } +// sft.setPacketSize(64096); +// sft.send(sde); + PIByteArray ba; + ba.resize(65536); + for (int i=0; i 80) {data.remove(data.size()/2, 1);} +// if(rand()%100 > 70) {data[data.size()-6] = 1;} +// if(rand()%100 < 90) + rft.received(data); + } + + EVENT_HANDLER1(void, rsend, PIByteArray &, data) { + bytes_from += data.size(); + piCout << "[receiver]" << rft.stateString() << ". datasize =" << data.size() + << "(" << PIString::readableSize(rft.bytesCur()) << "/" << PIString::readableSize(rft.bytesAll()) << ")" + << "(" << PIString::readableSize(bytes_to) << "/" << PIString::readableSize(bytes_from) << ")"; +// if(rand()%100 > 80) {data.remove(data.size()/2, 1);} +// if(rand()%100 > 70) {data[data.size()-6] = 1;} +// if(rand()%100 < 90) + sft.received(data); + } + + PIDataTransfer sft; + PIDataTransfer rft; + ullong bytes_to, bytes_from; +}; + + +class UDPFileTransfer: public PITimer { + PIOBJECT_SUBCLASS(UDPFileTransfer, PITimer) +public: + UDPFileTransfer(const PIString &src_ip_port, const PIString &dst_ip_port) { + eth.setReadAddress(src_ip_port); + eth.setSendAddress(dst_ip_port); + //ft.setPacketSize(65000); + CONNECTU(&ft, sendRequest, this, ftsend); + CONNECTU(&ft, sendFilesStarted, this, ftevent); + CONNECTU(&ft, receiveFilesStarted, this, ftevent); + CONNECTU(&ft, sendFilesFinished, this, ftevent); + CONNECTU(&ft, receiveFilesFinished, this, ftevent); + CONNECTU(ð, threadedReadEvent, this, received); + start(50); + eth.open(); + eth.startThreadedRead(); + } + + void startSend(const PIString &file) { + ft.send(file); + } + + PIFileTransfer ft; + +private: + PIEthernet eth; + + void tick(void *, int) { + if (ft.isSending() || ft.isReceiving()) ftevent(); + } + + EVENT_HANDLER(void, ftevent) { + piCout << ft.stateString() + << "(" << PIString::readableSize(ft.bytesFileCur()) << "/" << PIString::readableSize(ft.bytesFileAll()) << ", " + << PIString::readableSize(ft.bytesCur()) << "/" << PIString::readableSize(ft.bytesAll()) << ")"; + } + + EVENT_HANDLER1(void, ftsend, PIByteArray &, data) { + eth.send(data); + } + + EVENT_HANDLER2(void, received, uchar * , readed, int, size) { + PIByteArray ba(readed, size); + ft.received(ba); + } +}; + +int main (int argc, char * argv[]) { +// Ob o; +// PITimeMeasurer tm; +// o.startsend(); +// piCout << tm.elapsed_s(); +// return 0; + if (!(argc == 3 || argc == 4)) { + piCout << "UDPFileTransfer"; + piCout << "USE: piptest [src_ip_port] [dst_ip_port] {filename}"; + return 0; + } + PIKbdListener kbd; + kbd.enableExitCapture(); + PIString src = argv[1]; + PIString dst = argv[2]; + UDPFileTransfer f(src, dst); + piCout << "work directory" << f.ft.directory().absolutePath() << ", listen on" << src << ",send to" << dst; + if (argc == 4) { + PIString file = argv[3]; + piCout << "send file" << file; + f.startSend(file); + return 0; + } else { + piCout << "wait for receiving"; + } + WAIT_FOR_EXIT + return 0; + +} + diff --git a/src/io/pibasetransfer.cpp b/src/io/pibasetransfer.cpp new file mode 100644 index 00000000..a2479abb --- /dev/null +++ b/src/io/pibasetransfer.cpp @@ -0,0 +1,361 @@ +#include "pibasetransfer.h" + +const uint PIBaseTransfer::signature = 0x54444950; + +PIBaseTransfer::PIBaseTransfer(): crc(standardCRC_16()) { + header.sig = signature; + header.session_id = 0; + packet_header_size = sizeof(PacketHeader) + customHeader().size(); + part_header_size = sizeof(Part) + sizeof(int); + is_sending = is_receiving = false; + break_ = true; + bytes_all = bytes_cur = 0; + timeout_ = 1.; + setPacketSize(4096); + srand(PISystemTime::current().toMilliseconds()); +} + + +PIBaseTransfer::~PIBaseTransfer() { + break_ = true; + session.clear(); + replies.clear(); +} + + +void PIBaseTransfer::stopSend() { + if (!is_sending) return; + break_ = true; +} + + +void PIBaseTransfer::stopReceive() { + if (!is_receiving) return; + break_ = true; + finish_receive(false); +} + + +void PIBaseTransfer::received(PIByteArray& data) { + packet_header_size = sizeof(PacketHeader) + customHeader().size(); +// piCoutObj << "r" << data.size() << sizeof(PacketHeader); + if (data.size() < sizeof(PacketHeader)) return; + PacketHeader h; + data >> h; + PacketType pt = (PacketType)h.type; +// piCoutObj << "receive" << h.session_id << h.type << h.id; + switch (pt) { + case pt_Unknown: + break; + case pt_Data: + if (h.session_id != header.session_id || !is_receiving) { + sendBreak(h.session_id); + return; + } else { + uint rcrc = h.crc; + uint ccrc = crc.calculate(data.data(), data.size_s()); + if (rcrc != ccrc) { + header.id = h.id; + sendReply(pt_ReplyInvalid); + piCoutObj << "invalid CRC"; + } else { + processData(h.id, data); + } + } + break; + case pt_ReplySuccess: + case pt_ReplyInvalid: + if (h.session_id != header.session_id) return; + if (is_sending) { + if (h.id >= 0 && h.id < replies.size()) + replies[h.id] = pt; + } + if (is_receiving && h.id == 0) { + if (checkSession() == 0 && pt == pt_ReplySuccess) finish_receive(true); + } + break; + case pt_Break: + break_ = true; +// piCoutObj << "BREAK"; + if (is_receiving) { + stopReceive(); + return; + } + if (is_sending) { + stopSend(); + return; + } + break; + case pt_Start: + if (is_sending) { + sendBreak(h.session_id); + return; + } + if (header.session_id != h.session_id && is_receiving) { + sendBreak(h.session_id); + return; + } + if (data.size() == sizeof(StartRequest)) { + StartRequest sr; + data >> sr; + bytes_cur = 0; + state_string = "start request"; + bytes_all = sr.size; + header.session_id = h.session_id; + header.id = 0; + session.clear(); + replies.clear(); + session.resize(sr.packets); + replies.resize(sr.packets + 1); + replies.fill(pt_Unknown); + is_receiving = true; + break_ = false; + receiveStarted(); + state_string = "receiving"; + replies[0] = pt_ReplySuccess; + sendReply(pt_ReplySuccess); + } + break; + default: + break; + } +} + + +bool PIBaseTransfer::send_process() { + packet_header_size = sizeof(PacketHeader) + customHeader().size(); + break_ = false; + is_sending = true; + sendStarted(); + replies.resize(session.size() + 1); + replies.fill(pt_Unknown); + PIByteArray ba; + if (!getStartRequest()) return finish_send(false); + state_string = "sending"; + for (int i = 0; i < session.size_s(); i++) { + ba = build_packet(i); + sendRequest(ba); + if (break_) return finish_send(false); + } + PITimeMeasurer tm; + int prev_chk = 0; + while (tm.elapsed_s() < timeout_) { + int chk = checkSession(); + if (chk != prev_chk) tm.reset(); + if (chk == 0) return finish_send(true); + if (chk > 0) { +// piCoutObj << "recovery packet" << chk; + piMSleep(1); + ba = build_packet(chk - 1); + sendRequest(ba); + } +// if (chk == -1) return finish_send(false); + if (break_) return finish_send(false); + prev_chk = chk; + piMSleep(1); + } + return finish_send(false); +} + + +int PIBaseTransfer::checkSession() { + int miss = 0; + for (int i = 1; i < replies.size_s(); i++) { + if (replies[i] != pt_ReplySuccess) miss++; + if (replies[i] == pt_ReplyInvalid) return i; + } + for (int i = 1; i < replies.size_s(); i++) { + if (replies[i] != pt_ReplySuccess) return i; + } + if (miss > 0) { + piCoutObj << "missing" << miss << "packets"; + return -miss; + } else return 0; +} + + +void PIBaseTransfer::buildSession(PIVector parts) { + state_string = "calculating files... "; + session.clear(); + header.session_id = rand(); + bytes_all = 0; + Part fi; + int fi_index, fi_prts; + PIVector lfi; + int min_size = packet_header_size + part_header_size; + int cur_size = min_size; + for (int i = 0; i < parts.size_s(); i++) { + state_string = "calculating files... " + PIString::fromNumber(i) + " of " + PIString::fromNumber(parts.size()); + fi.id = parts[i].id; +// piCout << fi.id << state_string; + bytes_all += parts[i].size; +// fi.size = fi.entry.size; + fi.start = 0; + int rest = parts[i].size - (packet_size - cur_size); +// piCout << i << fi.size << rest << bytes_all; + if (rest <= 0) { + fi.size = parts[i].size; + lfi << fi; + cur_size += fi.size + part_header_size; + } else { + fi.size = parts[i].size - rest; + fi_index = 1; + fi_prts = 1 + 1 + piMaxi(1, rest / (packet_size - min_size)); +// piCout << fi_prts; + lfi << fi; + session << lfi; + lfi.clear(); + cur_size = min_size; + llong fs = fi.size; + for (int j = 1; j < fi_prts; j++) { + fi_index++; + fi.start = fs; + fi.size = piMin(parts[i].size - fs, packet_size - min_size); + lfi << fi; + cur_size += fi.size + part_header_size; + if (fi_index != fi_prts) { + session << lfi; + lfi.clear(); + cur_size = min_size; + fs += fi.size; + } + } + } + if (packet_size - cur_size < min_size) { + session << lfi; + lfi.clear(); + cur_size = min_size; + } + } + if (cur_size > min_size) session << lfi; +} + + +void PIBaseTransfer::sendBreak(int session_id) { + uint psid = header.session_id; + header.session_id = session_id; + sendReply(pt_Break); + header.session_id = psid; +} + + +void PIBaseTransfer::sendReply(PacketType reply) { + header.type = reply; + PIByteArray ba; + ba << header; + sendRequest(ba); +} + + +bool PIBaseTransfer::getStartRequest() { + PITimeMeasurer tm; + header.type = pt_Start; + header.id = 0; + PIByteArray ba; + StartRequest st; + st.packets = (uint)session.size(); + st.size = bytes_all; + ba << header; + ba << st; + state_string = "send request"; + for (int i = 0; i < 5; i++) { + tm.reset(); + sendRequest(ba); + while (tm.elapsed_s() < timeout_) { + if (break_) return false; + //piCoutObj << send_replyes[0]; + if (replies[0] == pt_ReplySuccess) { + state_string = "send permited!"; + return true; + } + piMSleep(10); + } + } + return false; +} + + +void PIBaseTransfer::processData(int id, PIByteArray & data) { +// piCoutObj << "received packet" << id << ", size" << data.size(); + if (id < 1 || id > replies.size_s()) return; + if (!session[id - 1].isEmpty()) { + header.id = id; + replies[id] = pt_ReplySuccess; + sendReply(pt_ReplySuccess); + if (checkSession() == 0) state_string = "receive ok"; + return; + } + Part fi; + PIByteArray ba, pheader; + pheader.resize(packet_header_size - sizeof(PacketHeader)); + if (!pheader.isEmpty()) { + memcpy(pheader.data(), data.data(), pheader.size()); + data.remove(0, pheader.size_s()); + } + while (!data.isEmpty()) { + ba.clear(); + data >> fi; + /*if (fi.size > 0) */data >> ba; +// fi.fsize = ba.size(); + bytes_cur += fi.size; +// piCoutObj << "recv" << fi; + session[id - 1] << fi; + state_string = "receiving..."; + receivePart(fi, ba, pheader); + } + header.id = id; + replies[id] = pt_ReplySuccess; + if (checkSession() == 0) state_string = "receive ok"; + sendReply(pt_ReplySuccess); +} + + +PIByteArray PIBaseTransfer::build_packet(int id) { + PIByteArray ret; + PIByteArray ba; + header.id = id + 1; + header.type = pt_Data; +// piCoutObj << "Packet" << header.id; +// piCoutObj << "session id" << header.session_id; + //ret << header; + ret.append(customHeader()); + for (int i = 0; i < session[id].size_s(); i++) { + Part fi = session[id][i]; + ret << fi; +// piCout << "biuld" << fi; + ba = buildPacket(fi); + bytes_cur += ba.size(); + if (ba.size() != fi.size) piCoutObj << "***error while build packet, wrong part size"; + ret << ba; + } + header.crc = crc.calculate(ret); + PIByteArray hdr; hdr << header; + ret.insert(0, hdr); + return ret; +} + + +bool PIBaseTransfer::finish_send(bool ok) { + if (ok) state_string = "send done"; + else state_string = "send failed"; +// piCoutObj << state_string << PIString::readableSize(bytes_all); + is_sending = false; + header.id = 0; + if (!ok) sendBreak(header.session_id); + else sendReply(pt_ReplySuccess); + sendFinished(ok); + bytes_all = bytes_cur = 0; + return ok; +} + + +void PIBaseTransfer::finish_receive(bool ok) { + if (ok) state_string = "receive done"; + else state_string = "receive failed"; +// piCoutObj << state_string << PIString::readableSize(bytes_all); + is_receiving = false; + if (!ok) sendBreak(header.session_id); + receiveFinished(ok); + bytes_all = bytes_cur = 0; +} + diff --git a/src/io/pibasetransfer.h b/src/io/pibasetransfer.h new file mode 100644 index 00000000..acef8f9f --- /dev/null +++ b/src/io/pibasetransfer.h @@ -0,0 +1,114 @@ +#ifndef PIBASETRANSFER_H +#define PIBASETRANSFER_H + +#include "picrc.h" +#include "pitimer.h" + +class PIBaseTransfer : public PIObject +{ + PIOBJECT(PIBaseTransfer) +public: + PIBaseTransfer(); + ~PIBaseTransfer(); + +# pragma pack(push,1) + struct PacketHeader { + uint sig; + int type; // PacketType + int session_id; + uint id; + uint crc; + bool check_sig() {return (sig == signature);} + }; + + struct Part { + Part(uint id_ = 0, ullong size_ = 0, ullong start_ = 0) : id(id_), size(size_), start(start_) {} + uint id; + ullong size; + ullong start; + }; +# pragma pack(pop) + + void stopSend(); + void stopReceive(); + + bool isSending() const {return is_sending;} + bool isReceiving() const {return is_receiving;} + + void setPacketSize(int size) {packet_size = size;} + int packetSize() const {return packet_size;} + + void setTimeout(double sec) {timeout_ = sec;} + double timeout() const {return timeout_;} + + const PIString & stateString() const {return state_string;} + llong bytesAll() const {return bytes_all;} + llong bytesCur() const {return bytes_cur;} + const PIString * stateString_ptr() const {return &state_string;} + const llong * bytesAll_ptr() const {return &bytes_all;} + const llong * bytesCur_ptr() const {return &bytes_cur;} + + EVENT(receiveStarted) + EVENT1(receiveFinished, bool, ok) + EVENT(sendStarted) + EVENT1(sendFinished, bool, ok) + EVENT1(sendRequest, PIByteArray &, data) + EVENT_HANDLER1(void, received, PIByteArray &, data); + +protected: + uint packet_header_size, part_header_size; + bool break_, is_sending, is_receiving; + PIString state_string; + llong bytes_all, bytes_cur; + + void buildSession(PIVector parts); + virtual PIByteArray buildPacket(Part fi) = 0; + virtual void receivePart(Part fi, PIByteArray ba, PIByteArray pheader) = 0; + virtual PIByteArray customHeader() {return PIByteArray();} + bool send_process(); + +private: + + enum PacketType {pt_Unknown, pt_Data, pt_ReplySuccess, pt_ReplyInvalid, pt_Break, pt_Start}; + +# pragma pack(push,1) + struct StartRequest { + uint packets; + ullong size; + }; +# pragma pack(pop) + + friend PIByteArray & operator >>(PIByteArray & s, PIBaseTransfer::StartRequest & v); + friend PIByteArray & operator <<(PIByteArray & s, const PIBaseTransfer::StartRequest & v); + + static const uint signature; + int packet_size; + double timeout_; + PIVector > session; + PIVector replies; + PacketHeader header; + CRC_16 crc; + + void processData(int id, PIByteArray &data); + PIByteArray build_packet(int id); + int checkSession(); + void sendBreak(int session_id); + void sendReply(PacketType reply); + bool getStartRequest(); + bool finish_send(bool ok); + void finish_receive(bool ok); +}; + +inline PIByteArray & operator <<(PIByteArray & s, const PIBaseTransfer::PacketHeader & v) {s << v.sig << v.type << v.session_id << v.id << v.crc; return s;} +inline PIByteArray & operator >>(PIByteArray & s, PIBaseTransfer::PacketHeader & v) {s >> v.sig >> v.type >> v.session_id >> v.id >> v.crc; return s;} + +inline PIByteArray & operator <<(PIByteArray & s, const PIBaseTransfer::Part & v) {s << v.id << v.size << v.start; return s;} +inline PIByteArray & operator >>(PIByteArray & s, PIBaseTransfer::Part & v) {s >> v.id >> v.size >> v.start; return s;} + +inline PIByteArray & operator <<(PIByteArray & s, const PIBaseTransfer::StartRequest & v) {s << v.packets << v.size; return s;} +inline PIByteArray & operator >>(PIByteArray & s, PIBaseTransfer::StartRequest & v) {s >> v.packets >> v.size; return s;} + +inline PICout operator <<(PICout s, const PIBaseTransfer::Part & v) {s.setControl(0, true); s << "Part(\"" << v.id << "\", " << PIString::readableSize(v.start) << " b | " << PIString::readableSize(v.size) << " b)"; s.restoreControl(); return s;} + + +#endif // PIBASETRANSFER_H diff --git a/src/system/piconsole.cpp b/src/system/piconsole.cpp deleted file mode 100755 index ccf79ac7..00000000 --- a/src/system/piconsole.cpp +++ /dev/null @@ -1,1064 +0,0 @@ -/* - PIP - Platform Independent Primitives - Console output/input - Copyright (C) 2014 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 . -*/ - -#include "piconsole.h" -#include "pipeer.h" - - -/** \class PIConsole - * \brief Console output class - * \details - * \section PIConsole_sec0 Synopsis - * This class provides output to console with automatic alignment and update. - * It supports tabs, keyboard listening, formats and colors. - * - * \section PIConsole_sec1 Layout - * %PIConsole works with variable pointers. You should add your variables with - * functions \a addVariable() which receives label name, pointer to variable - * and optional column and format. Columns count is dynamically increased if - * new column used. E.g. if you add variable to empty tab to column 3, columns - * count will be increased to 3, but two firsts columns will be empty. Each column - * filled from top to bottom, but you can add just string with function - * \a addString() or add empty line with function \a addEmptyLine(). Layout scheme: - * \image html piconsole_layout.png - * - * \section PIConsole_sec2 Keyboard usage - * %PIConsole should to be single in application. %PIConsole aggregate PIKbdListener - * which grab keyboard and automatic switch tabs by theirs bind keys. If there is no - * tab binded to pressed key external function "slot" will be called - * - **/ - - -extern PIMutex __PICout_mutex__; - - -PIConsole::PIConsole(bool startNow, KBFunc slot): PIThread() { - setName("console"); - setPriority(piLow); - needLockRun(true); - ret_func = slot; - num_format = systime_format = 0; - vid = 0; - cur_tab = width = height = pwidth = pheight = max_y = 0; - def_align = Nothing; - tabs.reserve(16); -#ifdef WINDOWS - ulcoord.X = 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; - ulcoord.Y = sbi.srWindow.Top; - GetConsoleMode(hOut, &smode); - GetConsoleCursorInfo(hOut, &curinfo); -#else - winsize ws; - ioctl(0, TIOCGWINSZ, &ws); - width = ws.ws_col; - height = ws.ws_row; -#endif - tabs.reserve(16); - addTab("main"); - listener = new PIKbdListener(key_event, this); - peer = 0; - server_mode = pause_ = false; - state = Disconnected; - peer_timer.addDelimiter(20); - peer_timer.setName("__S__PIConsole::peer_timer"); - CONNECT2(void, void * , int, &peer_timer, tickEvent, this, peerTimer); - if (startNow) start(); -} - - -PIConsole::~PIConsole() { - stopPeer(); - 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) { - if (isRunning()) lock(); - tabs.push_back(Tab(name, bind_key)); - cur_tab = tabs.size() - 1; - if (isRunning()) unlock(); - return tabs.size(); -} - - -void PIConsole::removeTab(uint index) { - if (index >= tabs.size()) return; - if (isRunning()) lock(); - tabs.remove(index); - if (cur_tab >= tabs.size()) cur_tab = tabs.size() - 1; - if (isRunning()) unlock(); -} - - -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); -} - - -void PIConsole::clearTab(uint index) { - if (index >= tabs.size()) return; - lock(); - tabs[index].columns.clear(); - if (cur_tab == index) { - clearScreen(); - fillLabels(); - } - if (cur_tab >= tabs.size()) cur_tab = tabs.size() - 1; - unlock(); -} - - -void PIConsole::clearTab(const PIString & name) { - uint index = tabs.size() + 1; - for (uint i = 0; i < tabs.size(); ++i) { - if (tabs[i].name == name) { - index = i; - break; - } - } - clearTab(index); -} - - -void PIConsole::update() { - lock(); - fillLabels(); - unlock(); -} - - -bool PIConsole::setTab(uint index) { - if (index >= tabs.size()) - return false; - if (!isRunning()) { - cur_tab = index; - return true; - } - lock(); - __PICout_mutex__.lock(); - cur_tab = index; - clearScreen(); - fillLabels(); - __PICout_mutex__.unlock(); - 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; - int ct = p->cur_tab; - if (key == char(PIKbdListener::LeftArrow)) { - do { - ct--; - if (ct < 0) return; - } while (p->tabs[ct].key == 0); - p->setTab(ct); - return; - } - if (key == char(PIKbdListener::RightArrow)) { - do { - ct++; - if (ct >= p->tabs.size_s()) return; - } while (p->tabs[ct].key == 0); - p->setTab(ct); - return; - } - 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); - p->keyPressed(key, t); -} - - -void PIConsole::clearVariables(bool clearScreen) { - if (isRunning()) lock(); - if (clearScreen && isRunning()) { - toUpperLeft(); - clearScreenLower(); - } - columns().clear(); - if (isRunning()) unlock(); -} - - -void PIConsole::stop(bool clear) { - PIThread::stop(true); - if (clear) clearScreen(); - moveTo(0, max_y + 4); - showCursor(); - couts(fstr(Normal)); -#ifdef WINDOWS - SetConsoleMode(hOut, smode); - SetConsoleTextAttribute(hOut, dattr); -#endif - fflush(0); -} - - -PIString PIConsole::fstr(FormatFlags f) { - num_format = systime_format = 0; - if (f[PIConsole::Dec]) num_format = 0; - if (f[PIConsole::Hex]) num_format = 1; - if (f[PIConsole::Oct]) num_format = 2; - if (f[PIConsole::Bin]) num_format = 4; - if (f[PIConsole::Scientific]) num_format = 3; - if (f[PIConsole::SystemTimeSplit]) systime_format = 0; - if (f[PIConsole::SystemTimeSeconds]) systime_format = 1; - -#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); - if ((attr & BACKGROUND_RED) + (attr & BACKGROUND_GREEN) + (attr & BACKGROUND_BLUE) == 0) - 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 ((attr & FOREGROUND_RED) + (attr & FOREGROUND_GREEN) + (attr & FOREGROUND_BLUE) == 0) - attr |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; - } - if (f[PIConsole::Bold]) attr |= FOREGROUND_INTENSITY; - if (f[PIConsole::Underline]) attr |= COMMON_LVB_UNDERSCORE; - - 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 -} - - -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) { - switch (num_format) {case (1): return printf("0x%.4hX", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 2)); break; default: return printf("%hd", v); break;} -} -inline int PIConsole::couts(const int v) { - switch (num_format) {case (1): return printf("0x%.8X", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 4)); break; default: return printf("%d", v); break;} -} -inline int PIConsole::couts(const long v) { - switch (num_format) {case (1): return printf("0x%.16lX", v); break; case (2): return printf("%lo", v); break; case (4): return printf("%s", toBin(&v, sizeof(v))); break; default: return printf("%ld", v); break;} -} -inline int PIConsole::couts(const llong v) { - switch (num_format) {case (1): return printf("0x%.16llX", v); break; case (2): return printf("%llo", v); break; case (4): return printf("%s", toBin(&v, sizeof(v))); break; default: return printf("%lld", v); break;} -} -inline int PIConsole::couts(const uchar v) { - switch (num_format) {case (1): return printf("0x%.2X", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 1)); break; default: return printf("%u", v); break;} -} -inline int PIConsole::couts(const ushort v) { - switch (num_format) {case (1): return printf("0x%.4hX", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 2)); break; default: return printf("%hu", v); break;} -} -inline int PIConsole::couts(const uint v) { - switch (num_format) {case (1): return printf("0x%.8X", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 4)); break; default: return printf("%u", v); break;} -} -inline int PIConsole::couts(const ulong v) { - switch (num_format) {case (1): return printf("0x%.16lX", v); break; case (2): return printf("%lo", v); break; case (4): return printf("%s", toBin(&v, sizeof(v))); break; default: return printf("%lu", v); break;} -} -inline int PIConsole::couts(const ullong v) { - switch (num_format) {case (1): return printf("0x%.16llX", v); break; case (2): return printf("%llo", v); break; case (4): return printf("%s", toBin(&v, sizeof(v))); break; default: return printf("%llu", v); break;} -} -inline int PIConsole::couts(const float v) { - switch (num_format) {case (3): return printf("%e", v); break; default: return printf("%.5g", v); break;} -} -inline int PIConsole::couts(const double v) { - switch (num_format) {case (3): return printf("%le", v); break; default: return printf("%.5lg", v); break;} -} -inline int PIConsole::couts(const PISystemTime & v) { - switch (systime_format) {case (1): return printf("%.6lg", v.toSeconds()); break; - default: return couts(v.seconds) + printf(" s, ") + couts(v.nanoseconds) + printf(" ns"); break;} -} - - -void PIConsole::begin() { -#ifdef WINDOWS - SetConsoleMode(hOut, ENABLE_WRAP_AT_EOL_OUTPUT); -#endif - max_y = 0; - __PICout_mutex__.lock(); - clearScreen(); - hideCursor(); - fillLabels(); - __PICout_mutex__.unlock(); -} - - -void PIConsole::run() { - if (pause_) return; - uint cx, clen = 0; - int j; -#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 - //fflush(0); return; - __PICout_mutex__.lock(); - if (pwidth != width || pheight != height) { - clearScreen(); - fillLabels(); - } - pwidth = width; - pheight = height; - col_cnt = columns().size(); - col_wid = (col_cnt > 0) ? width / col_cnt : width; - for (uint i = 0; i < col_cnt; ++i) { - PIVector & cvars(tabs[cur_tab].columns[i].variables); - cx = col_wid * i; - toUpperLeft(); - if (max_y < cvars.size()) max_y = cvars.size(); - j = 0; - piForeachC (Variable & tv, cvars) { - if (j > height - 3) continue; - j++; - moveRight(cx); - if (tv.type == 15) { - newLine(); - continue; - } - moveRight(tv.offset); - const void * ptr = 0; - if (tv.remote) { - if (tv.type == 0) { - rstr.clear(); - rba = tv.rdata; - rba >> rstr; - rstr.trim(); - ptr = &rstr; - } else - ptr = tv.rdata.data(); - } else - ptr = tv.ptr; - switch (tv.type) { - case 0: clen = printValue(ptr != 0 ? *(const PIString*)ptr : PIString(), tv.format); break; - case 1: clen = printValue(ptr != 0 ? *(const bool*)ptr : false, tv.format); break; - case 2: clen = printValue(ptr != 0 ? *(const int*)ptr : 0, tv.format); break; - case 3: clen = printValue(ptr != 0 ? *(const long*)ptr : 0l, tv.format); break; - case 4: clen = printValue(ptr != 0 ? *(const char*)ptr : char(0), tv.format); break; - case 5: clen = printValue(ptr != 0 ? *(const float*)ptr : 0.f, tv.format); break; - case 6: clen = printValue(ptr != 0 ? *(const double*)ptr : 0., tv.format); break; - case 7: clen = printValue(ptr != 0 ? *(const short*)ptr : short(0), tv.format); break; - case 8: clen = printValue(ptr != 0 ? *(const uint*)ptr : 0u, tv.format); break; - case 9: clen = printValue(ptr != 0 ? *(const ulong*)ptr : 0ul, tv.format); break; - case 10: clen = printValue(ptr != 0 ? *(const ushort*)ptr : ushort(0), tv.format); break; - case 11: clen = printValue(ptr != 0 ? *(const uchar*)ptr : uchar(0), tv.format); break; - case 12: clen = printValue(ptr != 0 ? *(const llong*)ptr : 0l, tv.format); break; - case 13: clen = printValue(ptr != 0 ? *(const ullong*)ptr: 0ull, tv.format); break; - case 20: clen = printValue(ptr != 0 ? *(const PISystemTime*)ptr: PISystemTime(), tv.format); break; - case 14: clen = printValue(bitsValue(ptr, tv.bitFrom, tv.bitCount), tv.format); break; - } - if (clen + tv.offset < (uint)col_wid) { - PIString ts = PIString( -#if defined(QNX) || defined(FREE_BSD) - col_wid - clen - tv.offset - 1, ' '); -#else - col_wid - clen - tv.offset, ' '); -#endif - printf("%s", ts.data()); - } - newLine(); - } - } -#ifdef WINDOWS - moveTo(0, max_y + 1); -#else - moveTo(0, max_y + 2); -#endif - fflush(0); - __PICout_mutex__.unlock(); -} - - -void PIConsole::fillLabels() { - if (!isRunning()) return; - uint cx, cy, mx = 0, dx; -#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 - max_y = 0; - col_cnt = columns().size(); - col_wid = (col_cnt > 0) ? width / col_cnt : width; - for (uint i = 0; i < col_cnt; ++i) { - Column & ccol(tabs[cur_tab].columns[i]); - PIVector & cvars(ccol.variables); - if (ccol.alignment != Nothing) { - mx = 0; - piForeachC (Variable & j, cvars) - if (!j.isEmpty()) - if (mx < j.name.size()) - mx = j.name.size(); - mx += 2; - } - cx = col_wid * i; - cy = 1; - toUpperLeft(); - for (uint j = 0; j < cvars.size(); ++j) { - if (int(j) > height - 3) continue; - if (max_y < j) max_y = j; - moveRight(cx); - Variable & tv(cvars[j]); - cvars[j].nx = cx; - cvars[j].ny = cy; - if (tv.name.isEmpty()) { - cvars[j].offset = 0; - clearLine(); - newLine(); - cy++; - continue; - } - clearLine(); - //piCout << tv.name << tv.type << tv.ptr; - if (tv.type == 15) { - cvars[j].offset = cvars[j].name.length(); - cvars[j].nx += cvars[j].offset; - printLine(tv.name, cx, tv.format); - newLine(); - cy++; - continue; - } - if (!tv.isEmpty()) { - switch (ccol.alignment) { - case Nothing: - cvars[j].offset = (tv.name + ": ").length(); - cvars[j].nx += cvars[j].offset; - printValue(tv.name + ": ", tv.format); - break; - case Left: - cvars[j].offset = mx; - cvars[j].nx += cvars[j].offset; - printValue(tv.name + ": ", tv.format); - break; - case Right: - cvars[j].offset = mx; - cvars[j].nx += cvars[j].offset; - dx = mx - (tv.name + ": ").length(); - moveRight(dx); - printValue(tv.name + ": ", tv.format); - moveLeft(dx); - break; - } - } - newLine(); - cy++; - } - } -#ifdef WINDOWS - moveTo(0, max_y + 1); -#else - moveTo(0, max_y + 2); -#endif - if (!tabs[cur_tab].status.isEmpty()) { - printValue(tabs[cur_tab].status); - newLine(); - } - status(); - //couts(fstr(Normal)); - //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); - if (i == cur_tab) - printValue(ctab->name + " ", PIConsole::BackYellow | PIConsole::Black); - else - printValue(ctab->name + " ", PIConsole::Cyan | PIConsole::Inverse); - printValue(" "); - } - newLine(); -} - - -int PIConsole::bitsValue(const void * src, int offset, int count) const { - int ret = 0, stbyte = offset / 8, cbit = offset - stbyte * 8; - char cbyte = reinterpret_cast(src)[stbyte]; - for (int i = 0; i < count; i++) { - ret |= ((cbyte >> cbit & 1) << i); - cbit++; - if (cbit == 8) { - cbit = 0; - stbyte++; - cbyte = reinterpret_cast(src)[stbyte]; - } - } - return ret; -} - - -const char * PIConsole::toBin(const void * d, int s) { - binstr.clear(); - uchar cc, b; - for (int i = 0; i < s; ++i) { - cc = ((const uchar *)d)[i]; - b = 1; - for (int j = 0; j < 8; ++j) { - binstr << (cc & b ? "1" : "0"); - b <<= 1; - } - if (i < s - 1) binstr << " "; - } - binstr.reverse(); - return binstr.data(); -} - - -#define ADD_VAR_BODY vid++; tv.id = vid; tv.name = name; tv.bitFrom = tv.bitCount = 0; tv.format = format; tv.remote = false; checkColumn(col); - -void PIConsole::addString(const PIString & name, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 15; tv.size = 0; tv.ptr = 0; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const PIString * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 0; tv.size = 0; tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const bool * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 1; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const int * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 2; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const long * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 3; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const char * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 4; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const float * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 5; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const double * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 6; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const short * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 7; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const uint * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 8; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const ulong * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 9; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const ushort * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 10; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const uchar * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 11; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const llong * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 12; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const ullong * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 13; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const PISystemTime * ptr, int col, FormatFlags format) { - ADD_VAR_BODY tv.type = 20; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -/** \brief Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - * \details This function add to column "column" next lines: - * * "protocol " - * * "Rec - receiverDeviceName": \a PIProtocol::receiverDeviceState - * * "Send - senderDeviceName": \a PIProtocol::senderDeviceState - * * "Received count": \a PIProtocol::receiveCount - * * "Invalid count": \a PIProtocol::wrongCount - * * "Missed count": \a PIProtocol::missedCount - * * "Sended count": \a PIProtocol::sendCount - * * "Immediate Frequency, Hz": \a PIProtocol::immediateFrequency - * * "Integral Frequency, Hz": \a PIProtocol::integralFrequency - * * "Receive speed": \a PIProtocol::receiveSpeed - * * "Send speed": \a PIProtocol::sendSpeed - * * "Receiver history size": \a PIProtocol::receiverHistorySize - * * "Sender history size": \a PIProtocol::senderHistorySize - * * "Disconnect Timeout, s": \a PIProtocol::disconnectTimeout - * * "Quality": \a PIProtocol::quality - * */ -void PIConsole::addVariable(const PIString & name, const PIProtocol * ptr, int col, FormatFlags format) { - addString("protocol " + name, col, format | PIConsole::Bold); - addVariable("Rec - " + ptr->receiverDeviceName(), ptr->receiverDeviceState_ptr(), col, format); - addVariable("Send - " + ptr->senderDeviceName(), ptr->senderDeviceState_ptr(), col, format); - addVariable("Received count", ptr->receiveCount_ptr(), col, format); - addVariable("Invalid count", ptr->wrongCount_ptr(), col, format); - addVariable("Missed count", ptr->missedCount_ptr(), col, format); - addVariable("Sended count", ptr->sendCount_ptr(), col, format); - addVariable("Immediate Frequency, Hz", ptr->immediateFrequency_ptr(), col, format); - addVariable("Integral Frequency, Hz", ptr->integralFrequency_ptr(), col, format); - addVariable("Receive speed", ptr->receiveSpeed_ptr(), col, format); - addVariable("Send speed", ptr->sendSpeed_ptr(), col, format); - addVariable("Receiver history size", ptr->receiverHistorySize_ptr(), col, format); - addVariable("Sender history size", ptr->senderHistorySize_ptr(), col, format); - addVariable("Disconnect Timeout, s", ptr->disconnectTimeout_ptr(), col, format); - addVariable("Quality", ptr->quality_ptr(), col, format); -} -/** \brief Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - * \details This function add to column "column" next lines: - * * " diagnostics" - * * "Received count": \a PIDiagnostics::receiveCount - * * "Invalid count": \a PIDiagnostics::wrongCount - * * "Sended count": \a PIDiagnostics::sendCount - * * "Immediate Frequency, Hz": \a PIDiagnostics::immediateFrequency - * * "Integral Frequency, Hz": \a PIDiagnostics::integralFrequency - * * "Receive speed": \a PIDiagnostics::receiveSpeed - * * "Send speed": \a PIDiagnostics::sendSpeed - * * "Quality": \a PIDiagnostics::quality - * */ -void PIConsole::addVariable(const PIString & name, const PIDiagnostics * ptr, int col, FormatFlags format) { - addString(name + " diagnostics", col, format | PIConsole::Bold); - addVariable("Received count", ptr->receiveCount_ptr(), col, format); - addVariable("Invalid count", ptr->wrongCount_ptr(), col, format); - addVariable("Sended count", ptr->sendCount_ptr(), col, format); - addVariable("Immediate Frequency, Hz", ptr->immediateFrequency_ptr(), col, format); - addVariable("Integral Frequency, Hz", ptr->integralFrequency_ptr(), col, format); - addVariable("Receive speed", ptr->receiveSpeed_ptr(), col, format); - addVariable("Send speed", ptr->sendSpeed_ptr(), col, format); - addVariable("Quality", ptr->quality_ptr(), col, format); -} -void PIConsole::addVariable(const PIString & name, const PISystemMonitor * ptr, int col, FormatFlags format) { - addString("monitor " + name, col, format | PIConsole::Bold); - addVariable("PID", &(ptr->statistic().ID), col, format); - //addVariable("state", &(ptr->statistic().state), col, format); - addVariable("threads", &(ptr->statistic().threads), col, format); - addVariable("priority", &(ptr->statistic().priority), col, format); - addVariable("memory physical", &(ptr->statistic().physical_memsize_readable), col, format); - addVariable("memory shared", &(ptr->statistic().share_memsize_readable), col, format); - addVariable("cpu load kernel", &(ptr->statistic().cpu_load_system), col, format); - addVariable("cpu load user", &(ptr->statistic().cpu_load_user), col, format); -} -void PIConsole::addBitVariable(const PIString & name, const void * ptr, int fromBit, int bitCount, int col, FormatFlags format) { - vid++; tv.id = vid; tv.size = sizeof(ullong); tv.name = name; tv.bitFrom = fromBit; tv.bitCount = bitCount; tv.type = 14; tv.ptr = ptr; tv.format = format; - checkColumn(col); column(col).push_back(tv);} -void PIConsole::addEmptyLine(int col, uint count) { - tv.id = 0; tv.size = 0; tv.name = ""; tv.type = 0; tv.ptr = 0; tv.format = Normal; - for (uint i = 0; i < count; ++i) { - checkColumn(col); - column(col).push_back(tv); - } -} - - -PIString PIConsole::getString(int x, int y) { - bool run = isRunning(); - if (run) PIThread::stop(true); - listener->setActive(false); - msleep(50); -#ifdef WINDOWS - moveTo(x - 1, y - 1); -#else - moveTo(x, y); -#endif - showCursor(); - PIByteArray ba(4096); -#ifdef CC_VC - int ret = scanf_s(" %s", ba.data()); -#else - int ret = scanf(" %s", ba.data()); -#endif - listener->setActive(true); - if (run) start(); - if (ret >= 1) return PIString(ba); - else return PIString(); -} - - -PIString PIConsole::getString(const PIString & name) { - piForeachC (Column & i, tabs[cur_tab].columns) - piForeachC (Variable & j, i.variables) - if (j.name == name) - return getString(j.nx + 1, j.ny); - return PIString(); -} - - -#define PRINT_VAR_BODY couts(fstr(format)); int ret = couts(value); couts(fstr(PIConsole::Dec)); return ret; - -inline void PIConsole::printLine(const PIString & value, int dx, FormatFlags format) { - int i = width - value.length() - dx; -#if defined(QNX) || defined(FREE_BSD) - --i; -#endif - PIString ts = fstr(format); - couts(ts); - if (i >= 0) ts = value + PIString(i, ' '); - else ts = value.left(value.size() + i); - couts(ts); - couts(fstr(Dec)); -} -inline int PIConsole::printValue(const PIString & value, FormatFlags format) { - couts(fstr(format)); - int ret = couts(value); - fstr(PIConsole::Dec); - return ret; -} -inline int PIConsole::printValue(const char * value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const bool value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const int value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const long value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const llong value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const float value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const double value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const char value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const short value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const uchar value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const ushort value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const uint value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const ulong value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const ullong value, FormatFlags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const PISystemTime & value, FormatFlags format) {PRINT_VAR_BODY} - - - -void PIConsole::startServer(const PIString & name) { - stopPeer(); - server_mode = true; - peer = new PIPeer("_rcs_:" + name); - CONNECT2(void, const PIString & , const PIByteArray &, peer, dataReceivedEvent, this, peerReceived); - CONNECT1(void, const PIString & , peer, peerDisconnectedEvent, this, peerDisconnectedEvent); - peer_timer.start(50.); - serverSendInfo(); -} - - -void PIConsole::stopPeer() { - remote_clients.clear(); - peer_timer.stop(); - if (peer != 0) delete peer; - peer = 0; - state = Disconnected; -} - - -PIStringList PIConsole::clients() const { - PIStringList sl; - if (peer == 0) return sl; - piForeachC (PIPeer::PeerInfo & i, peer->allPeers()) { - if (i.name.left(6) != "_rcc_:") continue; - sl << i.name.right(i.name.length() - 6); - } - return sl; -} - - -void PIConsole::listenServers() { - stopPeer(); - server_mode = false; - server_name.clear(); - srand(PISystemTime::current().nanoseconds); - peer = new PIPeer("_rcc_:" + PIDateTime::current().toString("hhmmssddMMyy_") + PIString::fromNumber(rand())); - CONNECT2(void, const PIString & , const PIByteArray &, peer, dataReceivedEvent, this, peerReceived); - peer_timer.start(100.); -} - - -PIStringList PIConsole::availableServers() const { - PIStringList sl; - if (peer == 0) return sl; - piForeachC (PIPeer::PeerInfo & i, peer->allPeers()) { - if (i.name.left(6) != "_rcs_:") continue; - sl << i.name.right(i.name.length() - 6); - } - return sl; -} - - -void PIConsole::connectToServer(const PIString & name) { - if (peer == 0) listenServers(); - server_name = name; -} - - -void PIConsole::disconnect() { - stopPeer(); -} - - -void PIConsole::serverSendInfo() { - if (peer == 0) return; - PIByteArray ba; - ba << int(0xAA); - peer->sendToAll(ba); -} - - -void PIConsole::serverSendData() { - if (peer == 0) return; - PIByteArray ba; - PIVector content; - piForeach (Tab & t, tabs) - piForeach (Column & c, t.columns) - piForeach (Variable & v, c.variables) - if (!v.isEmpty() && v.id > 0) { - VariableContent vc; - vc.id = v.id; - v.writeData(vc.rdata); - content << vc; - } - piForeach (RemoteClient & rc, remote_clients) { - ba.clear(); - switch (rc.state) { - case FetchingData: - ba << int(0xCC) << tabs; - //piCout << "server send const data" << rc.name << ba.size_s(); - break; - case Committing: - ba << int(0xDD); - break; - case Connected: - ba << int(0xEE) << content; - //piCout << "send data" << ba.size(); - break; - default: break; - } - if (!ba.isEmpty()) - peer->send(rc.name, ba); - } -} - - -PIConsole::RemoteClient & PIConsole::remoteClient(const PIString & fname) { - piForeach (RemoteClient & i, remote_clients) - if (i.name == fname) - return i; - remote_clients << RemoteClient(fname); - return remote_clients.back(); -} - - -void PIConsole::peerReceived(const PIString & from, const PIByteArray & data) { - int type; - PIByteArray ba(data); - ba >> type; - //piCout << "rec packet from" << from << "type" << PICoutManipulators::Hex << type; - if (server_mode) { - if (from.left(5) != "_rcc_") return; - //PIString rcn = from.right(from.length() - 6); - RemoteClient & rc(remoteClient(from)); - switch (type) { - case 0xBB: // fetch const data request - //piCout << "fetch data request from" << from << rc.state; - if (rc.state != Connected) - rc.state = FetchingData; - break; - case 0xCC: // const data commit - //piCout << "commit from" << from; - if (rc.state != Connected) - rc.state = Connected; - break; - default: break; - } - } else { - PIVector content; - PIMap vids; - if (from.left(5) != "_rcs_") return; - //PIString rcn = from.right(from.length() - 6); - switch (type) { - case 0xAA: // new server - //piCout << "new server" << rcn; - break; - case 0xCC: // const data - //piCout << "received const data"; - state = Committing; - ba >> tabs; - cur_tab = tabs.isEmpty() ? -1 : 0; - piForeach (Tab & t, tabs) - piForeach (Column & c, t.columns) - piForeach (Variable & v, c.variables) - v.remote = true; - break; - case 0xDD: // const data commit - //piCout << "received commit"; - state = Connected; - break; - case 0xEE: // dynamic data - //piCout << "received data" << ba.size_s(); - piForeach (Tab & t, tabs) - piForeach (Column & c, t.columns) - piForeach (Variable & v, c.variables) - if (!v.isEmpty() && v.id > 0) - vids[v.id] = &v; - ba >> content; - piForeach (VariableContent & vc, content) { - if (vc.id <= 0) continue; - Variable * v = vids.at(vc.id); - if (v == 0) continue; - //piCout << "read" << v->name << vc.rdata.size_s(); - v->rdata = vc.rdata; - } - break; - default: break; - } - } -} - - -void PIConsole::peerTimer(void * data, int delim) { - if (peer == 0) return; - //piCout << "timer" << delim; - if (server_mode) { - if (delim == 20) - serverSendInfo(); - else - serverSendData(); - } else { - if (delim != 1 || server_name.isEmpty()) return; - const PIPeer::PeerInfo * p = peer->getPeerByName("_rcs_:" + server_name); - if (p == 0) return; - PIByteArray ba; - switch (state) { - case Disconnected: - peer_tm.reset(); - ba << int(0xBB); - //piCout << "send to" << server_name << "fetch request disc"; - peer->send(p, ba); - state = FetchingData; - break; - case FetchingData: - if (peer_tm.elapsed_s() < 3.) - return; - peer_tm.reset(); - ba << int(0xBB); - //piCout << "send to" << server_name << "fetch request fd"; - peer->send(p, ba); - break; - case Committing: - peer_tm.reset(); - ba << int(0xCC); - //piCout << "send to" << server_name << "committing"; - state = Connected; - peer->send(p, ba); - break; - default: break; - }; - } -} - - -void PIConsole::peerDisconnectedEvent(const PIString & name) { - for (int i = 0; i < remote_clients.size_s(); ++i) - if (remote_clients[i].name == name) { - remote_clients.remove(i); - --i; - } -} diff --git a/src/system/piconsole.h b/src/system/piconsole.h deleted file mode 100755 index fa9d2fbe..00000000 --- a/src/system/piconsole.h +++ /dev/null @@ -1,508 +0,0 @@ -/*! \file piconsole.h - * \brief Console output class -*/ -/* - PIP - Platform Independent Primitives - Console output/input - Copyright (C) 2014 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 . -*/ - -#ifndef PICONSOLE_H -#define PICONSOLE_H - -#include "pikbdlistener.h" -#include "piprotocol.h" -#include "pidiagnostics.h" -#include "pisystemmonitor.h" -#ifndef WINDOWS -# include -# include -#else -# define COMMON_LVB_UNDERSCORE 0x8000 -#endif - -class PIPeer; - -class PIP_EXPORT PIConsole: public PIThread -{ - PIOBJECT_SUBCLASS(PIConsole, PIThread) -public: - - //! Constructs %PIConsole with key handler "slot" and if "startNow" start it - PIConsole(bool startNow = true, KBFunc slot = 0); - - ~PIConsole(); - - - //! Variables output format - enum Format { - Normal /** Default console format */ = 0x01, - Bold /** Bold text */ = 0x02, - Faint = 0x04, - Italic = 0x08, - Underline /** Underlined text */ = 0x10, - Blink /** Blinked text */ = 0x20, - Inverse /** Swap text and background colors */ = 0x40, - Black /** Black text */ = 0x100, - Red /** Red text */ = 0x200, - Green /** Green text */ = 0x400, - Yellow /** Yellow text */ = 0x800, - Blue /** Blue text */ = 0x1000, - Magenta /** Magenta text */ = 0x2000, - Cyan /** Cyan text */ = 0x4000, - White /** White text */ = 0x8000, - BackBlack /** Black background */ = 0x10000, - BackRed /** Red background */ = 0x20000, - BackGreen /** Green background */ = 0x40000, - BackYellow /** Yellow background */ = 0x80000, - BackBlue /** Blue background */ = 0x100000, - BackMagenta /** Magenta background */ = 0x200000, - BackCyan /** Cyan background */ = 0x400000, - BackWhite /** White background */ = 0x800000, - Dec /** Decimal base for integers */ = 0x1000000, - Hex /** Hexadecimal base for integers */ = 0x2000000, - Oct /** Octal base for integers */ = 0x4000000, - Bin /** Binary base for integers */ = 0x8000000, - Scientific /** Scientific representation of floats */ = 0x10000000, - SystemTimeSplit /** PISystemTime split representation (* s, * ns) */ = 0x20000000, - SystemTimeSeconds /** PISystemTime seconds representation (*.* s) */ = 0x40000000 - }; - - //! Column labels alignment - enum Alignment { - Nothing /** No alignment */ , - Left /** Labels align left and variables align left */ , - Right /** Labels align right and variables align left */ - }; - - typedef PIFlags FormatFlags; - - //! Add to current tab to column "column" string "name" with format "format" - void addString(const PIString & name, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const PIString * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const char * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const bool * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const short * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const int * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const long * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const llong * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const uchar * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const ushort * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const uint * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const ulong * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const ullong * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const float * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const double * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const PISystemTime * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - void addVariable(const PIString & name, const PIProtocol * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - void addVariable(const PIString & name, const PIDiagnostics * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - void addVariable(const PIString & name, const PISystemMonitor * ptr, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" bits field with label "name", pointer "ptr" and format "format" - void addBitVariable(const PIString & name, const void * ptr, int fromBit, int bitsCount, int column = 1, FormatFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" "count" empty lines - 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();} - - - //! Returns tabs count - uint tabsCount() const {return tabs.size();} - - //! Returns current tab name - PIString currentTab() const {return tabs[cur_tab].name;} - - //! Returns current tab index - int currentTabIndex() const {return cur_tab;} - - //! Add new tab with name "name", bind key "bind_key" and returns this tab index - int addTab(const PIString & name, char bind_key = 0); - - //! Remove tab with index "index" - void removeTab(uint index); - - //! Remove tab with name "name" - void removeTab(const PIString & name); - - //! Clear content of tab with index "index" - void clearTab(uint index); - - //! Clear content of tab with name "name" - void clearTab(const PIString & name); - - //! Set current tab to tab with index "index", returns if tab exists - bool setTab(uint index); - - //! Set current tab to tab with name "name", returns if tab exists - bool setTab(const PIString & name); - - //! Set tab with index "index" bind key to "bind_key", returns if tab exists - bool setTabBindKey(uint index, char bind_key); - - //! Set tab with name "name" bind key to "bind_key", returns if tab exists - bool setTabBindKey(const PIString & name, char bind_key); - - //! Remove all tabs and if "clearScreen" clear the screen - void clearTabs(bool clearScreen = true) {if (clearScreen && isRunning()) {toUpperLeft(); clearScreenLower();} tabs.clear();} - - - //! Set custom status text of current tab to "str" - void addCustomStatus(const PIString & str) {tabs[cur_tab].status = str;} - - //! Clear custom status text of current tab - void clearCustomStatus() {tabs[cur_tab].status.clear();} - - //! Returns default alignment - Alignment defaultAlignment() const {return def_align;} - - //! Set default alignment to "align" - void setDefaultAlignment(Alignment align) {def_align = align;} - - //! Set column "col" alignment to "align" - void setColumnAlignment(int col, Alignment align) {if (col < 0 || col >= columns().size_s()) return; column(col).alignment = align;} - - //! Set all columns of all tabs alignment to "align" - void setColumnAlignmentToAll(Alignment align) {piForeach (Tab & i, tabs) piForeach (Column & j, i.columns) j.alignment = align; fillLabels();} - - - //! Directly call function from \a PIKbdListener - void enableExitCapture(char key = 'Q') {listener->enableExitCapture(key);} - - //! Directly call function from \a PIKbdListener - void disableExitCapture() {listener->disableExitCapture();} - - //! Directly call function from \a PIKbdListener - bool exitCaptured() const {return listener->exitCaptured();} - - //! Directly call function from \a PIKbdListener - char exitKey() const {return listener->exitKey();} - - - int windowWidth() const {return width;} - int windowHeight() const {return height;} - - PIString fstr(FormatFlags f); - void update(); - void pause(bool yes) {pause_ = yes;} - - // Server functions - void startServer(const PIString & name); - void stopPeer(); - bool isServerStarted() const {return peer != 0;} - PIStringList clients() const; - - // Client functions - void listenServers(); - PIStringList availableServers() const; - PIString selectedServer() const {return server_name;} - void connectToServer(const PIString & name); - void disconnect(); - bool isConnected() const {return state == Connected;} - -#ifdef WINDOWS - 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 = ulcoord.Y + y; SetConsoleCursorPosition(hOut, ccoord);} - void clearScreen() {couts(fstr(Normal)); toUpperLeft(); FillConsoleOutputAttribute(hOut, dattr, width * (height + 1), ulcoord, &written); - FillConsoleOutputCharacter(hOut, ' ', width * (height + 1), ulcoord, &written);} - void clearScreenLower() {couts(fstr(Normal)); 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() {couts(fstr(Normal)); printf("\e[H\e[J");} - void clearScreenLower() {couts(fstr(Normal)); printf("\e[J");} - void clearLine() {printf("\e[K");} - void newLine() {printf("\eE");} - void hideCursor() {printf("\e[?25l");} - void showCursor() {printf("\e[?25h");} -#endif - - EVENT_HANDLER0(void, clearVariables) {clearVariables(true);} - EVENT_HANDLER1(void, clearVariables, bool, clearScreen); - - EVENT_HANDLER0(void, waitForFinish) {WAIT_FOR_EXIT} - EVENT_HANDLER0(void, start) {start(false);} - EVENT_HANDLER1(void, start, bool, wait) {PIThread::start(40); if (wait) waitForFinish();} - EVENT_HANDLER0(void, stop) {stop(false);} - EVENT_HANDLER1(void, stop, bool, clear); - - EVENT2(keyPressed, char, key, void * , data) - -//! \handlers -//! \{ - - //! \fn void waitForFinish() - //! \brief block until finished (exit key will be pressed) - - //! \fn void clearVariables(bool clearScreen = true) - //! \brief Remove all columns at current tab and if "clearScreen" clear the screen - - //! \fn void start(bool wait = false) - //! \brief Start console output and if "wait" block until finished (exit key will be pressed) - - //! \fn void stop(bool clear = false) - //! \brief Stop console output and if "clear" clear the screen - -//! \} -//! \events -//! \{ - - //! \fn void keyPressed(char key, void * data) - //! \brief Raise on key "key" pressed, "data" is pointer to %PIConsole object - -//! \} - -private: -#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;} -#endif - - void begin(); - void run(); - void fillLabels(); - 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; - const char * toBin(const void * d, int s); - inline void printLine(const PIString & str, int dx = 0, FormatFlags format = PIConsole::Normal); - inline int printValue(const PIString & str, FormatFlags format = PIConsole::Normal); - inline int printValue(const char * str, FormatFlags format = PIConsole::Normal); - inline int printValue(const bool value, FormatFlags format = PIConsole::Normal); - inline int printValue(const int value, FormatFlags format = PIConsole::Normal); - inline int printValue(const long value, FormatFlags format = PIConsole::Normal); - inline int printValue(const llong value, FormatFlags format = PIConsole::Normal); - inline int printValue(const float value, FormatFlags format = PIConsole::Normal); - inline int printValue(const double value, FormatFlags format = PIConsole::Normal); - inline int printValue(const char value, FormatFlags format = PIConsole::Normal); - inline int printValue(const short value, FormatFlags format = PIConsole::Normal); - inline int printValue(const uchar value, FormatFlags format = PIConsole::Normal); - inline int printValue(const ushort value, FormatFlags format = PIConsole::Normal); - inline int printValue(const uint value, FormatFlags format = PIConsole::Normal); - inline int printValue(const ulong value, FormatFlags format = PIConsole::Normal); - inline int printValue(const ullong value, FormatFlags format = PIConsole::Normal); - inline int printValue(const PISystemTime & value, FormatFlags format = PIConsole::Normal); - static void key_event(char key, void * t); - - struct Variable { - Variable() {nx = ny = type = offset = bitFrom = bitCount = size = 0; format = Normal; remote = false; ptr = 0; id = 1;} - bool isEmpty() const {return (remote ? false : ptr == 0);} - const void * data() {return (remote ? rdata.data() : ptr);} - void writeData(PIByteArray & ba) { - if (remote) ba << rdata; - else { - if (type == 0) ba << (*(PIString * )ptr); - else ba << PIByteArray::RawData(ptr, size); - } - } - PIString name; - FormatFlags format; - int nx; - int ny; - int type; - int offset; - int bitFrom; - int bitCount; - int size; - int id; - bool remote; - const void * ptr; - PIByteArray rdata; - void operator =(const Variable & src) {remote = src.remote; name = src.name; format = src.format; type = src.type; offset = src.offset; size = src.size; - bitFrom = src.bitFrom; bitCount = src.bitCount; ptr = src.ptr; nx = src.nx; ny = src.ny; rdata = src.rdata; id = src.id;} - }; - - struct VariableContent { - int id; - PIByteArray rdata; - }; - - struct Column { - Column(Alignment align = PIConsole::Right) {variables.reserve(32); alignment = align;} - PIVector variables; - Alignment alignment; - 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 { - Tab(PIString n = "", char k = 0) {columns.reserve(8); name = n; key = k;} - PIVector columns; - PIString name; - PIString status; - char key; - }; - - enum ConnectedState {Disconnected, FetchingData, Committing, Connected}; - - friend PIByteArray & operator <<(PIByteArray & ba, const PIConsole::VariableContent & v); - friend PIByteArray & operator >>(PIByteArray & ba, PIConsole::VariableContent & v); - - friend PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Variable & v); - friend PIByteArray & operator >>(PIByteArray & ba, PIConsole::Variable & v); - - friend PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Column & v); - friend PIByteArray & operator >>(PIByteArray & ba, PIConsole::Column & v); - - friend PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Tab & v); - friend PIByteArray & operator >>(PIByteArray & ba, PIConsole::Tab & v); - - PIVector & columns() {return tabs[cur_tab].columns;} - Column & column(int index) {return tabs[cur_tab].columns[index - 1];} - inline int couts(const PIString & v) {return printf("%s", v.data());} - inline int couts(const char * v) {return printf("%s", 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); - inline int couts(const PISystemTime & v); - - struct RemoteClient; - - void serverSendInfo(); - void serverSendData(); - RemoteClient & remoteClient(const PIString & fname); - EVENT_HANDLER2(void, peerReceived, const PIString &, from, const PIByteArray &, data); - EVENT_HANDLER2(void, peerTimer, void * , data, int, delim); - EVENT_HANDLER1(void, peerDisconnectedEvent, const PIString &, name); - -#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 tabs; - PIString binstr, rstr; - PIByteArray rba; - Variable tv; - PIKbdListener * listener; - Alignment def_align; - KBFunc ret_func; - int width, height, pwidth, pheight, ret, col_wid, num_format, systime_format; - uint max_y; - int vid; - uint cur_tab, col_cnt; - - PIPeer * peer; - PITimer peer_timer; - PITimeMeasurer peer_tm; - PIString server_name; - bool server_mode, pause_; - ConnectedState state; - - /*struct RemoteData { - RemoteData() {msg_count = msg_rec = msg_send = 0;} - void clear() {msg_count = msg_rec = msg_send = 0; data.clear();} - bool isEmpty() const {return msg_count == 0;} - bool isReadyRec() const {return msg_count == msg_rec;} - bool isReadySend() const {return msg_count == msg_send;} - void setData(const PIByteArray & ba) {data = ba; msg_rec = msg_send = 0; msg_count = (data.size_s() - 1) / 4096 + 1;} - PIByteArray data; - int msg_count; - int msg_rec; - int msg_send; - };*/ - - struct RemoteClient { - RemoteClient(const PIString & n = "") {name = n; state = Disconnected;} - PIString name; - ConnectedState state; - }; - - PIVector remote_clients; - -}; - -inline PIByteArray & operator <<(PIByteArray & ba, const PIConsole::VariableContent & v) {ba << v.id << v.rdata; return ba;} -inline PIByteArray & operator >>(PIByteArray & ba, PIConsole::VariableContent & v) {ba >> v.id; ba >> v.rdata; return ba;} - -inline PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Variable & v) {ba << v.name << v.id << (int)v.format << v.type << v.size << v.bitFrom << v.bitCount; return ba;} -inline PIByteArray & operator >>(PIByteArray & ba, PIConsole::Variable & v) {ba >> v.name >> v.id >> (int & )v.format >> v.type >> v.size >> v.bitFrom >> v.bitCount; return ba;} - -inline PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Column & v) {ba << (int)v.alignment << v.variables; return ba;} -inline PIByteArray & operator >>(PIByteArray & ba, PIConsole::Column & v) {ba >> (int & )v.alignment >> v.variables; return ba;} - -inline PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Tab & v) {ba << v.name << v.status << (uchar)v.key << v.columns; return ba;} -inline PIByteArray & operator >>(PIByteArray & ba, PIConsole::Tab & v) {ba >> v.name >> v.status >> (uchar&)v.key >> v.columns; return ba;} - -#endif // PICONSOLE_H diff --git a/src/system/pikbdlistener.cpp b/src/system/pikbdlistener.cpp deleted file mode 100755 index 1f7d674b..00000000 --- a/src/system/pikbdlistener.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - PIP - Platform Independent Primitives - Keyboard grabber for console - Copyright (C) 2014 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 . -*/ - -#include "pikbdlistener.h" - - -/** \class PIKbdListener - * \brief Keyboard console input listener - * \details This class provide listening of console keyboard input. - * There is two ways to receive pressed key: - * * external static function with format "void func(char key, void * data_)" - * * event \a keyPressed() - * - * Also there is static variable \a exiting which by default is set to - * \b false. If \a enableExitCapture() was called and listener was started - * with function \a start(), this variable will be set to \b true if exit - * key will be pressed. By default exit key is 'Q' = shift + 'q'. - * To wait for this variable changes to \b true there is WAIT_FOR_EXIT macro - * \snippet pikbdlistener.cpp main - * */ - - -bool PIKbdListener::exiting; - -PIKbdListener::PIKbdListener(KBFunc slot, void * _data): PIThread() { - setName("keyboard_listener"); -#ifdef WINDOWS - hIn = GetStdHandle(STD_INPUT_HANDLE); - GetConsoleMode(hIn, &smode); -#else - struct termios term; - tcgetattr(0, &term); - sterm = term; -#endif - is_active = true; - ret_func = slot; - data_ = _data; - PIKbdListener::exiting = exit_enabled = false; - start(); -} - - -void PIKbdListener::begin() { -#ifdef WINDOWS - GetConsoleMode(hIn, &tmode); - SetConsoleMode(hIn, ENABLE_PROCESSED_INPUT); -#else - struct termios term; - tcgetattr(0, &term); - term.c_lflag &= ~(ECHO | ICANON) | NOFLSH; - tterm = term; - tcsetattr(0, TCSANOW, &term); -#endif -} - - -void PIKbdListener::run() { - rc = 0; - char lc = 0; -#ifdef WINDOWS - INPUT_RECORD ir; - ReadConsoleInput(hIn, &ir, 1, &ret); - if (ir.EventType == KEY_EVENT) { - KEY_EVENT_RECORD ker = ir.Event.KeyEvent; - if (ker.bKeyDown) { - bool ctrl = ((ker.dwControlKeyState & LEFT_CTRL_PRESSED) || (ker.dwControlKeyState & RIGHT_CTRL_PRESSED)); - bool shift = (ker.dwControlKeyState & SHIFT_PRESSED); - if (ker.dwControlKeyState & CAPSLOCK_ON) shift = !shift; - //cout << "key " << int(ker.wVirtualKeyCode) << endl; - switch (ker.wVirtualKeyCode) { - case 37: ret = 1; lc = (ctrl ? CtrlLeftArrow : LeftArrow); break; - case 38: ret = 1; lc = (ctrl ? CtrlUpArrow : UpArrow); break; - case 39: ret = 1; lc = (ctrl ? CtrlRightArrow : RightArrow); break; - case 40: ret = 1; lc = (ctrl ? CtrlDownArrow : DownArrow); break; - default: ret = 1; lc = (shift ? char(toupper(ker.uChar.AsciiChar)) : ker.uChar.AsciiChar); break; - } - if (lc == 0) {piMSleep(10); return;} - } else {piMSleep(10); return;} - } else {piMSleep(10); return;} - /*if (lc == 0) { - ReadConsole(hIn, &rc, 1, &ret, 0); - //cout << "read console" << endl; - lc = char(rc); - }*/ - /*if (ret < 0 || ret > 3) return; - lc = char(((uchar * )&rc)[ret - 1]); - for (int i = 0; i < ret; ++i) - cout << std::hex << int(((uchar * )&rc)[i]) << ' '; - cout << endl << std::hex << rc << endl;*/ -#else - tcsetattr(0, TCSANOW, &tterm); - ret = read(0, &rc, 4); - if (rc == 0) {piMSleep(10); return;} - if (ret < 0 || ret > 3) {piMSleep(10); return;} - lc = char(((uchar * )&rc)[ret - 1]); - /*for (int i = 0; i < ret; ++i) - cout << std::hex << int(((uchar * )&rc)[i]) << ' '; - cout << endl << std::hex << rc << endl;*/ - if (((char * )&rc)[0] == '\e' && ret == 3) { - if (((char * )&rc)[1] == '[') { - switch (((char * )&rc)[2]) { - case 'A': lc = UpArrow; break; // up - case 'B': lc = DownArrow; break; // down - case 'C': lc = RightArrow; break; // right - case 'D': lc = LeftArrow; break; // left - case 'H': lc = Home; break; - case 'F': lc = End; break; - } - } - } - if (((char * )&rc)[0] == '5' && ret == 2) { - switch (((char * )&rc)[1]) { - case 'A': lc = CtrlUpArrow; break; // up - case 'B': lc = CtrlDownArrow; break; // down - case 'C': lc = CtrlRightArrow; break; // right - case 'D': lc = CtrlLeftArrow; break; // left - case 'H': lc = CtrlHome; break; - case 'F': lc = CtrlEnd; break; - } - } -#endif - if ((((char * )&rc)[0] == '\n' || ((char * )&rc)[0] == '\r') && ret == 1) - lc = Return; - if (exit_enabled && ret == 1 && lc == exit_key) { - PIKbdListener::exiting = true; - return; - } - if (ret > 0) { - keyPressed(lc, data_); - if (ret_func != 0) ret_func(lc, data_); - } -} - - -void PIKbdListener::end() { - //cout << "list end" << endl; -#ifdef WINDOWS - SetConsoleMode(hIn, smode); -#else - tcsetattr(0, TCSANOW, &sterm); -#endif -} - - -void PIKbdListener::setActive(bool yes) { - is_active = yes; - if (is_active) { -#ifdef WINDOWS - SetConsoleMode(hIn, tmode); -#else - tcsetattr(0, TCSANOW, &tterm); -#endif - } else { -#ifdef WINDOWS - SetConsoleMode(hIn, smode); -#else - tcsetattr(0, TCSANOW, &sterm); -#endif - } -} diff --git a/src/system/pikbdlistener.h b/src/system/pikbdlistener.h deleted file mode 100755 index a6b908e3..00000000 --- a/src/system/pikbdlistener.h +++ /dev/null @@ -1,139 +0,0 @@ -/*! \file pikbdlistener.h - * \brief Keyboard console input listener -*/ -/* - PIP - Platform Independent Primitives - Keyboard grabber for console - Copyright (C) 2014 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 . -*/ - -#ifndef PIKBDLISTENER_H -#define PIKBDLISTENER_H - -#include "pithread.h" -#ifndef WINDOWS -# include -#endif - -#define WAIT_FOR_EXIT while (!PIKbdListener::exiting) msleep(5); - -typedef void (*KBFunc)(char, void * ); - -class PIP_EXPORT PIKbdListener: public PIThread -{ - PIOBJECT(PIKbdListener) - PIOBJECT_PARENT(PIThread) - friend class PIConsole; -public: - - //! Special keyboard keys - enum SpecialSymbol { - UpArrow /** Up arrow key */ = -1, - DownArrow /** Down arrow key */ = -2, - RightArrow /** Right arrow key */ = -3, - LeftArrow /** Left arrow key */ = -4, - Home /** Home key */ = -9, - End /** End key */ = -10, - CtrlUpArrow /** Ctrl + Up arrow key */ = -5, - CtrlDownArrow /** Ctrl + Down arrow key */ = -6, - CtrlRightArrow /** Ctrl + Right arrow key */ = -7, - CtrlLeftArrow /** Ctrl + Left arrow key */ = -8, - CtrlHome /** Ctrl + Home key */ = -11, - CtrlEnd /** Ctrl + End key */ = -12, - Return /** Enter key */ = 0x0a, - Esc /** Escape key */ = 0x1b, - Space /** Space key */ = 0x20, - Backspace /** Backspace key */ = 0x7f - }; - - //! Constructs keyboard listener with external function "slot" and custom data "data" - PIKbdListener(KBFunc slot = 0, void * data = 0); - - ~PIKbdListener() {terminate(); end();} - - - //! Returns custom data - void * data() {return data_;} - - //! Set custom data to "_data" - void setData(void * _data) {data_ = _data;} - - //! Set external function to "slot" - void setSlot(KBFunc slot) {ret_func = slot;} - - //! Returns if exit key if awaiting - bool exitCaptured() const {return exit_enabled;} - - //! Returns exit key, default 'Q' - char exitKey() const {return exit_key;} - - - //! Returns if keyboard listening is active (not running!) - bool isActive() {return is_active;} - - EVENT_HANDLER( void, enableExitCapture) {enableExitCapture('Q');} - EVENT_HANDLER1(void, enableExitCapture, char, key) {exit_enabled = true; exit_key = key;} - EVENT_HANDLER(void, disableExitCapture) {exit_enabled = false;} - EVENT_HANDLER(void, setActive) {setActive(true);} - EVENT_HANDLER1(void, setActive, bool, yes); - - EVENT2(keyPressed, char, key, void * , data) - -//! \handlers -//! \{ - - //! \fn void enableExitCapture(char key = 'Q') - //! \brief Enable exit key "key" awaiting - - //! \fn void disableExitCapture() - //! \brief Disable exit key awaiting - - //! \fn void setActive(bool yes = true) - //! \brief Set keyboard listening is active or not - -//! \} -//! \events -//! \{ - - //! \fn void keyPressed(char key, void * data) - //! \brief Raise on key "key" pressed, "data" is custom data - -//! \} - - static bool exiting; - -private: - void begin(); - void run(); - void end(); - - KBFunc ret_func; - char exit_key; - bool exit_enabled, is_active; - void * data_; -#ifdef WINDOWS - DWORD ret, rc; - void * hIn; - DWORD smode, tmode; -#else - int rc; - int ret; - struct termios sterm, tterm; -#endif - -}; - -#endif // PIKBDLISTENER_H diff --git a/src/system/piscreen.cpp b/src/system/piscreen.cpp deleted file mode 100644 index e8ede7ea..00000000 --- a/src/system/piscreen.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* - PIP - Platform Independent Primitives - Console output/input - Copyright (C) 2014 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 . -*/ - -#include "piscreen.h" - - -/** \class PIScreen - * \brief Console output class - * \details - * \section PIScreen_sec0 Synopsis - * This class provides output to console with automatic alignment and update. - * It supports tabs, keyboard listening, formats and colors. - * - * \section PIScreen_sec1 Layout - * %PIScreen works with variable pointers. You should add your variables with - * functions \a addVariable() which receives label name, pointer to variable - * and optional column and format. Columns count is dynamically increased if - * new column used. E.g. if you add variable to empty tab to column 3, columns - * count will be increased to 3, but two firsts columns will be empty. Each column - * filled from top to bottom, but you can add just string with function - * \a addString() or add empty line with function \a addEmptyLine(). Layout scheme: - * \image html piconsole_layout.png - * - * \section PIScreen_sec2 Keyboard usage - * %PIScreen should to be single in application. %PIScreen aggregate PIKbdListener - * which grab keyboard and automatic switch tabs by theirs bind keys. If there is no - * tab binded to pressed key external function "slot" will be called - * - **/ - - -extern PIMutex __PICout_mutex__; - - -PIScreen::SystemConsole::SystemConsole() { - width = height = pwidth = pheight = 0; - int w, h; -#ifdef WINDOWS - ulcoord.X = 0; - hOut = GetStdHandle(STD_OUTPUT_HANDLE); - GetConsoleScreenBufferInfo(hOut, &sbi); - dattr = sbi.wAttributes; - w = sbi.srWindow.Right - sbi.srWindow.Left; - h = sbi.srWindow.Bottom - sbi.srWindow.Top; - ulcoord.Y = sbi.srWindow.Top; - GetConsoleMode(hOut, &smode); - GetConsoleCursorInfo(hOut, &curinfo); -#else - winsize ws; - ioctl(0, TIOCGWINSZ, &ws); - w = ws.ws_col; - h = ws.ws_row; -#endif - resize(w, h); -} - - -PIScreen::SystemConsole::~SystemConsole() { -#ifdef WINDOWS - SetConsoleMode(hOut, smode); - SetConsoleTextAttribute(hOut, dattr); -#endif -} - - -void PIScreen::SystemConsole::begin() { -#ifdef WINDOWS - SetConsoleMode(hOut, ENABLE_WRAP_AT_EOL_OUTPUT); - GetConsoleScreenBufferInfo(hOut, &sbi); - bc.X = 0; - bc.Y = 0; -#endif - clearScreen(); - hideCursor(); -} - - -void PIScreen::SystemConsole::end() { - showCursor(); -} - - -void PIScreen::SystemConsole::prepare() { - int w, h; -#ifdef WINDOWS - GetConsoleScreenBufferInfo(hOut, &sbi); - w = sbi.srWindow.Right - sbi.srWindow.Left + 1; - h = sbi.srWindow.Bottom - sbi.srWindow.Top + 1; -#else - winsize ws; - ioctl(0, TIOCGWINSZ, &ws); - w = ws.ws_col; - h = ws.ws_row; -#endif - resize(w, h); -} - - -void PIScreen::SystemConsole::resize(int w, int h) { - if (w == pwidth && h == pheight) return; - width = piMax(w, 0); - height = piMax(h, 0); - pwidth = width; - pheight = height; - cells.resize(height); - pcells.resize(height); - for (int i = 0; i < height; ++i) { - cells[i].resize(width); - pcells[i].resize(width, Cell(0)); - } -#ifdef WINDOWS - bs.X = width; - bs.Y = height; - chars.resize(width * height); -#endif -} - - -void PIScreen::SystemConsole::print() { -#ifdef WINDOWS - static int cnt = 0; - for (int i = 0; i < width; ++i) - for (int j = 0; j < height; ++j) { - int k = j * width + i; - chars[k].Char.UnicodeChar = 0; - chars[k].Char.AsciiChar = ((cnt + i + j / 3)%11 + '0'); - chars[k].Attributes = sbi.wAttributes; - if (i % 3 == 0) chars[k].Attributes |= BACKGROUND_RED; - //if (j % 3 == 1) chars[k].Attributes |= BACKGROUND_GREEN; - //if (j % 3 == 2) chars[k].Attributes |= BACKGROUND_BLUE; - /*if (i % 3 == 2) chars[k].Attributes |= FOREGROUND_INTENSITY; - if (i % 3 == 2) { - chars[k].Attributes |= FOREGROUND_INTENSITY; - chars[k].Attributes &= ~(FOREGROUND_RED | FOREGROUND_BLUE); - }*/ - } - srect = sbi.srWindow; - WriteConsoleOutput(hOut, chars.data(), bs, bc, &srect); -#else - for (int i = 0; i < height; ++i) - pcells[i] = cells[i]; -#endif -} - - - - -PIScreen::PIScreen(bool startNow, KBFunc slot): PIThread() { - setName("screen"); - setPriority(piLow); - needLockRun(true); - ret_func = slot; - listener = new PIKbdListener(key_event, this); - if (startNow) start(); -} - - -PIScreen::~PIScreen() { - if (isRunning()) - stop(); - delete listener; -} - - -void PIScreen::key_event(char key, void * t) { - PIScreen * p = (PIScreen * )t; - if (p->ret_func != 0) p->ret_func(key, t); - p->keyPressed(key, t); -} - - -void PIScreen::stop(bool clear) { - PIThread::stop(true); - if (clear) console.clearScreen(); - fflush(0); -} - - -void PIScreen::begin() { - console.begin(); -} - - -void PIScreen::run() { - console.prepare(); - console.print(); -} - - -void PIScreen::end() { - console.end(); -} diff --git a/src/system/piscreen.h b/src/system/piscreen.h deleted file mode 100644 index d0576662..00000000 --- a/src/system/piscreen.h +++ /dev/null @@ -1,194 +0,0 @@ -/*! \file piscreen.h - * \brief Console output class -*/ -/* - PIP - Platform Independent Primitives - Console output/input - Copyright (C) 2014 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 . -*/ - -#ifndef PSCREEN_H -#define PSCREEN_H - -#include "pikbdlistener.h" -#include "piprotocol.h" -#include "pidiagnostics.h" -#include "pisystemmonitor.h" -#ifndef WINDOWS -# include -# include -#endif - - -class PIP_EXPORT PIScreen: public PIThread -{ - PIOBJECT_SUBCLASS(PIScreen, PIThread) -public: - - //! Constructs %PIScreen with key handler "slot" and if "startNow" start it - PIScreen(bool startNow = true, KBFunc slot = 0); - - ~PIScreen(); - - //! Color for chars or background - enum Color { - Default /** Default */, - Black /** Black */, - Red /** Red */, - Green /** Green */, - Yellow /** Yellow */, - Blue /** Blue */, - Magenta /** Magenta */, - Cyan /** Cyan */, - White /** White */ - }; - - //! Flags for chars - enum CharFlag { - Bold /** Bold flag */ = 0x1, - Blink /** Blink flag */ = 0x2, - }; - - //! Variables output format - enum __Format { - Dec /** Decimal base for integers */ = 0x1000000, - Hex /** Hexadecimal base for integers */ = 0x2000000, - Oct /** Octal base for integers */ = 0x4000000, - Bin /** Binary base for integers */ = 0x8000000, - Scientific /** Scientific representation of floats */ = 0x10000000, - SystemTimeSplit /** PISystemTime split representation (* s, * ns) */ = 0x20000000, - SystemTimeSeconds /** PISystemTime seconds representation (*.* s) */ = 0x40000000 - }; - - //! Column labels alignment - enum Alignment { - Nothing /** No alignment */ , - Left /** Labels align left and variables align left */ , - Right /** Labels align right and variables align left */, - Center /** */ - }; - - typedef PIFlags CharFlags; - - - //! Directly call function from \a PIKbdListener - void enableExitCapture(char key = 'Q') {listener->enableExitCapture(key);} - - //! Directly call function from \a PIKbdListener - void disableExitCapture() {listener->disableExitCapture();} - - //! Directly call function from \a PIKbdListener - bool exitCaptured() const {return listener->exitCaptured();} - - //! Directly call function from \a PIKbdListener - char exitKey() const {return listener->exitKey();} - - - EVENT_HANDLER0(void, waitForFinish) {WAIT_FOR_EXIT} - EVENT_HANDLER0(void, start) {start(false);} - EVENT_HANDLER1(void, start, bool, wait) {PIThread::start(40); if (wait) waitForFinish();} - EVENT_HANDLER0(void, stop) {stop(false);} - EVENT_HANDLER1(void, stop, bool, clear); - - EVENT2(keyPressed, char, key, void * , data) - -//! \handlers -//! \{ - - //! \fn void waitForFinish() - //! \brief block until finished (exit key will be pressed) - - //! \fn void clearVariables(bool clearScreen = true) - //! \brief Remove all columns at current tab and if "clearScreen" clear the screen - - //! \fn void start(bool wait = false) - //! \brief Start console output and if "wait" block until finished (exit key will be pressed) - - //! \fn void stop(bool clear = false) - //! \brief Stop console output and if "clear" clear the screen - -//! \} -//! \events -//! \{ - - //! \fn void keyPressed(char key, void * data) - //! \brief Raise on key "key" pressed, "data" is pointer to %PIConsole object - -//! \} - -private: - class SystemConsole { - public: - SystemConsole(); - ~SystemConsole(); - struct Cell { - Cell(char c = ' ') {color_back = color_char = flags = 0; symbol = c;} - uchar color_char; - uchar color_back; - ushort flags; - PIChar symbol; - }; - void begin(); - void end(); - void prepare(); - void print(); - void resize(int w, int h); -#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 moveTo(int x = 0, int y = 0) {ccoord.X = x; ccoord.Y = ulcoord.Y + y; SetConsoleCursorPosition(hOut, ccoord);} - void hideCursor() {curinfo.bVisible = false; SetConsoleCursorInfo(hOut, &curinfo);} - void showCursor() {curinfo.bVisible = true; SetConsoleCursorInfo(hOut, &curinfo);} - void clearScreen() {toUpperLeft(); 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);} -#else - void toUpperLeft() {printf("\e[H");} - void moveTo(int x = 0, int y = 0) {printf("\e[%d;%dH", y, x);} - void hideCursor() {printf("\e[?25l");} - void showCursor() {printf("\e[?25h");} - void clearScreen() {printf("\e[0m\e[H\e[J");} - void clearScreenLower() {printf("\e[0m\e[J");} -#endif -#ifdef WINDOWS - void * hOut; - CONSOLE_SCREEN_BUFFER_INFO sbi, csbi; - CONSOLE_CURSOR_INFO curinfo; - COORD ccoord, ulcoord, bs, bc; - SMALL_RECT srect; - WORD dattr; - DWORD smode, written; - PIVector chars; -#endif - int width, height, pwidth, pheight; - PIVector > cells, pcells, dcells; - }; - - void begin(); - void run(); - void end(); - static void key_event(char key, void * t); - - SystemConsole console; - PIKbdListener * listener; - KBFunc ret_func; - - -}; - -#endif // PSCREEN_H