version 1.22.0

source tree changed
detached PIConsole and PIScreen* in "pip_console" library
This commit is contained in:
2020-06-28 00:18:24 +03:00
parent 5de62b1c83
commit 42925122cb
231 changed files with 22981 additions and 22948 deletions

View File

@@ -2,9 +2,9 @@ cmake_minimum_required(VERSION 3.0)
cmake_policy(SET CMP0017 NEW) # need include() with .cmake cmake_policy(SET CMP0017 NEW) # need include() with .cmake
project(pip) project(pip)
set(_PIP_MAJOR 1) set(_PIP_MAJOR 1)
set(_PIP_MINOR 21) set(_PIP_MINOR 22)
set(_PIP_REVISION 0) set(_PIP_REVISION 0)
set(_PIP_SUFFIX beta) set(_PIP_SUFFIX )
set(_PIP_COMPANY SHS) set(_PIP_COMPANY SHS)
set(_PIP_DOMAIN org.SHS) set(_PIP_DOMAIN org.SHS)
@@ -57,16 +57,27 @@ macro(gather_src DIR CPP H H_P)
list(APPEND ${H_P} ${PHS}) list(APPEND ${H_P} ${PHS})
endmacro() endmacro()
set(PIP_SRC_MAIN "src_main") set(PIP_SRC_MAIN "lib/main")
set(PIP_SRC_CRYPT "src_crypt") set(PIP_SRC_CONSOLE "lib/console")
set(PIP_SRC_COMPRESS "src_compress") set(PIP_SRC_CRYPT "lib/crypt")
set(PIP_SRC_USB "src_usb") set(PIP_SRC_COMPRESS "lib/compress")
set(PIP_SRC_FFTW "src_fftw") set(PIP_SRC_USB "lib/usb")
set(PIP_SRC_OPENCL "src_opencl") set(PIP_SRC_FFTW "lib/fftw")
set(PIP_SRC_IO_UTILS "src_io_utils") set(PIP_SRC_OPENCL "lib/opencl")
set(PIP_SRC_CONCURRENT "src_concurrent") set(PIP_SRC_IO_UTILS "lib/io_utils")
set(PIP_SRC_CLOUD "src_cloud") set(PIP_SRC_CONCURRENT "lib/concurrent")
set(PIP_SRC_DIRS "src_main" "src_crypt" "src_compress" "src_usb" "src_fftw" "src_opencl" "src_io_utils" "src_concurrent" "src_cloud") set(PIP_SRC_CLOUD "lib/cloud")
set(PIP_SRC_DIRS ${PIP_SRC_MAIN}
${PIP_SRC_CONSOLE}
${PIP_SRC_CRYPT}
${PIP_SRC_COMPRESS}
${PIP_SRC_USB}
${PIP_SRC_FFTW}
${PIP_SRC_OPENCL}
${PIP_SRC_IO_UTILS}
${PIP_SRC_CONCURRENT}
${PIP_SRC_CLOUD}
)
set(PIP_LIBS_TARGETS pip) set(PIP_LIBS_TARGETS pip)
set(LIBS_MAIN) set(LIBS_MAIN)
set(LIBS_STATUS) set(LIBS_STATUS)
@@ -178,6 +189,9 @@ endforeach(F)
# Crypt lib # Crypt lib
gather_src("${PIP_SRC_CRYPT}" CPP_LIB_CRYPT HDRS PHDRS) gather_src("${PIP_SRC_CRYPT}" CPP_LIB_CRYPT HDRS PHDRS)
# Console lib
gather_src("${PIP_SRC_CONSOLE}" CPP_LIB_CONSOLE HDRS PHDRS)
# Compress lib # Compress lib
gather_src("${PIP_SRC_COMPRESS}" CPP_LIB_COMPRESS HDRS PHDRS) gather_src("${PIP_SRC_COMPRESS}" CPP_LIB_COMPRESS HDRS PHDRS)
@@ -400,6 +414,19 @@ if (NOT CROSSTOOLS)
endif() endif()
# Add console library
import_version(pip_console pip)
set_deploy_property(pip_console ${PIP_LIB_TYPE}
LABEL "PIP console support"
FULLNAME "${_PIP_DOMAIN}.pip_console"
COMPANY "${_PIP_COMPANY}"
INFO "Platform-Independent Primitives")
make_rc(pip_console _RC)
add_library(pip_console ${PIP_LIB_TYPE} ${CPP_LIB_CONSOLE} ${_RC})
target_link_libraries(pip_console pip)
list(APPEND PIP_LIBS_TARGETS pip_console)
# Check if PIP support cryptographic encryption/decryption using sodium library # Check if PIP support cryptographic encryption/decryption using sodium library
find_library(sodium_FOUND sodium) find_library(sodium_FOUND sodium)
if(sodium_FOUND) if(sodium_FOUND)
@@ -517,7 +544,7 @@ if (NOT CROSSTOOLS)
include_directories(${OpenCL_INCLUDE_DIRS}) include_directories(${OpenCL_INCLUDE_DIRS})
endif() endif()
add_definitions(-DPIP_OPENCL) add_definitions(-DPIP_OPENCL)
pip_resources(CL_RES "src_opencl/resources.conf") pip_resources(CL_RES "${PIP_SRC_OPENCL}/resources.conf")
add_library(pip_opencl ${PIP_LIB_TYPE} ${CPP_LIB_OPENCL} ${CL_RES} ${_RC}) add_library(pip_opencl ${PIP_LIB_TYPE} ${CPP_LIB_OPENCL} ${CL_RES} ${_RC})
add_dependencies(pip_opencl pip_rc) add_dependencies(pip_opencl pip_rc)
if(${CMAKE_VERSION} VERSION_LESS "3.7.0") if(${CMAKE_VERSION} VERSION_LESS "3.7.0")

View File

@@ -1,20 +1,20 @@
set(COMPONENT_SRCS "main.cpp") set(COMPONENT_SRCS "main.cpp")
set(COMPONENT_ADD_INCLUDEDIRS "pip/src_main") set(COMPONENT_ADD_INCLUDEDIRS "pip/lib/main")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/auxiliary") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/auxiliary")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/code") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/code")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/console") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/console")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/containers") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/containers")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/core") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/core")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/crypt") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/crypt")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/geo") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/geo")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/io_devices") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/io_devices")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/io_utils") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/io_utils")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/math") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/math")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/opencl") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/opencl")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/resources") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/resources")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/system") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/system")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/thread") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/thread")
list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/src_main/introspection") list(APPEND COMPONENT_ADD_INCLUDEDIRS "pip/lib/main/introspection")
set(COMPONENT_PRIV_REQUIRES pthread lwip freertos vfs spiffs) set(COMPONENT_PRIV_REQUIRES pthread lwip freertos vfs spiffs)
register_component() register_component()
set(PIP_FREERTOS ON) set(PIP_FREERTOS ON)

View File

@@ -1,1168 +1,1168 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Console output/input Console output/input
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "piconsole.h" #include "piconsole.h"
#include "piincludes_p.h" #include "piincludes_p.h"
#include "pipeer.h" #include "pipeer.h"
#include "pidiagnostics.h" #include "pidiagnostics.h"
#include "pisystemmonitor.h" #include "pisystemmonitor.h"
#ifndef WINDOWS #ifndef WINDOWS
# include <sys/ioctl.h> # include <sys/ioctl.h>
# include <fcntl.h> # include <fcntl.h>
# include <termios.h> # include <termios.h>
#else #else
# include <wincon.h> # include <wincon.h>
# define COMMON_LVB_UNDERSCORE 0x8000 # define COMMON_LVB_UNDERSCORE 0x8000
#endif #endif
/** \class PIConsole /** \class PIConsole
* \brief Console output class * \brief Console output class
* \details * \details
* \section PIConsole_sec0 Synopsis * \section PIConsole_sec0 Synopsis
* This class provides output to console with automatic alignment and update. * This class provides output to console with automatic alignment and update.
* It supports tabs, keyboard listening, formats and colors. * It supports tabs, keyboard listening, formats and colors.
* *
* \section PIConsole_sec1 Layout * \section PIConsole_sec1 Layout
* %PIConsole works with variable pointers. You should add your variables with * %PIConsole works with variable pointers. You should add your variables with
* functions \a addVariable() which receives label name, pointer to variable * functions \a addVariable() which receives label name, pointer to variable
* and optional column and format. Columns count is dynamically increased if * 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 * 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 * 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 * 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: * \a addString() or add empty line with function \a addEmptyLine(). Layout scheme:
* \image html piconsole_layout.png * \image html piconsole_layout.png
* *
* \section PIConsole_sec2 Keyboard usage * \section PIConsole_sec2 Keyboard usage
* %PIConsole should to be single in application. %PIConsole aggregate PIKbdListener * %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 * 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 * tab binded to pressed key external function "slot" will be called
* *
**/ **/
PRIVATE_DEFINITION_START(PIConsole) PRIVATE_DEFINITION_START(PIConsole)
#ifdef WINDOWS #ifdef WINDOWS
void getWinCurCoord() {GetConsoleScreenBufferInfo(hOut, &csbi); ccoord = csbi.dwCursorPosition;} 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;} COORD & getWinCoord(int dx = 0, int dy = 0) {getWinCurCoord(); ccoord.X += dx; ccoord.Y += dy; return ccoord;}
void * hOut; void * hOut;
CONSOLE_SCREEN_BUFFER_INFO sbi, csbi; CONSOLE_SCREEN_BUFFER_INFO sbi, csbi;
CONSOLE_CURSOR_INFO curinfo; CONSOLE_CURSOR_INFO curinfo;
COORD ccoord, ulcoord; COORD ccoord, ulcoord;
WORD dattr; WORD dattr;
DWORD smode, written; DWORD smode, written;
#endif #endif
PRIVATE_DEFINITION_END(PIConsole) PRIVATE_DEFINITION_END(PIConsole)
PIConsole::PIConsole(bool startNow, PIKbdListener::KBFunc slot): PIThread() { PIConsole::PIConsole(bool startNow, PIKbdListener::KBFunc slot): PIThread() {
setName("console"); setName("console");
setPriority(piLow); setPriority(piLow);
needLockRun(true); needLockRun(true);
ret_func = slot; ret_func = slot;
num_format = systime_format = 0; num_format = systime_format = 0;
vid = 0; vid = 0;
cur_tab = width = height = pwidth = pheight = max_y = 0; cur_tab = width = height = pwidth = pheight = max_y = 0;
def_align = Nothing; def_align = Nothing;
tabs.reserve(16); tabs.reserve(16);
#ifdef WINDOWS #ifdef WINDOWS
PRIVATE->ulcoord.X = 0; PRIVATE->ulcoord.X = 0;
PRIVATE->hOut = GetStdHandle(STD_OUTPUT_HANDLE); PRIVATE->hOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi); GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi);
PRIVATE->dattr = PRIVATE->sbi.wAttributes; PRIVATE->dattr = PRIVATE->sbi.wAttributes;
width = PRIVATE->sbi.srWindow.Right - PRIVATE->sbi.srWindow.Left; width = PRIVATE->sbi.srWindow.Right - PRIVATE->sbi.srWindow.Left;
height = PRIVATE->sbi.srWindow.Bottom - PRIVATE->sbi.srWindow.Top; height = PRIVATE->sbi.srWindow.Bottom - PRIVATE->sbi.srWindow.Top;
PRIVATE->ulcoord.Y = PRIVATE->sbi.srWindow.Top; PRIVATE->ulcoord.Y = PRIVATE->sbi.srWindow.Top;
GetConsoleMode(PRIVATE->hOut, &PRIVATE->smode); GetConsoleMode(PRIVATE->hOut, &PRIVATE->smode);
GetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo); GetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo);
#else #else
# ifdef FREERTOS # ifdef FREERTOS
width = 80; width = 80;
height = 24; height = 24;
# else # else
winsize ws; winsize ws;
ioctl(0, TIOCGWINSZ, &ws); ioctl(0, TIOCGWINSZ, &ws);
width = ws.ws_col; width = ws.ws_col;
height = ws.ws_row; height = ws.ws_row;
# endif # endif
#endif #endif
addTab("main"); addTab("main");
listener = new PIKbdListener(key_event, this); listener = new PIKbdListener(key_event, this);
peer_timer = new PITimer(); peer_timer = new PITimer();
peer_timer->setName("__S__.PIConsole.peer_timer"); peer_timer->setName("__S__.PIConsole.peer_timer");
peer = 0; peer = 0;
server_mode = pause_ = false; server_mode = pause_ = false;
state = Disconnected; state = Disconnected;
peer_timer->addDelimiter(20); peer_timer->addDelimiter(20);
peer_timer->setName("__S__PIConsole::peer_timer"); peer_timer->setName("__S__PIConsole::peer_timer");
CONNECT2(void, void * , int, peer_timer, tickEvent, this, peerTimer); CONNECT2(void, void * , int, peer_timer, tickEvent, this, peerTimer);
if (startNow) start(); if (startNow) start();
} }
PIConsole::~PIConsole() { PIConsole::~PIConsole() {
stopPeer(); stopPeer();
if (isRunning()) if (isRunning())
stop(); stop();
clearTabs(false); clearTabs(false);
delete listener; delete listener;
delete peer_timer; delete peer_timer;
#ifdef WINDOWS #ifdef WINDOWS
SetConsoleMode(PRIVATE->hOut, PRIVATE->smode); SetConsoleMode(PRIVATE->hOut, PRIVATE->smode);
SetConsoleTextAttribute(PRIVATE->hOut, PRIVATE->dattr); SetConsoleTextAttribute(PRIVATE->hOut, PRIVATE->dattr);
#endif #endif
} }
int PIConsole::addTab(const PIString & name, char bind_key) { int PIConsole::addTab(const PIString & name, char bind_key) {
if (isRunning()) lock(); if (isRunning()) lock();
tabs.push_back(Tab(name, bind_key)); tabs.push_back(Tab(name, bind_key));
cur_tab = tabs.size() - 1; cur_tab = tabs.size() - 1;
if (isRunning()) unlock(); if (isRunning()) unlock();
return tabs.size(); return tabs.size();
} }
void PIConsole::removeTab(uint index) { void PIConsole::removeTab(uint index) {
if (index >= tabs.size()) return; if (index >= tabs.size()) return;
if (isRunning()) lock(); if (isRunning()) lock();
tabs.remove(index); tabs.remove(index);
if (cur_tab >= tabs.size()) cur_tab = tabs.size() - 1; if (cur_tab >= tabs.size()) cur_tab = tabs.size() - 1;
if (isRunning()) unlock(); if (isRunning()) unlock();
} }
void PIConsole::removeTab(const PIString & name) { void PIConsole::removeTab(const PIString & name) {
uint index = tabs.size() + 1; uint index = tabs.size() + 1;
for (uint i = 0; i < tabs.size(); ++i) { for (uint i = 0; i < tabs.size(); ++i) {
if (tabs[i].name == name) { if (tabs[i].name == name) {
index = i; index = i;
break; break;
} }
} }
removeTab(index); removeTab(index);
} }
void PIConsole::clearTab(uint index) { void PIConsole::clearTab(uint index) {
if (index >= tabs.size()) return; if (index >= tabs.size()) return;
lock(); lock();
tabs[index].columns.clear(); tabs[index].columns.clear();
if (cur_tab == index) { if (cur_tab == index) {
clearScreen(); clearScreen();
fillLabels(); fillLabels();
} }
if (cur_tab >= tabs.size()) cur_tab = tabs.size() - 1; if (cur_tab >= tabs.size()) cur_tab = tabs.size() - 1;
unlock(); unlock();
} }
void PIConsole::clearTab(const PIString & name) { void PIConsole::clearTab(const PIString & name) {
uint index = tabs.size() + 1; uint index = tabs.size() + 1;
for (uint i = 0; i < tabs.size(); ++i) { for (uint i = 0; i < tabs.size(); ++i) {
if (tabs[i].name == name) { if (tabs[i].name == name) {
index = i; index = i;
break; break;
} }
} }
clearTab(index); clearTab(index);
} }
void PIConsole::update() { void PIConsole::update() {
lock(); lock();
fillLabels(); fillLabels();
unlock(); unlock();
} }
bool PIConsole::setTab(uint index) { bool PIConsole::setTab(uint index) {
if (index >= tabs.size()) if (index >= tabs.size())
return false; return false;
if (!isRunning()) { if (!isRunning()) {
cur_tab = index; cur_tab = index;
return true; return true;
} }
lock(); lock();
PICout::__mutex__().lock(); PICout::__mutex__().lock();
cur_tab = index; cur_tab = index;
clearScreen(); clearScreen();
fillLabels(); fillLabels();
PICout::__mutex__().unlock(); PICout::__mutex__().unlock();
unlock(); unlock();
return true; return true;
} }
bool PIConsole::setTab(const PIString & name) { bool PIConsole::setTab(const PIString & name) {
uint index = tabs.size() + 1; uint index = tabs.size() + 1;
for (uint i = 0; i < tabs.size(); ++i) { for (uint i = 0; i < tabs.size(); ++i) {
if (tabs[i].name == name) { if (tabs[i].name == name) {
index = i; index = i;
break; break;
} }
} }
return setTab(index); return setTab(index);
} }
bool PIConsole::setTabBindKey(uint index, char bind_key) { bool PIConsole::setTabBindKey(uint index, char bind_key) {
if (index >= tabs.size()) if (index >= tabs.size())
return false; return false;
tabs[index].key = bind_key; tabs[index].key = bind_key;
return true; return true;
} }
bool PIConsole::setTabBindKey(const PIString & name, char bind_key) { bool PIConsole::setTabBindKey(const PIString & name, char bind_key) {
uint index =tabs.size() + 1; uint index =tabs.size() + 1;
for (uint i = 0; i < tabs.size(); ++i) { for (uint i = 0; i < tabs.size(); ++i) {
if (tabs[i].name == name) { if (tabs[i].name == name) {
index = i; index = i;
break; break;
} }
} }
return setTabBindKey(index, bind_key); return setTabBindKey(index, bind_key);
} }
void PIConsole::key_event(PIKbdListener::KeyEvent key, void * t) { void PIConsole::key_event(PIKbdListener::KeyEvent key, void * t) {
PIConsole * p = (PIConsole * )t; PIConsole * p = (PIConsole * )t;
int ct = p->cur_tab; int ct = p->cur_tab;
if (key.key == PIKbdListener::LeftArrow) { if (key.key == PIKbdListener::LeftArrow) {
do { do {
ct--; ct--;
if (ct < 0) return; if (ct < 0) return;
} while (p->tabs[ct].key == 0); } while (p->tabs[ct].key == 0);
p->setTab(ct); p->setTab(ct);
return; return;
} }
if (key.key == PIKbdListener::RightArrow) { if (key.key == PIKbdListener::RightArrow) {
do { do {
ct++; ct++;
if (ct >= p->tabs.size_s()) return; if (ct >= p->tabs.size_s()) return;
} while (p->tabs[ct].key == 0); } while (p->tabs[ct].key == 0);
p->setTab(ct); p->setTab(ct);
return; return;
} }
for (uint i = 0; i < p->tabsCount(); ++i) { for (uint i = 0; i < p->tabsCount(); ++i) {
if (p->tabs[i].key == key.key) { if (p->tabs[i].key == key.key) {
p->setTab(i); p->setTab(i);
return; return;
} }
} }
if (p->ret_func != 0) p->ret_func(key, t); if (p->ret_func != 0) p->ret_func(key, t);
p->keyPressed(key, t); p->keyPressed(key, t);
} }
int PIConsole::couts(const PIString & v) { int PIConsole::couts(const PIString & v) {
return printf("%s", v.data()); return printf("%s", v.data());
} }
int PIConsole::couts(const char * v) { int PIConsole::couts(const char * v) {
return printf("%s", v); return printf("%s", v);
} }
void PIConsole::clearVariables(bool clearScreen) { void PIConsole::clearVariables(bool clearScreen) {
if (isRunning()) lock(); if (isRunning()) lock();
if (clearScreen && isRunning()) { if (clearScreen && isRunning()) {
toUpperLeft(); toUpperLeft();
clearScreenLower(); clearScreenLower();
} }
columns().clear(); columns().clear();
if (isRunning()) unlock(); if (isRunning()) unlock();
} }
void PIConsole::stop(bool clear) { void PIConsole::stop(bool clear) {
PIThread::stop(true); PIThread::stop(true);
if (clear) clearScreen(); if (clear) clearScreen();
moveTo(0, max_y + 4); moveTo(0, max_y + 4);
showCursor(); showCursor();
couts(fstr(Normal)); couts(fstr(Normal));
#ifdef WINDOWS #ifdef WINDOWS
SetConsoleMode(PRIVATE->hOut, PRIVATE->smode); SetConsoleMode(PRIVATE->hOut, PRIVATE->smode);
SetConsoleTextAttribute(PRIVATE->hOut, PRIVATE->dattr); SetConsoleTextAttribute(PRIVATE->hOut, PRIVATE->dattr);
#endif #endif
fflush(0); fflush(0);
} }
PIString PIConsole::fstr(FormatFlags f) { PIString PIConsole::fstr(FormatFlags f) {
num_format = systime_format = 0; num_format = systime_format = 0;
if (f[PIConsole::Dec]) num_format = 0; if (f[PIConsole::Dec]) num_format = 0;
if (f[PIConsole::Hex]) num_format = 1; if (f[PIConsole::Hex]) num_format = 1;
if (f[PIConsole::Oct]) num_format = 2; if (f[PIConsole::Oct]) num_format = 2;
if (f[PIConsole::Bin]) num_format = 4; if (f[PIConsole::Bin]) num_format = 4;
if (f[PIConsole::Scientific]) num_format = 3; if (f[PIConsole::Scientific]) num_format = 3;
if (f[PIConsole::SystemTimeSplit]) systime_format = 0; if (f[PIConsole::SystemTimeSplit]) systime_format = 0;
if (f[PIConsole::SystemTimeSeconds]) systime_format = 1; if (f[PIConsole::SystemTimeSeconds]) systime_format = 1;
#ifdef WINDOWS #ifdef WINDOWS
WORD attr = 0; WORD attr = 0;
if (f[PIConsole::Inverse]) { if (f[PIConsole::Inverse]) {
if (f[PIConsole::Red]) attr |= BACKGROUND_RED; if (f[PIConsole::Red]) attr |= BACKGROUND_RED;
if (f[PIConsole::Green]) attr |= BACKGROUND_GREEN; if (f[PIConsole::Green]) attr |= BACKGROUND_GREEN;
if (f[PIConsole::Blue]) attr |= BACKGROUND_BLUE; if (f[PIConsole::Blue]) attr |= BACKGROUND_BLUE;
if (f[PIConsole::Yellow]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN); if (f[PIConsole::Yellow]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN);
if (f[PIConsole::Magenta]) attr |= (BACKGROUND_RED | BACKGROUND_BLUE); if (f[PIConsole::Magenta]) attr |= (BACKGROUND_RED | BACKGROUND_BLUE);
if (f[PIConsole::Cyan]) attr |= (BACKGROUND_GREEN | 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::White]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
if (f[PIConsole::BackRed]) attr |= FOREGROUND_RED; if (f[PIConsole::BackRed]) attr |= FOREGROUND_RED;
if (f[PIConsole::BackGreen]) attr |= FOREGROUND_GREEN; if (f[PIConsole::BackGreen]) attr |= FOREGROUND_GREEN;
if (f[PIConsole::BackBlue]) attr |= FOREGROUND_BLUE; if (f[PIConsole::BackBlue]) attr |= FOREGROUND_BLUE;
if (f[PIConsole::BackYellow]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN); if (f[PIConsole::BackYellow]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN);
if (f[PIConsole::BackMagenta]) attr |= (FOREGROUND_RED | FOREGROUND_BLUE); if (f[PIConsole::BackMagenta]) attr |= (FOREGROUND_RED | FOREGROUND_BLUE);
if (f[PIConsole::BackCyan]) attr |= (FOREGROUND_GREEN | FOREGROUND_BLUE); if (f[PIConsole::BackCyan]) attr |= (FOREGROUND_GREEN | FOREGROUND_BLUE);
if (f[PIConsole::BackWhite]) attr |= (FOREGROUND_RED | 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) if ((attr & BACKGROUND_RED) + (attr & BACKGROUND_GREEN) + (attr & BACKGROUND_BLUE) == 0)
attr |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; attr |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
} else { } else {
if (f[PIConsole::Red]) attr |= FOREGROUND_RED; if (f[PIConsole::Red]) attr |= FOREGROUND_RED;
if (f[PIConsole::Green]) attr |= FOREGROUND_GREEN; if (f[PIConsole::Green]) attr |= FOREGROUND_GREEN;
if (f[PIConsole::Blue]) attr |= FOREGROUND_BLUE; if (f[PIConsole::Blue]) attr |= FOREGROUND_BLUE;
if (f[PIConsole::Yellow]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN); if (f[PIConsole::Yellow]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN);
if (f[PIConsole::Magenta]) attr |= (FOREGROUND_RED | FOREGROUND_BLUE); if (f[PIConsole::Magenta]) attr |= (FOREGROUND_RED | FOREGROUND_BLUE);
if (f[PIConsole::Cyan]) attr |= (FOREGROUND_GREEN | 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::White]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
if (f[PIConsole::BackRed]) attr |= BACKGROUND_RED; if (f[PIConsole::BackRed]) attr |= BACKGROUND_RED;
if (f[PIConsole::BackGreen]) attr |= BACKGROUND_GREEN; if (f[PIConsole::BackGreen]) attr |= BACKGROUND_GREEN;
if (f[PIConsole::BackBlue]) attr |= BACKGROUND_BLUE; if (f[PIConsole::BackBlue]) attr |= BACKGROUND_BLUE;
if (f[PIConsole::BackYellow]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN); if (f[PIConsole::BackYellow]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN);
if (f[PIConsole::BackMagenta]) attr |= (BACKGROUND_RED | BACKGROUND_BLUE); if (f[PIConsole::BackMagenta]) attr |= (BACKGROUND_RED | BACKGROUND_BLUE);
if (f[PIConsole::BackCyan]) attr |= (BACKGROUND_GREEN | BACKGROUND_BLUE); if (f[PIConsole::BackCyan]) attr |= (BACKGROUND_GREEN | BACKGROUND_BLUE);
if (f[PIConsole::BackWhite]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); if (f[PIConsole::BackWhite]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
if ((attr & FOREGROUND_RED) + (attr & FOREGROUND_GREEN) + (attr & FOREGROUND_BLUE) == 0) if ((attr & FOREGROUND_RED) + (attr & FOREGROUND_GREEN) + (attr & FOREGROUND_BLUE) == 0)
attr |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; attr |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
} }
if (f[PIConsole::Bold]) attr |= FOREGROUND_INTENSITY; if (f[PIConsole::Bold]) attr |= FOREGROUND_INTENSITY;
if (f[PIConsole::Underline]) attr |= COMMON_LVB_UNDERSCORE; if (f[PIConsole::Underline]) attr |= COMMON_LVB_UNDERSCORE;
SetConsoleTextAttribute(PRIVATE->hOut, attr); SetConsoleTextAttribute(PRIVATE->hOut, attr);
return PIString(); return PIString();
#else #else
PIString ts("\e[0"); PIString ts("\e[0");
if (f[PIConsole::Bold]) ts += ";1"; if (f[PIConsole::Bold]) ts += ";1";
if (f[PIConsole::Faint]) ts += ";2"; if (f[PIConsole::Faint]) ts += ";2";
if (f[PIConsole::Italic]) ts += ";3"; if (f[PIConsole::Italic]) ts += ";3";
if (f[PIConsole::Underline]) ts += ";4"; if (f[PIConsole::Underline]) ts += ";4";
if (f[PIConsole::Blink]) ts += ";5"; if (f[PIConsole::Blink]) ts += ";5";
if (f[PIConsole::Inverse]) ts += ";7"; if (f[PIConsole::Inverse]) ts += ";7";
if (f[PIConsole::Black]) ts += ";30"; if (f[PIConsole::Black]) ts += ";30";
if (f[PIConsole::Red]) ts += ";31"; if (f[PIConsole::Red]) ts += ";31";
if (f[PIConsole::Green]) ts += ";32"; if (f[PIConsole::Green]) ts += ";32";
if (f[PIConsole::Yellow]) ts += ";33"; if (f[PIConsole::Yellow]) ts += ";33";
if (f[PIConsole::Blue]) ts += ";34"; if (f[PIConsole::Blue]) ts += ";34";
if (f[PIConsole::Magenta]) ts += ";35"; if (f[PIConsole::Magenta]) ts += ";35";
if (f[PIConsole::Cyan]) ts += ";36"; if (f[PIConsole::Cyan]) ts += ";36";
if (f[PIConsole::White]) ts += ";37"; if (f[PIConsole::White]) ts += ";37";
if (f[PIConsole::BackBlack]) ts += ";40"; if (f[PIConsole::BackBlack]) ts += ";40";
if (f[PIConsole::BackRed]) ts += ";41"; if (f[PIConsole::BackRed]) ts += ";41";
if (f[PIConsole::BackGreen]) ts += ";42"; if (f[PIConsole::BackGreen]) ts += ";42";
if (f[PIConsole::BackYellow]) ts += ";43"; if (f[PIConsole::BackYellow]) ts += ";43";
if (f[PIConsole::BackBlue]) ts += ";44"; if (f[PIConsole::BackBlue]) ts += ";44";
if (f[PIConsole::BackMagenta]) ts += ";45"; if (f[PIConsole::BackMagenta]) ts += ";45";
if (f[PIConsole::BackCyan]) ts += ";46"; if (f[PIConsole::BackCyan]) ts += ";46";
if (f[PIConsole::BackWhite]) ts += ";47"; if (f[PIConsole::BackWhite]) ts += ";47";
return ts + "m"; return ts + "m";
#endif #endif
} }
inline int PIConsole::couts(const bool v) {return (v ? printf("true") : printf("false"));} 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 char v) {return printf("%c", v);}
inline int PIConsole::couts(const short 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;} 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) { 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;} 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) { 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;} 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) { 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;} 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) { 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;} 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) { 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;} 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) { 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;} 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) { 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;} 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) { 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;} 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) { inline int PIConsole::couts(const float v) {
switch (num_format) {case (3): return printf("%e", v); break; default: return printf("%.5g", v); break;} switch (num_format) {case (3): return printf("%e", v); break; default: return printf("%.5g", v); break;}
} }
inline int PIConsole::couts(const double v) { inline int PIConsole::couts(const double v) {
switch (num_format) {case (3): return printf("%le", v); break; default: return printf("%.5lg", v); break;} switch (num_format) {case (3): return printf("%le", v); break; default: return printf("%.5lg", v); break;}
} }
inline int PIConsole::couts(const PISystemTime & v) { inline int PIConsole::couts(const PISystemTime & v) {
switch (systime_format) {case (1): return printf("%.6lg", v.toSeconds()); break; switch (systime_format) {case (1): return printf("%.6lg", v.toSeconds()); break;
default: return couts(v.seconds) + printf(" s, ") + couts(v.nanoseconds) + printf(" ns"); break;} default: return couts(v.seconds) + printf(" s, ") + couts(v.nanoseconds) + printf(" ns"); break;}
} }
void PIConsole::toUpperLeft() { void PIConsole::toUpperLeft() {
#ifdef WINDOWS #ifdef WINDOWS
SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ulcoord); SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ulcoord);
#else #else
printf("\e[H"); printf("\e[H");
#endif #endif
} }
void PIConsole::moveRight(int n) { void PIConsole::moveRight(int n) {
#ifdef WINDOWS #ifdef WINDOWS
SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->getWinCoord(n)); SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->getWinCoord(n));
#else #else
if (n > 0) printf("\e[%dC", n); if (n > 0) printf("\e[%dC", n);
#endif #endif
} }
void PIConsole::moveLeft(int n) { void PIConsole::moveLeft(int n) {
#ifdef WINDOWS #ifdef WINDOWS
SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->getWinCoord(-n)); SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->getWinCoord(-n));
#else #else
if (n > 0) printf("\e[%dD", n); if (n > 0) printf("\e[%dD", n);
#endif #endif
} }
void PIConsole::moveTo(int x, int y) { void PIConsole::moveTo(int x, int y) {
#ifdef WINDOWS #ifdef WINDOWS
PRIVATE->ccoord.X = x; PRIVATE->ccoord.X = x;
PRIVATE->ccoord.Y = PRIVATE->ulcoord.Y + y; PRIVATE->ccoord.Y = PRIVATE->ulcoord.Y + y;
SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ccoord); SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ccoord);
#else #else
printf("\e[%d;%dH", y, x); printf("\e[%d;%dH", y, x);
#endif #endif
} }
void PIConsole::clearScreen() { void PIConsole::clearScreen() {
#ifdef WINDOWS #ifdef WINDOWS
couts(fstr(Normal)); couts(fstr(Normal));
toUpperLeft(); toUpperLeft();
FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, width * (height + 1), PRIVATE->ulcoord, &PRIVATE->written); FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, width * (height + 1), PRIVATE->ulcoord, &PRIVATE->written);
FillConsoleOutputCharacter(PRIVATE->hOut, ' ', width * (height + 1), PRIVATE->ulcoord, &PRIVATE->written); FillConsoleOutputCharacter(PRIVATE->hOut, ' ', width * (height + 1), PRIVATE->ulcoord, &PRIVATE->written);
#else #else
couts(fstr(Normal)); printf("\e[H\e[J"); couts(fstr(Normal)); printf("\e[H\e[J");
#endif #endif
} }
void PIConsole::clearScreenLower() { void PIConsole::clearScreenLower() {
#ifdef WINDOWS #ifdef WINDOWS
couts(fstr(Normal)); couts(fstr(Normal));
PRIVATE->getWinCurCoord(); PRIVATE->getWinCurCoord();
FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, width * height - width * PRIVATE->ccoord.Y + PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written); FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, width * height - width * PRIVATE->ccoord.Y + PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written);
FillConsoleOutputCharacter(PRIVATE->hOut, ' ', width * height - width * PRIVATE->ccoord.Y + PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written); FillConsoleOutputCharacter(PRIVATE->hOut, ' ', width * height - width * PRIVATE->ccoord.Y + PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written);
#else #else
couts(fstr(Normal)); printf("\e[J"); couts(fstr(Normal)); printf("\e[J");
#endif #endif
} }
void PIConsole::clearLine() { void PIConsole::clearLine() {
#ifdef WINDOWS #ifdef WINDOWS
PRIVATE->getWinCurCoord(); PRIVATE->getWinCurCoord();
FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, width - PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written); FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, width - PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written);
FillConsoleOutputCharacter(PRIVATE->hOut, ' ', width - PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written); FillConsoleOutputCharacter(PRIVATE->hOut, ' ', width - PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written);
#else #else
printf("\e[K"); printf("\e[K");
#endif #endif
} }
void PIConsole::newLine() { void PIConsole::newLine() {
#ifdef WINDOWS #ifdef WINDOWS
PRIVATE->getWinCurCoord(); PRIVATE->getWinCurCoord();
PRIVATE->ccoord.X = 0; PRIVATE->ccoord.Y++; PRIVATE->ccoord.X = 0; PRIVATE->ccoord.Y++;
SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ccoord); SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ccoord);
#else #else
printf("\eE"); printf("\eE");
#endif #endif
} }
void PIConsole::hideCursor() { void PIConsole::hideCursor() {
#ifdef WINDOWS #ifdef WINDOWS
PRIVATE->curinfo.bVisible = false; PRIVATE->curinfo.bVisible = false;
SetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo); SetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo);
#else #else
printf("\e[?25l"); printf("\e[?25l");
#endif #endif
} }
void PIConsole::showCursor() { void PIConsole::showCursor() {
#ifdef WINDOWS #ifdef WINDOWS
PRIVATE->curinfo.bVisible = true; SetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo); PRIVATE->curinfo.bVisible = true; SetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo);
#else #else
printf("\e[?25h"); printf("\e[?25h");
#endif #endif
} }
void PIConsole::begin() { void PIConsole::begin() {
#ifdef WINDOWS #ifdef WINDOWS
SetConsoleMode(PRIVATE->hOut, ENABLE_WRAP_AT_EOL_OUTPUT); SetConsoleMode(PRIVATE->hOut, ENABLE_WRAP_AT_EOL_OUTPUT);
#endif #endif
max_y = 0; max_y = 0;
PICout::__mutex__().lock(); PICout::__mutex__().lock();
clearScreen(); clearScreen();
hideCursor(); hideCursor();
fillLabels(); fillLabels();
PICout::__mutex__().unlock(); PICout::__mutex__().unlock();
} }
void PIConsole::run() { void PIConsole::run() {
if (pause_) return; if (pause_) return;
uint cx, clen = 0; uint cx, clen = 0;
int j; int j;
#ifdef WINDOWS #ifdef WINDOWS
GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi); GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi);
width = PRIVATE->sbi.srWindow.Right - PRIVATE->sbi.srWindow.Left; width = PRIVATE->sbi.srWindow.Right - PRIVATE->sbi.srWindow.Left;
height = PRIVATE->sbi.srWindow.Bottom - PRIVATE->sbi.srWindow.Top; height = PRIVATE->sbi.srWindow.Bottom - PRIVATE->sbi.srWindow.Top;
#else #else
# ifdef FREERTOS # ifdef FREERTOS
width = 80; width = 80;
height = 24; height = 24;
# else # else
winsize ws; winsize ws;
ioctl(0, TIOCGWINSZ, &ws); ioctl(0, TIOCGWINSZ, &ws);
width = ws.ws_col; width = ws.ws_col;
height = ws.ws_row; height = ws.ws_row;
# endif # endif
#endif #endif
//fflush(0); return; //fflush(0); return;
PICout::__mutex__().lock(); PICout::__mutex__().lock();
if (pwidth != width || pheight != height) { if (pwidth != width || pheight != height) {
clearScreen(); clearScreen();
fillLabels(); fillLabels();
} }
pwidth = width; pwidth = width;
pheight = height; pheight = height;
col_cnt = columns().size(); col_cnt = columns().size();
col_wid = (col_cnt > 0) ? width / col_cnt : width; col_wid = (col_cnt > 0) ? width / col_cnt : width;
for (uint i = 0; i < col_cnt; ++i) { for (uint i = 0; i < col_cnt; ++i) {
PIVector<Variable> & cvars(tabs[cur_tab].columns[i].variables); PIVector<Variable> & cvars(tabs[cur_tab].columns[i].variables);
cx = col_wid * i; cx = col_wid * i;
toUpperLeft(); toUpperLeft();
if (max_y < cvars.size()) max_y = cvars.size(); if (max_y < cvars.size()) max_y = cvars.size();
j = 0; j = 0;
piForeachC (Variable & tv_, cvars) { piForeachC (Variable & tv_, cvars) {
if (j > height - 3) continue; if (j > height - 3) continue;
j++; j++;
moveRight(cx); moveRight(cx);
if (tv_.type == 15) { if (tv_.type == 15) {
newLine(); newLine();
continue; continue;
} }
moveRight(tv_.offset); moveRight(tv_.offset);
const void * ptr = 0; const void * ptr = 0;
if (tv_.remote) { if (tv_.remote) {
if (tv_.type == 0) { if (tv_.type == 0) {
rstr.clear(); rstr.clear();
rba = tv_.rdata; rba = tv_.rdata;
rba >> rstr; rba >> rstr;
rstr.trim(); rstr.trim();
ptr = &rstr; ptr = &rstr;
} else } else
ptr = tv_.rdata.data(); ptr = tv_.rdata.data();
} else } else
ptr = tv_.ptr; ptr = tv_.ptr;
switch (tv_.type) { switch (tv_.type) {
case 0: clen = printValue(ptr != 0 ? *(const PIString*)ptr : PIString(), tv_.format); break; 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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; case 14: clen = printValue(bitsValue(ptr, tv_.bitFrom, tv_.bitCount), tv_.format); break;
} }
if (clen + tv_.offset < (uint)col_wid) { if (clen + tv_.offset < (uint)col_wid) {
PIString ts = PIString( PIString ts = PIString(
#if defined(QNX) || defined(FREE_BSD) #if defined(QNX) || defined(FREE_BSD)
col_wid - clen - tv_.offset - 1, ' '); col_wid - clen - tv_.offset - 1, ' ');
#else #else
col_wid - clen - tv_.offset, ' '); col_wid - clen - tv_.offset, ' ');
#endif #endif
printf("%s", ts.data()); printf("%s", ts.data());
} }
newLine(); newLine();
} }
} }
#ifdef WINDOWS #ifdef WINDOWS
moveTo(0, max_y + 1); moveTo(0, max_y + 1);
#else #else
moveTo(0, max_y + 2); moveTo(0, max_y + 2);
#endif #endif
fflush(0); fflush(0);
PICout::__mutex__().unlock(); PICout::__mutex__().unlock();
} }
void PIConsole::fillLabels() { void PIConsole::fillLabels() {
if (!isRunning()) return; if (!isRunning()) return;
uint cx, cy, mx = 0, dx; uint cx, cy, mx = 0, dx;
#ifdef WINDOWS #ifdef WINDOWS
GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi); GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi);
width = PRIVATE->sbi.srWindow.Right - PRIVATE->sbi.srWindow.Left; width = PRIVATE->sbi.srWindow.Right - PRIVATE->sbi.srWindow.Left;
height = PRIVATE->sbi.srWindow.Bottom - PRIVATE->sbi.srWindow.Top; height = PRIVATE->sbi.srWindow.Bottom - PRIVATE->sbi.srWindow.Top;
#else #else
# ifdef FREERTOS # ifdef FREERTOS
width = 80; width = 80;
height = 24; height = 24;
# else # else
winsize ws; winsize ws;
ioctl(0, TIOCGWINSZ, &ws); ioctl(0, TIOCGWINSZ, &ws);
width = ws.ws_col; width = ws.ws_col;
height = ws.ws_row; height = ws.ws_row;
# endif # endif
#endif #endif
max_y = 0; max_y = 0;
col_cnt = columns().size(); col_cnt = columns().size();
col_wid = (col_cnt > 0) ? width / col_cnt : width; col_wid = (col_cnt > 0) ? width / col_cnt : width;
for (uint i = 0; i < col_cnt; ++i) { for (uint i = 0; i < col_cnt; ++i) {
Column & ccol(tabs[cur_tab].columns[i]); Column & ccol(tabs[cur_tab].columns[i]);
PIVector<Variable> & cvars(ccol.variables); PIVector<Variable> & cvars(ccol.variables);
if (ccol.alignment != Nothing) { if (ccol.alignment != Nothing) {
mx = 0; mx = 0;
piForeachC (Variable & j, cvars) piForeachC (Variable & j, cvars)
if (!j.isEmpty()) if (!j.isEmpty())
if (mx < j.name.size()) if (mx < j.name.size())
mx = j.name.size(); mx = j.name.size();
mx += 2; mx += 2;
} }
cx = col_wid * i; cx = col_wid * i;
cy = 1; cy = 1;
toUpperLeft(); toUpperLeft();
for (uint j = 0; j < cvars.size(); ++j) { for (uint j = 0; j < cvars.size(); ++j) {
if (int(j) > height - 3) continue; if (int(j) > height - 3) continue;
if (max_y < j) max_y = j; if (max_y < j) max_y = j;
moveRight(cx); moveRight(cx);
Variable & tv_(cvars[j]); Variable & tv_(cvars[j]);
cvars[j].nx = cx; cvars[j].nx = cx;
cvars[j].ny = cy; cvars[j].ny = cy;
if (tv_.name.isEmpty()) { if (tv_.name.isEmpty()) {
cvars[j].offset = 0; cvars[j].offset = 0;
clearLine(); clearLine();
newLine(); newLine();
cy++; cy++;
continue; continue;
} }
clearLine(); clearLine();
//piCout << tv_.name << tv_.type << tv_.ptr; //piCout << tv_.name << tv_.type << tv_.ptr;
if (tv_.type == 15) { if (tv_.type == 15) {
cvars[j].offset = cvars[j].name.length(); cvars[j].offset = cvars[j].name.length();
cvars[j].nx += cvars[j].offset; cvars[j].nx += cvars[j].offset;
printLine(tv_.name, cx, tv_.format); printLine(tv_.name, cx, tv_.format);
newLine(); newLine();
cy++; cy++;
continue; continue;
} }
if (!tv_.isEmpty()) { if (!tv_.isEmpty()) {
switch (ccol.alignment) { switch (ccol.alignment) {
case Nothing: case Nothing:
cvars[j].offset = (tv_.name + ": ").length(); cvars[j].offset = (tv_.name + ": ").length();
cvars[j].nx += cvars[j].offset; cvars[j].nx += cvars[j].offset;
printValue(tv_.name + ": ", tv_.format); printValue(tv_.name + ": ", tv_.format);
break; break;
case Left: case Left:
cvars[j].offset = mx; cvars[j].offset = mx;
cvars[j].nx += cvars[j].offset; cvars[j].nx += cvars[j].offset;
printValue(tv_.name + ": ", tv_.format); printValue(tv_.name + ": ", tv_.format);
break; break;
case Right: case Right:
cvars[j].offset = mx; cvars[j].offset = mx;
cvars[j].nx += cvars[j].offset; cvars[j].nx += cvars[j].offset;
dx = mx - (tv_.name + ": ").length(); dx = mx - (tv_.name + ": ").length();
moveRight(dx); moveRight(dx);
printValue(tv_.name + ": ", tv_.format); printValue(tv_.name + ": ", tv_.format);
moveLeft(dx); moveLeft(dx);
break; break;
} }
} }
newLine(); newLine();
cy++; cy++;
} }
} }
#ifdef WINDOWS #ifdef WINDOWS
moveTo(0, max_y + 1); moveTo(0, max_y + 1);
#else #else
moveTo(0, max_y + 2); moveTo(0, max_y + 2);
#endif #endif
if (!tabs[cur_tab].status.isEmpty()) { if (!tabs[cur_tab].status.isEmpty()) {
printValue(tabs[cur_tab].status); printValue(tabs[cur_tab].status);
newLine(); newLine();
} }
status(); status();
} }
void PIConsole::status() { void PIConsole::status() {
Tab * ctab; Tab * ctab;
for (uint i = 0; i < tabsCount(); ++i) { for (uint i = 0; i < tabsCount(); ++i) {
ctab = &tabs[i]; ctab = &tabs[i];
if (ctab->key == 0) continue; if (ctab->key == 0) continue;
printValue(ctab->key, PIConsole::White | PIConsole::Bold); printValue(ctab->key, PIConsole::White | PIConsole::Bold);
if (i == cur_tab) if (i == cur_tab)
printValue(ctab->name + " ", PIConsole::BackYellow | PIConsole::Black); printValue(ctab->name + " ", PIConsole::BackYellow | PIConsole::Black);
else else
printValue(ctab->name + " ", PIConsole::Cyan | PIConsole::Inverse); printValue(ctab->name + " ", PIConsole::Cyan | PIConsole::Inverse);
printValue(" "); printValue(" ");
} }
newLine(); newLine();
} }
int PIConsole::bitsValue(const void * src, int offset, int count) const { int PIConsole::bitsValue(const void * src, int offset, int count) const {
int ret = 0, stbyte = offset / 8, cbit = offset - stbyte * 8; int ret = 0, stbyte = offset / 8, cbit = offset - stbyte * 8;
char cbyte = reinterpret_cast<const char * >(src)[stbyte]; char cbyte = reinterpret_cast<const char * >(src)[stbyte];
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
ret |= ((cbyte >> cbit & 1) << i); ret |= ((cbyte >> cbit & 1) << i);
cbit++; cbit++;
if (cbit == 8) { if (cbit == 8) {
cbit = 0; cbit = 0;
stbyte++; stbyte++;
cbyte = reinterpret_cast<const char * >(src)[stbyte]; cbyte = reinterpret_cast<const char * >(src)[stbyte];
} }
} }
return ret; return ret;
} }
const char * PIConsole::toBin(const void * d, int s) { const char * PIConsole::toBin(const void * d, int s) {
binstr.clear(); binstr.clear();
uchar cc, b; uchar cc, b;
for (int i = 0; i < s; ++i) { for (int i = 0; i < s; ++i) {
cc = ((const uchar *)d)[i]; cc = ((const uchar *)d)[i];
b = 1; b = 1;
for (int j = 0; j < 8; ++j) { for (int j = 0; j < 8; ++j) {
binstr << (cc & b ? "1" : "0"); binstr << (cc & b ? "1" : "0");
b <<= 1; b <<= 1;
} }
if (i < s - 1) binstr << " "; if (i < s - 1) binstr << " ";
} }
binstr.reverse(); binstr.reverse();
return binstr.data(); 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); #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) { 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);} 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) { 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);} 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) { 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);} 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) { 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);} 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) { 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);} 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) { 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);} 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) { 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);} 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) { 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);} 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) { 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);} 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) { 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);} 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) { 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);} 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) { 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);} 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) { 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);} 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) { 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);} 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) { 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);} 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) { 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);} 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" /** \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: * \details This function add to column "column" next lines:
* * "<name> diagnostics" * * "<name> diagnostics"
* * "Received count": \a PIDiagnostics::receiveCount * * "Received count": \a PIDiagnostics::receiveCount
* * "Invalid count": \a PIDiagnostics::wrongCount * * "Invalid count": \a PIDiagnostics::wrongCount
* * "Sended count": \a PIDiagnostics::sendCount * * "Sended count": \a PIDiagnostics::sendCount
* * "Immediate Frequency, Hz": \a PIDiagnostics::immediateFrequency * * "Immediate Frequency, Hz": \a PIDiagnostics::immediateFrequency
* * "Integral Frequency, Hz": \a PIDiagnostics::integralFrequency * * "Integral Frequency, Hz": \a PIDiagnostics::integralFrequency
* * "Receive speed": \a PIDiagnostics::receiveSpeed * * "Receive speed": \a PIDiagnostics::receiveSpeed
* * "Send speed": \a PIDiagnostics::sendSpeed * * "Send speed": \a PIDiagnostics::sendSpeed
* * "Quality": \a PIDiagnostics::quality * * "Quality": \a PIDiagnostics::quality
* */ * */
void PIConsole::addVariable(const PIString & name, const PIDiagnostics * ptr, int col, FormatFlags format) { void PIConsole::addVariable(const PIString & name, const PIDiagnostics * ptr, int col, FormatFlags format) {
addString(name + " diagnostics", col, format | PIConsole::Bold); addString(name + " diagnostics", col, format | PIConsole::Bold);
// addVariable("Received count", ptr->receiveCount_ptr(), col, format); // addVariable("Received count", ptr->receiveCount_ptr(), col, format);
// addVariable("Invalid count", ptr->wrongCount_ptr(), col, format); // addVariable("Invalid count", ptr->wrongCount_ptr(), col, format);
// addVariable("Sended count", ptr->sendCount_ptr(), col, format); // addVariable("Sended count", ptr->sendCount_ptr(), col, format);
// addVariable("Immediate Frequency, Hz", ptr->immediateFrequency_ptr(), col, format); // addVariable("Immediate Frequency, Hz", ptr->immediateFrequency_ptr(), col, format);
// addVariable("Integral Frequency, Hz", ptr->integralFrequency_ptr(), col, format); // addVariable("Integral Frequency, Hz", ptr->integralFrequency_ptr(), col, format);
// addVariable("Receive speed", ptr->receiveSpeed_ptr(), col, format); // addVariable("Receive speed", ptr->receiveSpeed_ptr(), col, format);
// addVariable("Send speed", ptr->sendSpeed_ptr(), col, format); // addVariable("Send speed", ptr->sendSpeed_ptr(), col, format);
// addVariable("Quality", ptr->quality_ptr(), col, format); // addVariable("Quality", ptr->quality_ptr(), col, format);
} }
void PIConsole::addVariable(const PIString & name, const PISystemMonitor * ptr, int col, FormatFlags format) { void PIConsole::addVariable(const PIString & name, const PISystemMonitor * ptr, int col, FormatFlags format) {
addString("monitor " + name, col, format | PIConsole::Bold); addString("monitor " + name, col, format | PIConsole::Bold);
//addVariable("PID", &(ptr->statistic().ID), col, format); //addVariable("PID", &(ptr->statistic().ID), col, format);
//addVariable("state", &(ptr->statistic().state), col, format); //addVariable("state", &(ptr->statistic().state), col, format);
//addVariable("threads", &(ptr->statistic().threads), col, format); //addVariable("threads", &(ptr->statistic().threads), col, format);
//addVariable("priority", &(ptr->statistic().priority), col, format); //addVariable("priority", &(ptr->statistic().priority), col, format);
//addVariable("memory physical", &(ptr->statistic().physical_memsize_readable), col, format); //addVariable("memory physical", &(ptr->statistic().physical_memsize_readable), col, format);
//addVariable("memory shared", &(ptr->statistic().share_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 kernel", &(ptr->statistic().cpu_load_system), col, format);
//addVariable("cpu load user", &(ptr->statistic().cpu_load_user), 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) { 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; 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);} checkColumn(col); column(col).push_back(tv);}
void PIConsole::addEmptyLine(int col, uint count) { void PIConsole::addEmptyLine(int col, uint count) {
tv.id = 0; tv.size = 0; tv.name = ""; tv.type = 0; tv.ptr = 0; tv.format = Normal; tv.id = 0; tv.size = 0; tv.name = ""; tv.type = 0; tv.ptr = 0; tv.format = Normal;
for (uint i = 0; i < count; ++i) { for (uint i = 0; i < count; ++i) {
checkColumn(col); checkColumn(col);
column(col).push_back(tv); column(col).push_back(tv);
} }
} }
PIString PIConsole::getString(int x, int y) { PIString PIConsole::getString(int x, int y) {
bool run = isRunning(); bool run = isRunning();
if (run) PIThread::stop(true); if (run) PIThread::stop(true);
listener->setActive(false); listener->setActive(false);
msleep(50); msleep(50);
#ifdef WINDOWS #ifdef WINDOWS
moveTo(x - 1, y - 1); moveTo(x - 1, y - 1);
#else #else
moveTo(x, y); moveTo(x, y);
#endif #endif
showCursor(); showCursor();
PIByteArray ba(4096); PIByteArray ba(4096);
#ifdef CC_VC #ifdef CC_VC
int ret = scanf_s(" %s", ba.data()); int ret = scanf_s(" %s", ba.data());
#else #else
int ret = scanf(" %s", ba.data()); int ret = scanf(" %s", ba.data());
#endif #endif
listener->setActive(true); listener->setActive(true);
if (run) start(); if (run) start();
if (ret >= 1) return PIString(ba); if (ret >= 1) return PIString(ba);
else return PIString(); else return PIString();
} }
PIString PIConsole::getString(const PIString & name) { PIString PIConsole::getString(const PIString & name) {
piForeachC (Column & i, tabs[cur_tab].columns) piForeachC (Column & i, tabs[cur_tab].columns)
piForeachC (Variable & j, i.variables) piForeachC (Variable & j, i.variables)
if (j.name == name) if (j.name == name)
return getString(j.nx + 1, j.ny); return getString(j.nx + 1, j.ny);
return PIString(); return PIString();
} }
#define PRINT_VAR_BODY couts(fstr(format)); int ret = couts(value); couts(fstr(PIConsole::Dec)); return ret; #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) { inline void PIConsole::printLine(const PIString & value, int dx, FormatFlags format) {
int i = width - value.length() - dx; int i = width - value.length() - dx;
#if defined(QNX) || defined(FREE_BSD) #if defined(QNX) || defined(FREE_BSD)
--i; --i;
#endif #endif
PIString ts = fstr(format); PIString ts = fstr(format);
couts(ts); couts(ts);
if (i >= 0) ts = value + PIString(i, ' '); if (i >= 0) ts = value + PIString(i, ' ');
else ts = value.left(value.size() + i); else ts = value.left(value.size() + i);
couts(ts); couts(ts);
couts(fstr(Dec)); couts(fstr(Dec));
} }
inline int PIConsole::printValue(const PIString & value, FormatFlags format) { inline int PIConsole::printValue(const PIString & value, FormatFlags format) {
couts(fstr(format)); couts(fstr(format));
int ret = couts(value); int ret = couts(value);
fstr(PIConsole::Dec); fstr(PIConsole::Dec);
return ret; return ret;
} }
inline int PIConsole::printValue(const char * value, FormatFlags format) {PRINT_VAR_BODY} 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 bool value, FormatFlags format) {PRINT_VAR_BODY}
inline int PIConsole::printValue(const int 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 long value, FormatFlags format) {PRINT_VAR_BODY}
inline int PIConsole::printValue(const llong 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 float value, FormatFlags format) {PRINT_VAR_BODY}
inline int PIConsole::printValue(const double 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 char value, FormatFlags format) {PRINT_VAR_BODY}
inline int PIConsole::printValue(const short 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 uchar value, FormatFlags format) {PRINT_VAR_BODY}
inline int PIConsole::printValue(const ushort 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 uint value, FormatFlags format) {PRINT_VAR_BODY}
inline int PIConsole::printValue(const ulong 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 ullong value, FormatFlags format) {PRINT_VAR_BODY}
inline int PIConsole::printValue(const PISystemTime & value, FormatFlags format) {PRINT_VAR_BODY} inline int PIConsole::printValue(const PISystemTime & value, FormatFlags format) {PRINT_VAR_BODY}
void PIConsole::startServer(const PIString & name) { void PIConsole::startServer(const PIString & name) {
stopPeer(); stopPeer();
server_mode = true; server_mode = true;
peer = new PIPeer("_rcs_:" + name); peer = new PIPeer("_rcs_:" + name);
CONNECT2(void, const PIString & , const PIByteArray &, peer, dataReceivedEvent, this, peerReceived); CONNECT2(void, const PIString & , const PIByteArray &, peer, dataReceivedEvent, this, peerReceived);
CONNECT1(void, const PIString & , peer, peerDisconnectedEvent, this, peerDisconnectedEvent); CONNECT1(void, const PIString & , peer, peerDisconnectedEvent, this, peerDisconnectedEvent);
peer_timer->start(50.); peer_timer->start(50.);
serverSendInfo(); serverSendInfo();
} }
void PIConsole::stopPeer() { void PIConsole::stopPeer() {
remote_clients.clear(); remote_clients.clear();
peer_timer->stop(); peer_timer->stop();
if (peer != 0) delete peer; if (peer != 0) delete peer;
peer = 0; peer = 0;
state = Disconnected; state = Disconnected;
} }
PIStringList PIConsole::clients() const { PIStringList PIConsole::clients() const {
PIStringList sl; PIStringList sl;
if (peer == 0) return sl; if (peer == 0) return sl;
piForeachC (PIPeer::PeerInfo & i, peer->allPeers()) { piForeachC (PIPeer::PeerInfo & i, peer->allPeers()) {
if (i.name.left(6) != "_rcc_:") continue; if (i.name.left(6) != "_rcc_:") continue;
sl << i.name.right(i.name.length() - 6); sl << i.name.right(i.name.length() - 6);
} }
return sl; return sl;
} }
void PIConsole::listenServers() { void PIConsole::listenServers() {
stopPeer(); stopPeer();
server_mode = false; server_mode = false;
server_name.clear(); server_name.clear();
randomize(); randomize();
peer = new PIPeer("_rcc_:" + PIDateTime::current().toString("hhmmssddMMyy_") + PIString::fromNumber(randomi())); peer = new PIPeer("_rcc_:" + PIDateTime::current().toString("hhmmssddMMyy_") + PIString::fromNumber(randomi()));
CONNECT2(void, const PIString & , const PIByteArray &, peer, dataReceivedEvent, this, peerReceived); CONNECT2(void, const PIString & , const PIByteArray &, peer, dataReceivedEvent, this, peerReceived);
peer_timer->start(100.); peer_timer->start(100.);
} }
PIStringList PIConsole::availableServers() const { PIStringList PIConsole::availableServers() const {
PIStringList sl; PIStringList sl;
if (peer == 0) return sl; if (peer == 0) return sl;
piForeachC (PIPeer::PeerInfo & i, peer->allPeers()) { piForeachC (PIPeer::PeerInfo & i, peer->allPeers()) {
if (i.name.left(6) != "_rcs_:") continue; if (i.name.left(6) != "_rcs_:") continue;
sl << i.name.right(i.name.length() - 6); sl << i.name.right(i.name.length() - 6);
} }
return sl; return sl;
} }
void PIConsole::connectToServer(const PIString & name) { void PIConsole::connectToServer(const PIString & name) {
if (peer == 0) listenServers(); if (peer == 0) listenServers();
server_name = name; server_name = name;
} }
void PIConsole::disconnect() { void PIConsole::disconnect() {
stopPeer(); stopPeer();
} }
void PIConsole::serverSendInfo() { void PIConsole::serverSendInfo() {
if (peer == 0) return; if (peer == 0) return;
PIByteArray ba; PIByteArray ba;
ba << int(0xAA); ba << int(0xAA);
peer->sendToAll(ba); peer->sendToAll(ba);
} }
void PIConsole::serverSendData() { void PIConsole::serverSendData() {
if (peer == 0) return; if (peer == 0) return;
PIByteArray ba; PIByteArray ba;
PIVector<VariableContent> content; PIVector<VariableContent> content;
piForeach (Tab & t, tabs) piForeach (Tab & t, tabs)
piForeach (Column & c, t.columns) piForeach (Column & c, t.columns)
piForeach (Variable & v, c.variables) piForeach (Variable & v, c.variables)
if (!v.isEmpty() && v.id > 0) { if (!v.isEmpty() && v.id > 0) {
VariableContent vc; VariableContent vc;
vc.id = v.id; vc.id = v.id;
v.writeData(vc.rdata); v.writeData(vc.rdata);
content << vc; content << vc;
} }
piForeach (RemoteClient & rc, remote_clients) { piForeach (RemoteClient & rc, remote_clients) {
ba.clear(); ba.clear();
switch (rc.state) { switch (rc.state) {
case FetchingData: case FetchingData:
ba << int(0xCC) << tabs; ba << int(0xCC) << tabs;
//piCout << "server send const data" << rc.name << ba.size_s(); //piCout << "server send const data" << rc.name << ba.size_s();
break; break;
case Committing: case Committing:
ba << int(0xDD); ba << int(0xDD);
break; break;
case Connected: case Connected:
ba << int(0xEE) << content; ba << int(0xEE) << content;
//piCout << "send data" << ba.size(); //piCout << "send data" << ba.size();
break; break;
default: break; default: break;
} }
if (!ba.isEmpty()) if (!ba.isEmpty())
peer->send(rc.name, ba); peer->send(rc.name, ba);
} }
} }
PIConsole::RemoteClient & PIConsole::remoteClient(const PIString & fname) { PIConsole::RemoteClient & PIConsole::remoteClient(const PIString & fname) {
piForeach (RemoteClient & i, remote_clients) piForeach (RemoteClient & i, remote_clients)
if (i.name == fname) if (i.name == fname)
return i; return i;
remote_clients << RemoteClient(fname); remote_clients << RemoteClient(fname);
return remote_clients.back(); return remote_clients.back();
} }
void PIConsole::peerReceived(const PIString & from, const PIByteArray & data) { void PIConsole::peerReceived(const PIString & from, const PIByteArray & data) {
int type; int type;
PIByteArray ba(data); PIByteArray ba(data);
ba >> type; ba >> type;
//piCout << "rec packet from" << from << "type" << PICoutManipulators::Hex << type; //piCout << "rec packet from" << from << "type" << PICoutManipulators::Hex << type;
if (server_mode) { if (server_mode) {
if (from.left(5) != "_rcc_") return; if (from.left(5) != "_rcc_") return;
//PIString rcn = from.right(from.length() - 6); //PIString rcn = from.right(from.length() - 6);
RemoteClient & rc(remoteClient(from)); RemoteClient & rc(remoteClient(from));
switch (type) { switch (type) {
case 0xBB: // fetch const data request case 0xBB: // fetch const data request
//piCout << "fetch data request from" << from << rc.state; //piCout << "fetch data request from" << from << rc.state;
if (rc.state != Connected) if (rc.state != Connected)
rc.state = FetchingData; rc.state = FetchingData;
break; break;
case 0xCC: // const data commit case 0xCC: // const data commit
//piCout << "commit from" << from; //piCout << "commit from" << from;
if (rc.state != Connected) if (rc.state != Connected)
rc.state = Connected; rc.state = Connected;
break; break;
default: break; default: break;
} }
} else { } else {
PIVector<VariableContent> content; PIVector<VariableContent> content;
PIMap<int, Variable * > vids; PIMap<int, Variable * > vids;
if (from.left(5) != "_rcs_") return; if (from.left(5) != "_rcs_") return;
//PIString rcn = from.right(from.length() - 6); //PIString rcn = from.right(from.length() - 6);
switch (type) { switch (type) {
case 0xAA: // new server case 0xAA: // new server
//piCout << "new server" << rcn; //piCout << "new server" << rcn;
break; break;
case 0xCC: // const data case 0xCC: // const data
//piCout << "received const data"; //piCout << "received const data";
state = Committing; state = Committing;
ba >> tabs; ba >> tabs;
cur_tab = tabs.isEmpty() ? -1 : 0; cur_tab = tabs.isEmpty() ? -1 : 0;
piForeach (Tab & t, tabs) piForeach (Tab & t, tabs)
piForeach (Column & c, t.columns) piForeach (Column & c, t.columns)
piForeach (Variable & v, c.variables) piForeach (Variable & v, c.variables)
v.remote = true; v.remote = true;
break; break;
case 0xDD: // const data commit case 0xDD: // const data commit
//piCout << "received commit"; //piCout << "received commit";
state = Connected; state = Connected;
break; break;
case 0xEE: // dynamic data case 0xEE: // dynamic data
//piCout << "received data" << ba.size_s(); //piCout << "received data" << ba.size_s();
piForeach (Tab & t, tabs) piForeach (Tab & t, tabs)
piForeach (Column & c, t.columns) piForeach (Column & c, t.columns)
piForeach (Variable & v, c.variables) piForeach (Variable & v, c.variables)
if (!v.isEmpty() && v.id > 0) if (!v.isEmpty() && v.id > 0)
vids[v.id] = &v; vids[v.id] = &v;
ba >> content; ba >> content;
piForeach (VariableContent & vc, content) { piForeach (VariableContent & vc, content) {
if (vc.id <= 0) continue; if (vc.id <= 0) continue;
Variable * v = vids.at(vc.id); Variable * v = vids.at(vc.id);
if (v == 0) continue; if (v == 0) continue;
//piCout << "read" << v->name << vc.rdata.size_s(); //piCout << "read" << v->name << vc.rdata.size_s();
v->rdata = vc.rdata; v->rdata = vc.rdata;
} }
break; break;
default: break; default: break;
} }
} }
} }
void PIConsole::peerTimer(void * data, int delim) { void PIConsole::peerTimer(void * data, int delim) {
if (peer == 0) return; if (peer == 0) return;
//piCout << "timer" << delim; //piCout << "timer" << delim;
if (server_mode) { if (server_mode) {
if (delim == 20) if (delim == 20)
serverSendInfo(); serverSendInfo();
else else
serverSendData(); serverSendData();
} else { } else {
if (delim != 1 || server_name.isEmpty()) return; if (delim != 1 || server_name.isEmpty()) return;
const PIPeer::PeerInfo * p = peer->getPeerByName("_rcs_:" + server_name); const PIPeer::PeerInfo * p = peer->getPeerByName("_rcs_:" + server_name);
if (p == 0) return; if (p == 0) return;
PIByteArray ba; PIByteArray ba;
switch (state) { switch (state) {
case Disconnected: case Disconnected:
peer_tm.reset(); peer_tm.reset();
ba << int(0xBB); ba << int(0xBB);
//piCout << "send to" << server_name << "fetch request disc"; //piCout << "send to" << server_name << "fetch request disc";
peer->send(p, ba); peer->send(p, ba);
state = FetchingData; state = FetchingData;
break; break;
case FetchingData: case FetchingData:
if (peer_tm.elapsed_s() < 3.) if (peer_tm.elapsed_s() < 3.)
return; return;
peer_tm.reset(); peer_tm.reset();
ba << int(0xBB); ba << int(0xBB);
//piCout << "send to" << server_name << "fetch request fd"; //piCout << "send to" << server_name << "fetch request fd";
peer->send(p, ba); peer->send(p, ba);
break; break;
case Committing: case Committing:
peer_tm.reset(); peer_tm.reset();
ba << int(0xCC); ba << int(0xCC);
//piCout << "send to" << server_name << "committing"; //piCout << "send to" << server_name << "committing";
state = Connected; state = Connected;
peer->send(p, ba); peer->send(p, ba);
break; break;
default: break; default: break;
}; };
} }
} }
void PIConsole::peerDisconnectedEvent(const PIString & name) { void PIConsole::peerDisconnectedEvent(const PIString & name) {
for (int i = 0; i < remote_clients.size_s(); ++i) for (int i = 0; i < remote_clients.size_s(); ++i)
if (remote_clients[i].name == name) { if (remote_clients[i].name == name) {
remote_clients.remove(i); remote_clients.remove(i);
--i; --i;
} }
} }

View File

@@ -1,645 +1,645 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Console output/input Console output/input
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "piscreen.h" #include "piscreen.h"
#include "piincludes_p.h" #include "piincludes_p.h"
#ifndef WINDOWS #ifndef WINDOWS
# include <sys/ioctl.h> # include <sys/ioctl.h>
# include <fcntl.h> # include <fcntl.h>
# include <termios.h> # include <termios.h>
#else #else
# include <wincon.h> # include <wincon.h>
# ifndef COMMON_LVB_UNDERSCORE # ifndef COMMON_LVB_UNDERSCORE
# define COMMON_LVB_UNDERSCORE 0x8000 # define COMMON_LVB_UNDERSCORE 0x8000
# endif # endif
#endif #endif
using namespace PIScreenTypes; using namespace PIScreenTypes;
PRIVATE_DEFINITION_START(PIScreen::SystemConsole) PRIVATE_DEFINITION_START(PIScreen::SystemConsole)
#ifdef WINDOWS #ifdef WINDOWS
void * hOut; void * hOut;
CONSOLE_SCREEN_BUFFER_INFO sbi, csbi; CONSOLE_SCREEN_BUFFER_INFO sbi, csbi;
CONSOLE_CURSOR_INFO curinfo; CONSOLE_CURSOR_INFO curinfo;
COORD ccoord, ulcoord, bs, bc; COORD ccoord, ulcoord, bs, bc;
SMALL_RECT srect; SMALL_RECT srect;
WORD dattr; WORD dattr;
DWORD smode, written; DWORD smode, written;
PIVector<CHAR_INFO> chars; PIVector<CHAR_INFO> chars;
#endif #endif
PRIVATE_DEFINITION_END(PIScreen::SystemConsole) PRIVATE_DEFINITION_END(PIScreen::SystemConsole)
PIScreen::SystemConsole::SystemConsole() { PIScreen::SystemConsole::SystemConsole() {
width = height = pwidth = pheight = 0; width = height = pwidth = pheight = 0;
mouse_x = mouse_y = -1; mouse_x = mouse_y = -1;
int w, h; int w, h;
#ifdef WINDOWS #ifdef WINDOWS
PRIVATE->ulcoord.X = 0; PRIVATE->ulcoord.X = 0;
PRIVATE->hOut = GetStdHandle(STD_OUTPUT_HANDLE); PRIVATE->hOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi); GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi);
PRIVATE->dattr = PRIVATE->sbi.wAttributes; PRIVATE->dattr = PRIVATE->sbi.wAttributes;
w = PRIVATE->sbi.srWindow.Right - PRIVATE->sbi.srWindow.Left; w = PRIVATE->sbi.srWindow.Right - PRIVATE->sbi.srWindow.Left;
h = PRIVATE->sbi.srWindow.Bottom - PRIVATE->sbi.srWindow.Top; h = PRIVATE->sbi.srWindow.Bottom - PRIVATE->sbi.srWindow.Top;
PRIVATE->ulcoord.Y = PRIVATE->sbi.srWindow.Top; PRIVATE->ulcoord.Y = PRIVATE->sbi.srWindow.Top;
GetConsoleMode(PRIVATE->hOut, &PRIVATE->smode); GetConsoleMode(PRIVATE->hOut, &PRIVATE->smode);
GetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo); GetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo);
#else #else
# ifdef FREERTOS # ifdef FREERTOS
w = 80; w = 80;
h = 24; h = 24;
# else # else
winsize ws; winsize ws;
ioctl(0, TIOCGWINSZ, &ws); ioctl(0, TIOCGWINSZ, &ws);
w = ws.ws_col; w = ws.ws_col;
h = ws.ws_row; h = ws.ws_row;
# endif # endif
#endif #endif
resize(w, h); resize(w, h);
} }
PIScreen::SystemConsole::~SystemConsole() { PIScreen::SystemConsole::~SystemConsole() {
#ifdef WINDOWS #ifdef WINDOWS
SetConsoleMode(PRIVATE->hOut, PRIVATE->smode); SetConsoleMode(PRIVATE->hOut, PRIVATE->smode);
SetConsoleTextAttribute(PRIVATE->hOut, PRIVATE->dattr); SetConsoleTextAttribute(PRIVATE->hOut, PRIVATE->dattr);
#endif #endif
} }
void PIScreen::SystemConsole::begin() { void PIScreen::SystemConsole::begin() {
#ifdef WINDOWS #ifdef WINDOWS
SetConsoleMode(PRIVATE->hOut, ENABLE_WRAP_AT_EOL_OUTPUT); SetConsoleMode(PRIVATE->hOut, ENABLE_WRAP_AT_EOL_OUTPUT);
GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi); GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi);
PRIVATE->bc.X = 0; PRIVATE->bc.X = 0;
PRIVATE->bc.Y = 0; PRIVATE->bc.Y = 0;
#endif #endif
clear(); clear();
hideCursor(); hideCursor();
} }
void PIScreen::SystemConsole::end() { void PIScreen::SystemConsole::end() {
#ifdef WINDOWS #ifdef WINDOWS
SetConsoleTextAttribute(PRIVATE->hOut, PRIVATE->dattr); SetConsoleTextAttribute(PRIVATE->hOut, PRIVATE->dattr);
#else #else
printf("\e[0m"); printf("\e[0m");
#endif #endif
moveTo(0, height); moveTo(0, height);
showCursor(); showCursor();
} }
void PIScreen::SystemConsole::prepare() { void PIScreen::SystemConsole::prepare() {
int w, h; int w, h;
#ifdef WINDOWS #ifdef WINDOWS
GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->csbi); GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->csbi);
w = PRIVATE->csbi.srWindow.Right - PRIVATE->csbi.srWindow.Left + 1; w = PRIVATE->csbi.srWindow.Right - PRIVATE->csbi.srWindow.Left + 1;
h = PRIVATE->csbi.srWindow.Bottom - PRIVATE->csbi.srWindow.Top + 1; h = PRIVATE->csbi.srWindow.Bottom - PRIVATE->csbi.srWindow.Top + 1;
#else #else
# ifdef FREERTOS # ifdef FREERTOS
w = 80; w = 80;
h = 24; h = 24;
# else # else
winsize ws; winsize ws;
ioctl(0, TIOCGWINSZ, &ws); ioctl(0, TIOCGWINSZ, &ws);
w = ws.ws_col; w = ws.ws_col;
h = ws.ws_row; h = ws.ws_row;
# endif # endif
#endif #endif
resize(w, h); resize(w, h);
} }
void PIScreen::SystemConsole::clear() { void PIScreen::SystemConsole::clear() {
for (int i = 0; i < cells.size_s(); ++i) for (int i = 0; i < cells.size_s(); ++i)
cells[i].fill(Cell()); cells[i].fill(Cell());
} }
void PIScreen::SystemConsole::resize(int w, int h) { void PIScreen::SystemConsole::resize(int w, int h) {
if (w == pwidth && h == pheight) return; if (w == pwidth && h == pheight) return;
width = piMaxi(w, 0); width = piMaxi(w, 0);
height = piMaxi(h, 0); height = piMaxi(h, 0);
pwidth = width; pwidth = width;
pheight = height; pheight = height;
cells.resize(height); cells.resize(height);
pcells.resize(height); pcells.resize(height);
for (int i = 0; i < height; ++i) { for (int i = 0; i < height; ++i) {
cells[i].resize(width); cells[i].resize(width);
pcells[i].resize(width, Cell(0)); pcells[i].resize(width, Cell(0));
} }
#ifdef WINDOWS #ifdef WINDOWS
PRIVATE->sbi.srWindow = PRIVATE->csbi.srWindow; PRIVATE->sbi.srWindow = PRIVATE->csbi.srWindow;
PRIVATE->chars.resize(width * height); PRIVATE->chars.resize(width * height);
#endif #endif
for (int i = 0; i < pcells.size_s(); ++i) for (int i = 0; i < pcells.size_s(); ++i)
pcells[i].fill(Cell()); pcells[i].fill(Cell());
clear(); clear();
clearScreen(); clearScreen();
} }
void PIScreen::SystemConsole::print() { void PIScreen::SystemConsole::print() {
if (mouse_x >= 0 && mouse_x < width && mouse_y >= 0 && mouse_y < height) { if (mouse_x >= 0 && mouse_x < width && mouse_y >= 0 && mouse_y < height) {
///cells[mouse_y][mouse_x].format.flags ^= Inverse; ///cells[mouse_y][mouse_x].format.flags ^= Inverse;
} }
#ifdef WINDOWS #ifdef WINDOWS
PRIVATE->srect = PRIVATE->sbi.srWindow; PRIVATE->srect = PRIVATE->sbi.srWindow;
int dx0 = -1, dx1 = -1, dy0 = -1, dy1 = -1; int dx0 = -1, dx1 = -1, dy0 = -1, dy1 = -1;
for (int j = 0; j < height; ++j) { for (int j = 0; j < height; ++j) {
PIVector<Cell> & ccv(cells[j]); PIVector<Cell> & ccv(cells[j]);
PIVector<Cell> & pcv(pcells[j]); PIVector<Cell> & pcv(pcells[j]);
for (int i = 0; i < width; ++i) for (int i = 0; i < width; ++i)
if (ccv[i] != pcv[i]) { if (ccv[i] != pcv[i]) {
if (dx0 < 0) { if (dx0 < 0) {
dx0 = dx1 = i; dx0 = dx1 = i;
dy0 = dy1 = j; dy0 = dy1 = j;
} else { } else {
dx0 = piMini(dx0, i); dx0 = piMini(dx0, i);
dx1 = piMaxi(dx1, i); dx1 = piMaxi(dx1, i);
dy0 = piMini(dy0, j); dy0 = piMini(dy0, j);
dy1 = piMaxi(dy1, j); dy1 = piMaxi(dy1, j);
} }
} }
} }
if (dx0 < 0) return; if (dx0 < 0) return;
int dw = dx1 - dx0 + 1, dh = dy1 - dy0 + 1; int dw = dx1 - dx0 + 1, dh = dy1 - dy0 + 1;
for (int i = 0; i < dw; ++i) for (int i = 0; i < dw; ++i)
for (int j = 0; j < dh; ++j) { for (int j = 0; j < dh; ++j) {
int k = j * dw + i; int k = j * dw + i;
Cell & c(cells[j + dy0][i + dx0]); Cell & c(cells[j + dy0][i + dx0]);
PRIVATE->chars[k].Char.UnicodeChar = 0; PRIVATE->chars[k].Char.UnicodeChar = 0;
PRIVATE->chars[k].Char.AsciiChar = c.symbol.toConsole1Byte(); PRIVATE->chars[k].Char.AsciiChar = c.symbol.toConsole1Byte();
PRIVATE->chars[k].Attributes = attributes(c); PRIVATE->chars[k].Attributes = attributes(c);
} }
//piCout << "draw" << dw << dh; //piCout << "draw" << dw << dh;
PRIVATE->bs.X = dw; PRIVATE->bs.X = dw;
PRIVATE->bs.Y = dh; PRIVATE->bs.Y = dh;
PRIVATE->srect.Left += dx0; PRIVATE->srect.Left += dx0;
PRIVATE->srect.Top += dy0; PRIVATE->srect.Top += dy0;
PRIVATE->srect.Right -= width - dx1 - 1; PRIVATE->srect.Right -= width - dx1 - 1;
PRIVATE->srect.Bottom -= height - dy1 - 1; PRIVATE->srect.Bottom -= height - dy1 - 1;
WriteConsoleOutput(PRIVATE->hOut, PRIVATE->chars.data(), PRIVATE->bs, PRIVATE->bc, &PRIVATE->srect); WriteConsoleOutput(PRIVATE->hOut, PRIVATE->chars.data(), PRIVATE->bs, PRIVATE->bc, &PRIVATE->srect);
#else #else
PIString s; PIString s;
int si = 0, sj = 0; int si = 0, sj = 0;
CellFormat prf(0xFFFF); CellFormat prf(0xFFFF);
for (int j = 0; j < height; ++j) { for (int j = 0; j < height; ++j) {
PIVector<Cell> & ccv(cells[j]); PIVector<Cell> & ccv(cells[j]);
PIVector<Cell> & pcv(pcells[j]); PIVector<Cell> & pcv(pcells[j]);
for (int i = 0; i < width; ++i) { for (int i = 0; i < width; ++i) {
Cell & cc(ccv[i]); Cell & cc(ccv[i]);
Cell & pc(pcv[i]); Cell & pc(pcv[i]);
if (cc != pc) { if (cc != pc) {
if (s.isEmpty()) { if (s.isEmpty()) {
si = i; si = i;
sj = j; sj = j;
} }
if (prf != cc.format) { if (prf != cc.format) {
prf = cc.format; prf = cc.format;
s += formatString(cc); s += formatString(cc);
} }
s += cc.symbol; s += cc.symbol;
} else { } else {
if (!s.isEmpty()) { if (!s.isEmpty()) {
moveTo(si, sj); moveTo(si, sj);
printf("%s", s.data()); printf("%s", s.data());
s.clear(); s.clear();
} }
} }
} }
if (!s.isEmpty()) { if (!s.isEmpty()) {
moveTo(si, sj); moveTo(si, sj);
printf("%s", s.data()); printf("%s", s.data());
s.clear(); s.clear();
} }
} }
printf("\e[0m"); printf("\e[0m");
fflush(0); fflush(0);
#endif #endif
pcells = cells; pcells = cells;
} }
#ifdef WINDOWS #ifdef WINDOWS
#define FOREGROUND_MASK (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE) #define FOREGROUND_MASK (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
#define BACKGROUND_MASK (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE) #define BACKGROUND_MASK (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
ushort PIScreen::SystemConsole::attributes(const PIScreenTypes::Cell & c) { ushort PIScreen::SystemConsole::attributes(const PIScreenTypes::Cell & c) {
WORD attr = PRIVATE->dattr; WORD attr = PRIVATE->dattr;
if (c.format.flags & Bold) attr |= FOREGROUND_INTENSITY; if (c.format.flags & Bold) attr |= FOREGROUND_INTENSITY;
else attr &= ~FOREGROUND_INTENSITY; else attr &= ~FOREGROUND_INTENSITY;
if (c.format.flags & Underline) attr |= COMMON_LVB_UNDERSCORE; if (c.format.flags & Underline) attr |= COMMON_LVB_UNDERSCORE;
else attr &= ~COMMON_LVB_UNDERSCORE; else attr &= ~COMMON_LVB_UNDERSCORE;
switch (c.format.color_char) { switch (c.format.color_char) {
case Black: attr = (attr & ~FOREGROUND_MASK); break; case Black: attr = (attr & ~FOREGROUND_MASK); break;
case Red: attr = (attr & ~FOREGROUND_MASK) | FOREGROUND_RED; break; case Red: attr = (attr & ~FOREGROUND_MASK) | FOREGROUND_RED; break;
case Green: attr = (attr & ~FOREGROUND_MASK) | FOREGROUND_GREEN; break; case Green: attr = (attr & ~FOREGROUND_MASK) | FOREGROUND_GREEN; break;
case Blue: attr = (attr & ~FOREGROUND_MASK) | FOREGROUND_BLUE; break; case Blue: attr = (attr & ~FOREGROUND_MASK) | FOREGROUND_BLUE; break;
case Cyan: attr = (attr & ~FOREGROUND_MASK) | FOREGROUND_GREEN | FOREGROUND_BLUE; break; case Cyan: attr = (attr & ~FOREGROUND_MASK) | FOREGROUND_GREEN | FOREGROUND_BLUE; break;
case Magenta: attr = (attr & ~FOREGROUND_MASK) | FOREGROUND_RED | FOREGROUND_BLUE; break; case Magenta: attr = (attr & ~FOREGROUND_MASK) | FOREGROUND_RED | FOREGROUND_BLUE; break;
case Yellow: attr = (attr & ~FOREGROUND_MASK) | FOREGROUND_RED | FOREGROUND_GREEN; break; case Yellow: attr = (attr & ~FOREGROUND_MASK) | FOREGROUND_RED | FOREGROUND_GREEN; break;
case White: attr = attr | FOREGROUND_MASK; break; case White: attr = attr | FOREGROUND_MASK; break;
} }
switch (c.format.color_back) { switch (c.format.color_back) {
case Black: attr = (attr & ~BACKGROUND_MASK); break; case Black: attr = (attr & ~BACKGROUND_MASK); break;
case Red: attr = (attr & ~BACKGROUND_MASK) | BACKGROUND_RED; break; case Red: attr = (attr & ~BACKGROUND_MASK) | BACKGROUND_RED; break;
case Green: attr = (attr & ~BACKGROUND_MASK) | BACKGROUND_GREEN; break; case Green: attr = (attr & ~BACKGROUND_MASK) | BACKGROUND_GREEN; break;
case Blue: attr = (attr & ~BACKGROUND_MASK) | BACKGROUND_BLUE; break; case Blue: attr = (attr & ~BACKGROUND_MASK) | BACKGROUND_BLUE; break;
case Cyan: attr = (attr & ~BACKGROUND_MASK) | BACKGROUND_GREEN | BACKGROUND_BLUE; break; case Cyan: attr = (attr & ~BACKGROUND_MASK) | BACKGROUND_GREEN | BACKGROUND_BLUE; break;
case Magenta: attr = (attr & ~BACKGROUND_MASK) | BACKGROUND_RED | BACKGROUND_BLUE; break; case Magenta: attr = (attr & ~BACKGROUND_MASK) | BACKGROUND_RED | BACKGROUND_BLUE; break;
case Yellow: attr = (attr & ~BACKGROUND_MASK) | BACKGROUND_RED | BACKGROUND_GREEN; break; case Yellow: attr = (attr & ~BACKGROUND_MASK) | BACKGROUND_RED | BACKGROUND_GREEN; break;
case White: attr = attr | BACKGROUND_MASK; break; case White: attr = attr | BACKGROUND_MASK; break;
} }
if ((c.format.flags & Inverse) == Inverse) { if ((c.format.flags & Inverse) == Inverse) {
uchar f = attr & 0xFF; uchar f = attr & 0xFF;
attr &= 0xFFFFFF00; attr &= 0xFFFFFF00;
f = (f << 4) | (f >> 4); f = (f << 4) | (f >> 4);
attr |= f; attr |= f;
} }
return attr; return attr;
} }
#undef FOREGROUND_MASK #undef FOREGROUND_MASK
#undef BACKGROUND_MASK #undef BACKGROUND_MASK
void PIScreen::SystemConsole::getWinCurCoord() { void PIScreen::SystemConsole::getWinCurCoord() {
GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->csbi); GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->csbi);
PRIVATE->ccoord = PRIVATE->csbi.dwCursorPosition; PRIVATE->ccoord = PRIVATE->csbi.dwCursorPosition;
} }
void PIScreen::SystemConsole::clearLine() { void PIScreen::SystemConsole::clearLine() {
getWinCurCoord(); getWinCurCoord();
FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, width - PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written); FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, width - PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written);
FillConsoleOutputCharacter(PRIVATE->hOut, ' ', width - PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written); FillConsoleOutputCharacter(PRIVATE->hOut, ' ', width - PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written);
} }
void PIScreen::SystemConsole::newLine() { void PIScreen::SystemConsole::newLine() {
getWinCurCoord(); getWinCurCoord();
PRIVATE->ccoord.X = 0; PRIVATE->ccoord.Y++; PRIVATE->ccoord.X = 0; PRIVATE->ccoord.Y++;
SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ccoord); SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ccoord);
} }
#else // WINDOWS #else // WINDOWS
PIString PIScreen::SystemConsole::formatString(const PIScreenTypes::Cell & c) { PIString PIScreen::SystemConsole::formatString(const PIScreenTypes::Cell & c) {
PIString ts("\e[0"); PIString ts("\e[0");
switch (c.format.color_char) { switch (c.format.color_char) {
case Black: ts += ";30"; break; case Black: ts += ";30"; break;
case Red: ts += ";31"; break; case Red: ts += ";31"; break;
case Green: ts += ";32"; break; case Green: ts += ";32"; break;
case Blue: ts += ";34"; break; case Blue: ts += ";34"; break;
case Cyan: ts += ";36"; break; case Cyan: ts += ";36"; break;
case Magenta: ts += ";35"; break; case Magenta: ts += ";35"; break;
case Yellow: ts += ";33"; break; case Yellow: ts += ";33"; break;
case White: ts += ";37"; break; case White: ts += ";37"; break;
} }
switch (c.format.color_back) { switch (c.format.color_back) {
case Black: ts += ";40"; break; case Black: ts += ";40"; break;
case Red: ts += ";41"; break; case Red: ts += ";41"; break;
case Green: ts += ";42"; break; case Green: ts += ";42"; break;
case Blue: ts += ";44"; break; case Blue: ts += ";44"; break;
case Cyan: ts += ";46"; break; case Cyan: ts += ";46"; break;
case Magenta: ts += ";45"; break; case Magenta: ts += ";45"; break;
case Yellow: ts += ";43"; break; case Yellow: ts += ";43"; break;
case White: ts += ";47"; break; case White: ts += ";47"; break;
} }
if ((c.format.flags & Bold) == Bold) ts += ";1"; if ((c.format.flags & Bold) == Bold) ts += ";1";
if ((c.format.flags & Underline) == Underline) ts += ";4"; if ((c.format.flags & Underline) == Underline) ts += ";4";
if ((c.format.flags & Blink) == Blink) ts += ";5"; if ((c.format.flags & Blink) == Blink) ts += ";5";
if ((c.format.flags & Inverse) == Inverse) ts += ";7"; if ((c.format.flags & Inverse) == Inverse) ts += ";7";
return ts + "m"; return ts + "m";
} }
#endif // WINDOWS #endif // WINDOWS
void PIScreen::SystemConsole::toUpperLeft() { void PIScreen::SystemConsole::toUpperLeft() {
#ifdef WINDOWS #ifdef WINDOWS
SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ulcoord); SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ulcoord);
#else #else
printf("\e[H"); printf("\e[H");
#endif #endif
} }
void PIScreen::SystemConsole::moveTo(int x, int y) { void PIScreen::SystemConsole::moveTo(int x, int y) {
#ifdef WINDOWS #ifdef WINDOWS
PRIVATE->ccoord.X = x; PRIVATE->ccoord.X = x;
PRIVATE->ccoord.Y = PRIVATE->ulcoord.Y + y; PRIVATE->ccoord.Y = PRIVATE->ulcoord.Y + y;
SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ccoord); SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ccoord);
#else #else
printf("\e[%d;%dH", y + 1, x + 1); printf("\e[%d;%dH", y + 1, x + 1);
#endif #endif
} }
void PIScreen::SystemConsole::clearScreen() { void PIScreen::SystemConsole::clearScreen() {
#ifdef WINDOWS #ifdef WINDOWS
toUpperLeft(); toUpperLeft();
FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, width * (height + 1), PRIVATE->ulcoord, &PRIVATE->written); FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, width * (height + 1), PRIVATE->ulcoord, &PRIVATE->written);
FillConsoleOutputCharacter(PRIVATE->hOut, ' ', width * (height + 1), PRIVATE->ulcoord, &PRIVATE->written); FillConsoleOutputCharacter(PRIVATE->hOut, ' ', width * (height + 1), PRIVATE->ulcoord, &PRIVATE->written);
#else #else
printf("\e[0m\e[H\e[J"); printf("\e[0m\e[H\e[J");
#endif #endif
} }
void PIScreen::SystemConsole::clearScreenLower() { void PIScreen::SystemConsole::clearScreenLower() {
#ifdef WINDOWS #ifdef WINDOWS
getWinCurCoord(); getWinCurCoord();
FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, width * height - width * PRIVATE->ccoord.Y + PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written); FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, width * height - width * PRIVATE->ccoord.Y + PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written);
FillConsoleOutputCharacter(PRIVATE->hOut, ' ', width * height - width * PRIVATE->ccoord.Y + PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written); FillConsoleOutputCharacter(PRIVATE->hOut, ' ', width * height - width * PRIVATE->ccoord.Y + PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written);
#else #else
printf("\e[0m\e[J"); printf("\e[0m\e[J");
#endif #endif
} }
void PIScreen::SystemConsole::hideCursor() { void PIScreen::SystemConsole::hideCursor() {
#ifdef WINDOWS #ifdef WINDOWS
PRIVATE->curinfo.bVisible = false; PRIVATE->curinfo.bVisible = false;
SetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo); SetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo);
#else #else
printf("\e[?25l"); printf("\e[?25l");
#endif #endif
} }
void PIScreen::SystemConsole::showCursor() { void PIScreen::SystemConsole::showCursor() {
#ifdef WINDOWS #ifdef WINDOWS
PRIVATE->curinfo.bVisible = true; PRIVATE->curinfo.bVisible = true;
SetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo); SetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo);
#else #else
printf("\e[?25h"); printf("\e[?25h");
#endif #endif
} }
PIScreen::PIScreen(bool startNow, PIKbdListener::KBFunc slot): PIThread(), drawer_(console.cells), root("rootTile") { PIScreen::PIScreen(bool startNow, PIKbdListener::KBFunc slot): PIThread(), drawer_(console.cells), root("rootTile") {
setName("screen"); setName("screen");
setPriority(piLow); setPriority(piLow);
needLockRun(true); needLockRun(true);
mouse_ = false; mouse_ = false;
ret_func = slot; ret_func = slot;
tile_focus = tile_dialog = 0; tile_focus = tile_dialog = 0;
root.screen = this; root.screen = this;
listener = new PIKbdListener(key_eventS, this, startNow); listener = new PIKbdListener(key_eventS, this, startNow);
CONNECTU(listener, mouseEvent, this, mouse_event); CONNECTU(listener, mouseEvent, this, mouse_event);
CONNECTU(listener, wheelEvent, this, wheel_event); CONNECTU(listener, wheelEvent, this, wheel_event);
if (startNow) start(); if (startNow) start();
} }
PIScreen::~PIScreen() { PIScreen::~PIScreen() {
if (isRunning()) if (isRunning())
stop(); stop();
PIThread::waitForFinish(10); PIThread::waitForFinish(10);
listener->waitForFinish(10); listener->waitForFinish(10);
delete listener; delete listener;
} }
void PIScreen::setMouseEnabled(bool on) { void PIScreen::setMouseEnabled(bool on) {
mouse_ = on; mouse_ = on;
console.mouse_x = console.mouse_y = -1; console.mouse_x = console.mouse_y = -1;
} }
void PIScreen::key_event(PIKbdListener::KeyEvent key) { void PIScreen::key_event(PIKbdListener::KeyEvent key) {
/** DEBUG /** DEBUG
if (ret_func != 0) ret_func(key, t); if (ret_func != 0) ret_func(key, t);
keyPressed(key, t); keyPressed(key, t);
return; return;
*/ */
PIScreenTile * rtile = rootTile(); PIScreenTile * rtile = rootTile();
if (tile_dialog) if (tile_dialog)
rtile = tile_dialog; rtile = tile_dialog;
bool used = nextFocus(rtile, key); bool used = nextFocus(rtile, key);
if (used) return; if (used) return;
if (!used && tile_focus) { if (!used && tile_focus) {
if (tile_focus->visible) { if (tile_focus->visible) {
if (tile_focus->keyEvent(key)) if (tile_focus->keyEvent(key))
return; return;
} }
} }
if (ret_func != 0) ret_func(key, data_); if (ret_func != 0) ret_func(key, data_);
keyPressed(key, data_); keyPressed(key, data_);
} }
PIVector<PIScreenTile * > PIScreen::prepareMouse(PIKbdListener::MouseEvent * e) { PIVector<PIScreenTile * > PIScreen::prepareMouse(PIKbdListener::MouseEvent * e) {
PIVector<PIScreenTile * > ret; PIVector<PIScreenTile * > ret;
if (!mouse_ || !e) return ret; if (!mouse_ || !e) return ret;
console.mouse_x = e->x; console.mouse_x = e->x;
console.mouse_y = e->y; console.mouse_y = e->y;
PIVector<PIScreenTile * > tl = tilesUnderMouse(e->x, e->y); PIVector<PIScreenTile * > tl = tilesUnderMouse(e->x, e->y);
bool ff = false; bool ff = false;
piForeachR (PIScreenTile * t, tl) { piForeachR (PIScreenTile * t, tl) {
if (!ff) { if (!ff) {
if (t->focus_flags[FocusOnMouse] && (e->action == PIKbdListener::MouseButtonPress)) { if (t->focus_flags[FocusOnMouse] && (e->action == PIKbdListener::MouseButtonPress)) {
t->setFocus(); t->setFocus();
ff = true; ff = true;
} }
if (t->focus_flags[FocusOnWheel] && (e->action == PIKbdListener::MouseWheel)) { if (t->focus_flags[FocusOnWheel] && (e->action == PIKbdListener::MouseWheel)) {
t->setFocus(); t->setFocus();
ff = true; ff = true;
} }
} }
} }
return tl; return tl;
} }
PIVector<PIScreenTile * > PIScreen::tilesUnderMouse(int x, int y) { PIVector<PIScreenTile * > PIScreen::tilesUnderMouse(int x, int y) {
PIVector<PIScreenTile * > ret; PIVector<PIScreenTile * > ret;
if (x < 0 || x >= console.width || y < 0 || y >= console.height) return ret; if (x < 0 || x >= console.width || y < 0 || y >= console.height) return ret;
PIScreenTile * ct = tile_dialog ? tile_dialog : rootTile(); PIScreenTile * ct = tile_dialog ? tile_dialog : rootTile();
bool f = true; bool f = true;
while (ct) { while (ct) {
if (!f) ret << ct; if (!f) ret << ct;
f = false; f = false;
ct = ct->childUnderMouse(x, y); ct = ct->childUnderMouse(x, y);
} }
return ret; return ret;
} }
void PIScreen::mouse_event(PIKbdListener::MouseEvent me) { void PIScreen::mouse_event(PIKbdListener::MouseEvent me) {
PIVector<PIScreenTile * > tl = prepareMouse(&me); PIVector<PIScreenTile * > tl = prepareMouse(&me);
if (tl.isEmpty()) return; if (tl.isEmpty()) return;
piForeachR (PIScreenTile * t, tl) piForeachR (PIScreenTile * t, tl)
if (t->mouseEvent(me)) piBreak; if (t->mouseEvent(me)) piBreak;
} }
void PIScreen::wheel_event(PIKbdListener::WheelEvent we) { void PIScreen::wheel_event(PIKbdListener::WheelEvent we) {
PIVector<PIScreenTile * > tl = prepareMouse(&we); PIVector<PIScreenTile * > tl = prepareMouse(&we);
if (tl.isEmpty()) return; if (tl.isEmpty()) return;
piForeachR (PIScreenTile * t, tl) piForeachR (PIScreenTile * t, tl)
if (t->wheelEvent(we)) piBreak; if (t->wheelEvent(we)) piBreak;
} }
bool PIScreen::nextFocus(PIScreenTile * rt, PIKbdListener::KeyEvent key) { bool PIScreen::nextFocus(PIScreenTile * rt, PIKbdListener::KeyEvent key) {
PIVector<PIScreenTile*> vtl = rt->children(true), ftl; PIVector<PIScreenTile*> vtl = rt->children(true), ftl;
piForeach (PIScreenTile * t, vtl) { piForeach (PIScreenTile * t, vtl) {
if (t->focus_flags[CanHasFocus]) if (t->focus_flags[CanHasFocus])
ftl << t; ftl << t;
} }
int ind = -1; int ind = -1;
for (int i = 0; i < ftl.size_s(); ++i) for (int i = 0; i < ftl.size_s(); ++i)
if (ftl[i] == tile_focus) { if (ftl[i] == tile_focus) {
ind = i; ind = i;
break; break;
} }
if (ind < 0) if (ind < 0)
tile_focus = 0; tile_focus = 0;
if (ftl.isEmpty()) if (ftl.isEmpty())
tile_focus = 0; tile_focus = 0;
else { else {
if (tile_focus) if (tile_focus)
if (!tile_focus->visible) if (!tile_focus->visible)
tile_focus = 0; tile_focus = 0;
int next = tile_focus ? 0 : 1; int next = tile_focus ? 0 : 1;
if (tile_focus) { if (tile_focus) {
if (tile_focus->focus_flags[NextByTab] && key.key == PIKbdListener::Tab) if (tile_focus->focus_flags[NextByTab] && key.key == PIKbdListener::Tab)
next = 1; next = 1;
if (tile_focus->focus_flags[NextByArrowsHorizontal]) { if (tile_focus->focus_flags[NextByArrowsHorizontal]) {
if (key.key == PIKbdListener::LeftArrow) next = -1; if (key.key == PIKbdListener::LeftArrow) next = -1;
if (key.key == PIKbdListener::RightArrow) next = 1; if (key.key == PIKbdListener::RightArrow) next = 1;
} }
if (tile_focus->focus_flags[NextByArrowsVertical]) { if (tile_focus->focus_flags[NextByArrowsVertical]) {
if (key.key == PIKbdListener::UpArrow) next = -1; if (key.key == PIKbdListener::UpArrow) next = -1;
if (key.key == PIKbdListener::DownArrow) next = 1; if (key.key == PIKbdListener::DownArrow) next = 1;
} }
} }
//piCout << ftl.size() << ind << next; //piCout << ftl.size() << ind << next;
if (next != 0) { if (next != 0) {
PIVector<PIScreenTile*> tl = rt->children(); PIVector<PIScreenTile*> tl = rt->children();
piForeach (PIScreenTile * t, tl) piForeach (PIScreenTile * t, tl)
t->has_focus = false; t->has_focus = false;
if (!ftl.isEmpty()) { if (!ftl.isEmpty()) {
ind += next; ind += next;
if (ind >= ftl.size_s()) ind = 0; if (ind >= ftl.size_s()) ind = 0;
if (ind < 0) ind = ftl.size_s() - 1; if (ind < 0) ind = ftl.size_s() - 1;
tile_focus = ftl[ind]; tile_focus = ftl[ind];
tile_focus->has_focus = true; tile_focus->has_focus = true;
} }
return true; return true;
} }
} }
return false; return false;
} }
void PIScreen::tileEventInternal(PIScreenTile * t, TileEvent e) { void PIScreen::tileEventInternal(PIScreenTile * t, TileEvent e) {
tileEvent(t, e); tileEvent(t, e);
} }
void PIScreen::tileRemovedInternal(PIScreenTile * t) { void PIScreen::tileRemovedInternal(PIScreenTile * t) {
if (tile_dialog == t) if (tile_dialog == t)
tile_dialog = 0; tile_dialog = 0;
} }
void PIScreen::tileSetFocusInternal(PIScreenTile * t) { void PIScreen::tileSetFocusInternal(PIScreenTile * t) {
PIScreenTile * rt = rootTile(); PIScreenTile * rt = rootTile();
if (tile_dialog) if (tile_dialog)
rt = tile_dialog; rt = tile_dialog;
PIVector<PIScreenTile*> tl = rt->children(), ftl; PIVector<PIScreenTile*> tl = rt->children(), ftl;
piForeach (PIScreenTile * i, tl) piForeach (PIScreenTile * i, tl)
i->has_focus = false; i->has_focus = false;
tile_focus = t; tile_focus = t;
if (!tile_focus) return; if (!tile_focus) return;
if (tile_focus->focus_flags[CanHasFocus]) if (tile_focus->focus_flags[CanHasFocus])
tile_focus->has_focus = true; tile_focus->has_focus = true;
} }
void PIScreen::setDialogTile(PIScreenTile * t) { void PIScreen::setDialogTile(PIScreenTile * t) {
tile_dialog = t; tile_dialog = t;
if (!tile_dialog) { if (!tile_dialog) {
nextFocus(&root); nextFocus(&root);
return; return;
} }
tile_dialog->setScreen(this); tile_dialog->setScreen(this);
tile_dialog->parent = 0; tile_dialog->parent = 0;
nextFocus(tile_dialog); nextFocus(tile_dialog);
} }
void PIScreen::waitForFinish() { void PIScreen::waitForFinish() {
WAIT_FOR_EXIT WAIT_FOR_EXIT
stop(); stop();
} }
void PIScreen::stop(bool clear) { void PIScreen::stop(bool clear) {
PIThread::stop(true); PIThread::stop(true);
if (clear) console.clearScreen(); if (clear) console.clearScreen();
#ifndef WINDOWS #ifndef WINDOWS
fflush(0); fflush(0);
#endif #endif
} }
void PIScreen::begin() { void PIScreen::begin() {
listener->start(); listener->start();
nextFocus(&root); nextFocus(&root);
console.begin(); console.begin();
} }
void PIScreen::run() { void PIScreen::run() {
console.prepare(); console.prepare();
root.width_ = drawer_.width = console.width; root.width_ = drawer_.width = console.width;
root.height_ = drawer_.height = console.height; root.height_ = drawer_.height = console.height;
root.layout(); root.layout();
root.drawEventInternal(&drawer_); root.drawEventInternal(&drawer_);
if (tile_dialog) { if (tile_dialog) {
int sw(0), sh(0); int sw(0), sh(0);
tile_dialog->sizeHint(sw, sh); tile_dialog->sizeHint(sw, sh);
sw = piClampi(sw, tile_dialog->minimumWidth, tile_dialog->maximumWidth); sw = piClampi(sw, tile_dialog->minimumWidth, tile_dialog->maximumWidth);
sh = piClampi(sh, tile_dialog->minimumHeight, tile_dialog->maximumHeight); sh = piClampi(sh, tile_dialog->minimumHeight, tile_dialog->maximumHeight);
tile_dialog->x_ = (console.width - sw) / 2; tile_dialog->x_ = (console.width - sw) / 2;
tile_dialog->y_ = (console.height - sh) / 2; tile_dialog->y_ = (console.height - sh) / 2;
tile_dialog->width_ = sw; tile_dialog->width_ = sw;
tile_dialog->height_ = sh; tile_dialog->height_ = sh;
tile_dialog->layout(); tile_dialog->layout();
int dx = tile_dialog->x_ - 1, dy = tile_dialog->y_ - 1, dw = tile_dialog->width_, dh = tile_dialog->height_; int dx = tile_dialog->x_ - 1, dy = tile_dialog->y_ - 1, dw = tile_dialog->width_, dh = tile_dialog->height_;
drawer_.drawFrame(dx, dy, dx + dw + 1, dy + dh + 1, (Color)tile_dialog->back_format.color_char, drawer_.drawFrame(dx, dy, dx + dw + 1, dy + dh + 1, (Color)tile_dialog->back_format.color_char,
(Color)tile_dialog->back_format.color_back, (CharFlags)tile_dialog->back_format.flags); (Color)tile_dialog->back_format.color_back, (CharFlags)tile_dialog->back_format.flags);
tile_dialog->drawEventInternal(&drawer_); tile_dialog->drawEventInternal(&drawer_);
} }
console.print(); console.print();
} }
void PIScreen::end() { void PIScreen::end() {
listener->stop(); listener->stop();
console.end(); console.end();
} }
PIScreenTile * PIScreen::tileByName(const PIString & name) { PIScreenTile * PIScreen::tileByName(const PIString & name) {
PIVector<PIScreenTile*> tl(tiles()); PIVector<PIScreenTile*> tl(tiles());
piForeach (PIScreenTile * t, tl) piForeach (PIScreenTile * t, tl)
if (t->name() == name) if (t->name() == name)
return t; return t;
return 0; return 0;
} }

View File

@@ -1,42 +1,42 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Tile for PIScreen with PIConsole API Tile for PIScreen with PIConsole API
Andrey Bychkov work.a.b@yandex.ru Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "piscreenconsole.h" #include "piscreenconsole.h"
using namespace PIScreenTypes; using namespace PIScreenTypes;
TileVars::TileVars(const PIString &n) : PIScreenTile(n) { TileVars::TileVars(const PIString &n) : PIScreenTile(n) {
alignment = Left; alignment = Left;
} }
void TileVars::sizeHint(int &w, int &h) const { void TileVars::sizeHint(int &w, int &h) const {
} }
void TileVars::drawEvent(PIScreenDrawer *d) { void TileVars::drawEvent(PIScreenDrawer *d) {
} }
PIScreenConsoleTile::PIScreenConsoleTile() { PIScreenConsoleTile::PIScreenConsoleTile() {
} }

View File

@@ -1,271 +1,271 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Console output/input Console output/input
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "piscreendrawer.h" #include "piscreendrawer.h"
// comment for use ascii instead of unicode symbols // comment for use ascii instead of unicode symbols
#define USE_UNICODE #define USE_UNICODE
using namespace PIScreenTypes; using namespace PIScreenTypes;
PIScreenDrawer::PIScreenDrawer(PIVector<PIVector<Cell> > & c): cells(c) { PIScreenDrawer::PIScreenDrawer(PIVector<PIVector<Cell> > & c): cells(c) {
arts_[LineVertical] = arts_[LineVertical] =
#ifdef USE_UNICODE #ifdef USE_UNICODE
PIChar::fromUTF8(""); PIChar::fromUTF8("");
#else #else
PIChar('|'); PIChar('|');
#endif #endif
arts_[LineHorizontal] = arts_[LineHorizontal] =
#ifdef USE_UNICODE #ifdef USE_UNICODE
PIChar::fromUTF8(""); PIChar::fromUTF8("");
#else #else
PIChar('-'); PIChar('-');
#endif #endif
arts_[Cross] = arts_[Cross] =
#ifdef USE_UNICODE #ifdef USE_UNICODE
PIChar::fromUTF8(""); PIChar::fromUTF8("");
#else #else
PIChar('+'); PIChar('+');
#endif #endif
arts_[CornerTopLeft] = arts_[CornerTopLeft] =
#ifdef USE_UNICODE #ifdef USE_UNICODE
PIChar::fromUTF8(""); PIChar::fromUTF8("");
#else #else
PIChar('+'); PIChar('+');
#endif #endif
arts_[CornerTopRight] = arts_[CornerTopRight] =
#ifdef USE_UNICODE #ifdef USE_UNICODE
PIChar::fromUTF8(""); PIChar::fromUTF8("");
#else #else
PIChar('+'); PIChar('+');
#endif #endif
arts_[CornerBottomLeft] = arts_[CornerBottomLeft] =
#ifdef USE_UNICODE #ifdef USE_UNICODE
PIChar::fromUTF8(""); PIChar::fromUTF8("");
#else #else
PIChar('+'); PIChar('+');
#endif #endif
arts_[CornerBottomRight] = arts_[CornerBottomRight] =
#ifdef USE_UNICODE #ifdef USE_UNICODE
PIChar::fromUTF8(""); PIChar::fromUTF8("");
#else #else
PIChar('+'); PIChar('+');
#endif #endif
arts_[Unchecked] = arts_[Unchecked] =
#ifdef USE_UNICODE #ifdef USE_UNICODE
PIChar::fromUTF8(""); PIChar::fromUTF8("");
#else #else
PIChar('O'); PIChar('O');
#endif #endif
arts_[Checked] = arts_[Checked] =
#ifdef USE_UNICODE #ifdef USE_UNICODE
PIChar::fromUTF8(""); PIChar::fromUTF8("");
#else #else
PIChar('0'); PIChar('0');
#endif #endif
} }
void PIScreenDrawer::clear() { void PIScreenDrawer::clear() {
clear(cells); clear(cells);
} }
void PIScreenDrawer::drawPixel(int x, int y, const PIChar & c, Color col_char, Color col_back, CharFlags flags_char) { void PIScreenDrawer::drawPixel(int x, int y, const PIChar & c, Color col_char, Color col_back, CharFlags flags_char) {
if (x < 0 || x >= width || y < 0 || y >= height) return; if (x < 0 || x >= width || y < 0 || y >= height) return;
cells[y][x].symbol = c; cells[y][x].symbol = c;
cells[y][x].format.color_char = col_char; cells[y][x].format.color_char = col_char;
cells[y][x].format.color_back = col_back; cells[y][x].format.color_back = col_back;
cells[y][x].format.flags = flags_char; cells[y][x].format.flags = flags_char;
} }
void PIScreenDrawer::drawLine(int x0, int y0, int x1, int y1, const PIChar & c, Color col_char, Color col_back, CharFlags flags_char) { void PIScreenDrawer::drawLine(int x0, int y0, int x1, int y1, const PIChar & c, Color col_char, Color col_back, CharFlags flags_char) {
if (x0 == x1 && y0 == y1) drawPixel(x0, y0, c, col_char, col_back, flags_char); if (x0 == x1 && y0 == y1) drawPixel(x0, y0, c, col_char, col_back, flags_char);
Cell cc; Cell cc;
cc.symbol = c; cc.symbol = c;
cc.format.color_char = col_char; cc.format.color_char = col_char;
cc.format.color_back = col_back; cc.format.color_back = col_back;
cc.format.flags = flags_char; cc.format.flags = flags_char;
int x = 0, y = 0; int x = 0, y = 0;
if (piAbsi(x1 - x0) >= piAbsi(y1 - y0)) { if (piAbsi(x1 - x0) >= piAbsi(y1 - y0)) {
float dy = (y1 - y0) / float(piAbsi(x1 - x0)), cy = y0; float dy = (y1 - y0) / float(piAbsi(x1 - x0)), cy = y0;
int dx = x0 < x1 ? 1 : -1; int dx = x0 < x1 ? 1 : -1;
for (int i = x0; i != x1; i += dx) { for (int i = x0; i != x1; i += dx) {
x = i; y = piRound(cy); x = i; y = piRound(cy);
if (x >= 0 && x < width && y >= 0 && y < height) if (x >= 0 && x < width && y >= 0 && y < height)
cells[y][x] = cc; cells[y][x] = cc;
cy += dy; cy += dy;
} }
y = piRound(cy); y = piRound(cy);
if (x1 >= 0 && x1 < width && y >= 0 && y < height) if (x1 >= 0 && x1 < width && y >= 0 && y < height)
cells[y][x1] = cc; cells[y][x1] = cc;
} else { } else {
float dx = (x1 - x0) / float(piAbsi(y1 - y0)), cx = x0; float dx = (x1 - x0) / float(piAbsi(y1 - y0)), cx = x0;
int dy = y0 < y1 ? 1 : -1; int dy = y0 < y1 ? 1 : -1;
for (int i = y0; i != y1; i += dy) { for (int i = y0; i != y1; i += dy) {
x = piRound(cx); y = i; x = piRound(cx); y = i;
if (x >= 0 && x < width && y >= 0 && y < height) if (x >= 0 && x < width && y >= 0 && y < height)
cells[y][x] = cc; cells[y][x] = cc;
cx += dx; cx += dx;
} }
x = piRound(cx); x = piRound(cx);
if (x >= 0 && x < width && y1 >= 0 && y1 < height) if (x >= 0 && x < width && y1 >= 0 && y1 < height)
cells[y1][x] = cc; cells[y1][x] = cc;
} }
} }
void PIScreenDrawer::drawRect(int x0, int y0, int x1, int y1, const PIChar & c, Color col_char, Color col_back, CharFlags flags_char) { void PIScreenDrawer::drawRect(int x0, int y0, int x1, int y1, const PIChar & c, Color col_char, Color col_back, CharFlags flags_char) {
if (x0 == x1 && y0 == y1) drawPixel(x0, y0, c, col_char, col_back, flags_char); if (x0 == x1 && y0 == y1) drawPixel(x0, y0, c, col_char, col_back, flags_char);
Cell cc; Cell cc;
cc.symbol = c; cc.symbol = c;
cc.format.color_char = col_char; cc.format.color_char = col_char;
cc.format.color_back = col_back; cc.format.color_back = col_back;
cc.format.flags = flags_char; cc.format.flags = flags_char;
int dx = x0 < x1 ? 1 : -1; int dx = x0 < x1 ? 1 : -1;
int dy = y0 < y1 ? 1 : -1; int dy = y0 < y1 ? 1 : -1;
int xs[2] = {x0, x1}; int xs[2] = {x0, x1};
int ys[2] = {y0, y1}; int ys[2] = {y0, y1};
for (int k = 0; k < 2; ++k) { for (int k = 0; k < 2; ++k) {
int j = ys[k]; int j = ys[k];
if (j >= 0 && j < height) { if (j >= 0 && j < height) {
PIVector<Cell> & cv(cells[j]); PIVector<Cell> & cv(cells[j]);
for (int i = x0; i != x1; i += dx) for (int i = x0; i != x1; i += dx)
if (i >= 0 && i < width) if (i >= 0 && i < width)
cv[i] = cc; cv[i] = cc;
} }
j = xs[k]; j = xs[k];
if (j >= 0 && j < width) { if (j >= 0 && j < width) {
for (int i = y0; i != y1; i += dy) for (int i = y0; i != y1; i += dy)
if (i >= 0 && i < height) if (i >= 0 && i < height)
cells[i][j] = cc; cells[i][j] = cc;
} }
} }
int i = x1, j = y1; int i = x1, j = y1;
if (i >= 0 && i < width && j >= 0 && j < height) if (i >= 0 && i < width && j >= 0 && j < height)
cells[j][i] = cc; cells[j][i] = cc;
} }
void PIScreenDrawer::drawFrame(int x0, int y0, int x1, int y1, Color col_char, Color col_back, CharFlags flags_char) { void PIScreenDrawer::drawFrame(int x0, int y0, int x1, int y1, Color col_char, Color col_back, CharFlags flags_char) {
if (x0 == x1 && y0 == y1) return; if (x0 == x1 && y0 == y1) return;
Cell cc; Cell cc;
cc.format.color_char = col_char; cc.format.color_char = col_char;
cc.format.color_back = col_back; cc.format.color_back = col_back;
cc.format.flags = flags_char; cc.format.flags = flags_char;
int dx = x0 < x1 ? 1 : -1; int dx = x0 < x1 ? 1 : -1;
int dy = y0 < y1 ? 1 : -1; int dy = y0 < y1 ? 1 : -1;
int xs[2] = {x0, x1}; int xs[2] = {x0, x1};
int ys[2] = {y0, y1}; int ys[2] = {y0, y1};
for (int k = 0; k < 2; ++k) { for (int k = 0; k < 2; ++k) {
int j = ys[k]; int j = ys[k];
if (j >= 0 && j < height) { if (j >= 0 && j < height) {
PIVector<Cell> & cv(cells[j]); PIVector<Cell> & cv(cells[j]);
cc.symbol = artChar(LineHorizontal); cc.symbol = artChar(LineHorizontal);
for (int i = x0 + 1; i != x1; i += dx) for (int i = x0 + 1; i != x1; i += dx)
if (i >= 0 && i < width) if (i >= 0 && i < width)
cv[i] = cc; cv[i] = cc;
} }
j = xs[k]; j = xs[k];
if (j >= 0 && j < width) { if (j >= 0 && j < width) {
cc.symbol = artChar(LineVertical); cc.symbol = artChar(LineVertical);
for (int i = y0 + 1; i != y1; i += dy) for (int i = y0 + 1; i != y1; i += dy)
if (i >= 0 && i < height) if (i >= 0 && i < height)
cells[i][j] = cc; cells[i][j] = cc;
} }
} }
int i = x0, j = y0; cc.symbol = artChar(CornerTopLeft); int i = x0, j = y0; cc.symbol = artChar(CornerTopLeft);
if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc; if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc;
i = x1, j = y0; cc.symbol = artChar(CornerTopRight); i = x1, j = y0; cc.symbol = artChar(CornerTopRight);
if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc; if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc;
i = x0, j = y1; cc.symbol = artChar(CornerBottomLeft); i = x0, j = y1; cc.symbol = artChar(CornerBottomLeft);
if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc; if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc;
i = x1, j = y1; cc.symbol = artChar(CornerBottomRight); i = x1, j = y1; cc.symbol = artChar(CornerBottomRight);
if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc; if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc;
} }
void PIScreenDrawer::fillRect(int x0, int y0, int x1, int y1, const PIChar & c, Color col_char, Color col_back, CharFlags flags_char) { void PIScreenDrawer::fillRect(int x0, int y0, int x1, int y1, const PIChar & c, Color col_char, Color col_back, CharFlags flags_char) {
if (x0 == x1 && y0 == y1) drawPixel(x0, y0, c, col_char, col_back, flags_char); if (x0 == x1 && y0 == y1) drawPixel(x0, y0, c, col_char, col_back, flags_char);
Cell cc; Cell cc;
cc.symbol = c; cc.symbol = c;
cc.format.color_char = col_char; cc.format.color_char = col_char;
cc.format.color_back = col_back; cc.format.color_back = col_back;
cc.format.flags = flags_char; cc.format.flags = flags_char;
int dx = x0 < x1 ? 1 : -1; int dx = x0 < x1 ? 1 : -1;
int dy = y0 < y1 ? 1 : -1; int dy = y0 < y1 ? 1 : -1;
for (int j = y0; j != y1; j += dy) for (int j = y0; j != y1; j += dy)
if (j >= 0 && j < height) { if (j >= 0 && j < height) {
PIVector<Cell> & cv(cells[j]); PIVector<Cell> & cv(cells[j]);
for (int i = x0; i != x1; i += dx) for (int i = x0; i != x1; i += dx)
if (i >= 0 && i < width) if (i >= 0 && i < width)
cv[i] = cc; cv[i] = cc;
} }
} }
void PIScreenDrawer::fillRect(int x0, int y0, int x1, int y1, PIVector<PIVector<Cell> > & content) { void PIScreenDrawer::fillRect(int x0, int y0, int x1, int y1, PIVector<PIVector<Cell> > & content) {
if (x0 > x1) piSwap(x0, x1); if (x0 > x1) piSwap(x0, x1);
if (y0 > y1) piSwap(y0, y1); if (y0 > y1) piSwap(y0, y1);
int w = x1 - x0; int w = x1 - x0;
int h = y1 - y0; int h = y1 - y0;
for (int j = 0; j < h; ++j) for (int j = 0; j < h; ++j)
if (j < piMini(height, content.size_s())) { if (j < piMini(height, content.size_s())) {
if ((j + y0) >= 0 && (j + y0) < height) { if ((j + y0) >= 0 && (j + y0) < height) {
PIVector<Cell> & cv(cells[y0 + j]); PIVector<Cell> & cv(cells[y0 + j]);
PIVector<Cell> & contv(content[j]); PIVector<Cell> & contv(content[j]);
for (int i = 0; i < piMini(w, contv.size_s()); ++i) for (int i = 0; i < piMini(w, contv.size_s()); ++i)
if ((i + x0) >= 0 && (i + x0) < width) if ((i + x0) >= 0 && (i + x0) < width)
cv[x0 + i] = contv[i]; cv[x0 + i] = contv[i];
} }
} }
} }
void PIScreenDrawer::clear(PIVector<PIVector<Cell> > & cells) { void PIScreenDrawer::clear(PIVector<PIVector<Cell> > & cells) {
for (int i = 0; i < cells.size_s(); ++i) for (int i = 0; i < cells.size_s(); ++i)
cells[i].fill(Cell()); cells[i].fill(Cell());
} }
void PIScreenDrawer::drawText(int x, int y, const PIString & s, Color col_char, Color col_back, CharFlags flags_char) { void PIScreenDrawer::drawText(int x, int y, const PIString & s, Color col_char, Color col_back, CharFlags flags_char) {
if (x < 0 || x >= width || y < 0 || y >= height) return; if (x < 0 || x >= width || y < 0 || y >= height) return;
PIVector<Cell> & cv(cells[y]); PIVector<Cell> & cv(cells[y]);
Cell cc; Cell cc;
cc.format.color_char = col_char; cc.format.color_char = col_char;
cc.format.color_back = col_back; cc.format.color_back = col_back;
cc.format.flags = flags_char; cc.format.flags = flags_char;
for (int i = 0; i < s.size_s(); ++i) { for (int i = 0; i < s.size_s(); ++i) {
int j = i + x; int j = i + x;
if (j >= 0 && j < width) { if (j >= 0 && j < width) {
cc.symbol = s[i]; cc.symbol = s[i];
cv[j] = cc; cv[j] = cc;
} }
} }
} }

View File

@@ -1,250 +1,250 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Basic PIScreen tile Basic PIScreen tile
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "piscreentile.h" #include "piscreentile.h"
#include "piscreendrawer.h" #include "piscreendrawer.h"
using namespace PIScreenTypes; using namespace PIScreenTypes;
PIScreenTile::PIScreenTile(const PIString & n, Direction d, SizePolicy p): PIObject(n) { PIScreenTile::PIScreenTile(const PIString & n, Direction d, SizePolicy p): PIObject(n) {
direction = d; direction = d;
size_policy = p; size_policy = p;
focus_flags = 0; focus_flags = 0;
screen = 0; screen = 0;
minimumWidth = minimumHeight = x_ = y_ = width_ = height_ = pw = ph = 0; minimumWidth = minimumHeight = x_ = y_ = width_ = height_ = pw = ph = 0;
maximumWidth = maximumHeight = 65535; maximumWidth = maximumHeight = 65535;
marginLeft = marginRight = marginTop = marginBottom = spacing = 0; marginLeft = marginRight = marginTop = marginBottom = spacing = 0;
parent = 0; parent = 0;
back_symbol = ' '; back_symbol = ' ';
visible = true; visible = true;
has_focus = false; has_focus = false;
} }
PIScreenTile::~PIScreenTile() { PIScreenTile::~PIScreenTile() {
//piCout << this << "~"; //piCout << this << "~";
if (screen) if (screen)
screen->tileRemovedInternal(this); screen->tileRemovedInternal(this);
setScreen(0); setScreen(0);
deleteChildren(); deleteChildren();
if (!parent) return; if (!parent) return;
parent->tiles.removeOne(this); parent->tiles.removeOne(this);
} }
void PIScreenTile::addTile(PIScreenTile * t) { void PIScreenTile::addTile(PIScreenTile * t) {
if (t == 0) return; if (t == 0) return;
if (tiles.contains(t)) return; if (tiles.contains(t)) return;
tiles << t; tiles << t;
t->parent = this; t->parent = this;
t->setScreen(screen); t->setScreen(screen);
} }
void PIScreenTile::takeTile(PIScreenTile * t) { void PIScreenTile::takeTile(PIScreenTile * t) {
if (!tiles.contains(t)) return; if (!tiles.contains(t)) return;
tiles.removeOne(t); tiles.removeOne(t);
t->parent = 0; t->parent = 0;
t->setScreen(0); t->setScreen(0);
} }
void PIScreenTile::removeTile(PIScreenTile * t) { void PIScreenTile::removeTile(PIScreenTile * t) {
if (!tiles.contains(t)) return; if (!tiles.contains(t)) return;
tiles.removeOne(t); tiles.removeOne(t);
t->parent = 0; t->parent = 0;
t->setScreen(0); t->setScreen(0);
delete t; delete t;
} }
PIVector<PIScreenTile * > PIScreenTile::children(bool only_visible) { PIVector<PIScreenTile * > PIScreenTile::children(bool only_visible) {
PIVector<PIScreenTile * > ret; PIVector<PIScreenTile * > ret;
piForeach (PIScreenTile * t, tiles) piForeach (PIScreenTile * t, tiles)
if (t->visible || !only_visible) if (t->visible || !only_visible)
ret << t << t->children(only_visible); ret << t << t->children(only_visible);
return ret; return ret;
} }
PIScreenTile * PIScreenTile::childUnderMouse(int x, int y) { PIScreenTile * PIScreenTile::childUnderMouse(int x, int y) {
piForeach (PIScreenTile * t, tiles) { piForeach (PIScreenTile * t, tiles) {
if (!t->visible) continue; if (!t->visible) continue;
if (x >= t->x_ && (x - t->x_) < t->width_ && if (x >= t->x_ && (x - t->x_) < t->width_ &&
y >= t->y_ && (y - t->y_) < t->height_) { y >= t->y_ && (y - t->y_) < t->height_) {
return t; return t;
} }
} }
return 0; return 0;
} }
void PIScreenTile::raiseEvent(TileEvent e) { void PIScreenTile::raiseEvent(TileEvent e) {
if (!screen) return; if (!screen) return;
screen->tileEventInternal(this, e); screen->tileEventInternal(this, e);
} }
void PIScreenTile::setScreen(PIScreenBase * s) { void PIScreenTile::setScreen(PIScreenBase * s) {
screen = s; screen = s;
piForeach (PIScreenTile * t, tiles) piForeach (PIScreenTile * t, tiles)
t->setScreen(s); t->setScreen(s);
} }
void PIScreenTile::deleteChildren() { void PIScreenTile::deleteChildren() {
piForeach (PIScreenTile * t, tiles) { piForeach (PIScreenTile * t, tiles) {
t->parent = 0; t->parent = 0;
delete t; delete t;
} }
tiles.clear(); tiles.clear();
} }
void PIScreenTile::setFocus() { void PIScreenTile::setFocus() {
if (!screen || !focus_flags[CanHasFocus]) return; if (!screen || !focus_flags[CanHasFocus]) return;
screen->tileSetFocusInternal(this); screen->tileSetFocusInternal(this);
} }
void PIScreenTile::drawEventInternal(PIScreenDrawer * d) { void PIScreenTile::drawEventInternal(PIScreenDrawer * d) {
if (!visible) { if (!visible) {
return; return;
} }
d->fillRect(x_, y_, x_ + width_, y_ + height_, back_symbol, (Color)back_format.color_char, (Color)back_format.color_back, back_format.flags); d->fillRect(x_, y_, x_ + width_, y_ + height_, back_symbol, (Color)back_format.color_char, (Color)back_format.color_back, back_format.flags);
drawEvent(d); drawEvent(d);
piForeach (PIScreenTile * t, tiles) piForeach (PIScreenTile * t, tiles)
t->drawEventInternal(d); t->drawEventInternal(d);
} }
void PIScreenTile::sizeHint(int & w, int & h) const { void PIScreenTile::sizeHint(int & w, int & h) const {
w = 0; w = 0;
h = 0; h = 0;
if (tiles.isEmpty()) return; if (tiles.isEmpty()) return;
int sl = spacing * (tiles.size_s() - 1); int sl = spacing * (tiles.size_s() - 1);
if (direction == Horizontal) w += sl; if (direction == Horizontal) w += sl;
else h += sl; else h += sl;
piForeachC (PIScreenTile * t, tiles) { piForeachC (PIScreenTile * t, tiles) {
if (!t->visible) continue; if (!t->visible) continue;
int cw(0), ch(0); int cw(0), ch(0);
t->sizeHint(cw, ch); t->sizeHint(cw, ch);
cw = piClampi(cw, t->minimumWidth, t->maximumWidth); cw = piClampi(cw, t->minimumWidth, t->maximumWidth);
ch = piClampi(ch, t->minimumHeight, t->maximumHeight); ch = piClampi(ch, t->minimumHeight, t->maximumHeight);
if (direction == Horizontal) { if (direction == Horizontal) {
w += cw; h = piMaxi(h, ch); w += cw; h = piMaxi(h, ch);
} else { } else {
h += ch; w = piMaxi(w, cw); h += ch; w = piMaxi(w, cw);
} }
} }
w += marginLeft + marginRight; w += marginLeft + marginRight;
h += marginTop + marginBottom; h += marginTop + marginBottom;
} }
void PIScreenTile::layout() { void PIScreenTile::layout() {
if (tiles.isEmpty() || !visible) return; if (tiles.isEmpty() || !visible) return;
int as(0), ts(0), ts2(0), ecnt(0), pcnt(0); int as(0), ts(0), ts2(0), ecnt(0), pcnt(0);
ts = (direction == Horizontal) ? (width_ - marginLeft - marginRight) : (height_ - marginTop - marginBottom); ts = (direction == Horizontal) ? (width_ - marginLeft - marginRight) : (height_ - marginTop - marginBottom);
ts2 = (direction != Horizontal) ? (width_ - marginLeft - marginRight) : (height_ - marginTop - marginBottom); ts2 = (direction != Horizontal) ? (width_ - marginLeft - marginRight) : (height_ - marginTop - marginBottom);
ts -= spacing * (tiles.size_s() - 1); ts -= spacing * (tiles.size_s() - 1);
PIVector<int> hints(tiles.size_s()); PIVector<int> hints(tiles.size_s());
PIVector<float> asizes(tiles.size_s()); PIVector<float> asizes(tiles.size_s());
for (int i = 0; i < tiles.size_s(); ++i) { for (int i = 0; i < tiles.size_s(); ++i) {
PIScreenTile * t(tiles[i]); PIScreenTile * t(tiles[i]);
int cw(0), ch(0), cs(0); int cw(0), ch(0), cs(0);
if (t->visible && t->needLayout()) { if (t->visible && t->needLayout()) {
t->sizeHint(cw, ch); t->sizeHint(cw, ch);
cw = piClampi(cw, t->minimumWidth, t->maximumWidth); cw = piClampi(cw, t->minimumWidth, t->maximumWidth);
ch = piClampi(ch, t->minimumHeight, t->maximumHeight); ch = piClampi(ch, t->minimumHeight, t->maximumHeight);
if (t->size_policy == Expanding) ++ecnt; if (t->size_policy == Expanding) ++ecnt;
if (t->size_policy == Preferred) ++pcnt; if (t->size_policy == Preferred) ++pcnt;
cs = (direction == Horizontal) ? cw : ch; cs = (direction == Horizontal) ? cw : ch;
as += cs; as += cs;
} }
hints[i] = cs; hints[i] = cs;
asizes[i] = 0.f; asizes[i] = 0.f;
} }
if (as <= ts) { if (as <= ts) {
int acnt(0); int acnt(0);
SizePolicy pol = Fixed; SizePolicy pol = Fixed;
if (ecnt > 0) { if (ecnt > 0) {
acnt = ecnt; acnt = ecnt;
pol = Expanding; pol = Expanding;
} else if (pcnt > 0) { } else if (pcnt > 0) {
acnt = pcnt; acnt = pcnt;
pol = Preferred; pol = Preferred;
} }
if (acnt > 0) { if (acnt > 0) {
float add_a = float(ts - as), add_s = add_a / acnt, add_da(0.); float add_a = float(ts - as), add_s = add_a / acnt, add_da(0.);
asizes.fill(add_s); asizes.fill(add_s);
PISet<int> max_tl; PISet<int> max_tl;
for (int i = 0; i < tiles.size_s(); ++i) { for (int i = 0; i < tiles.size_s(); ++i) {
if (tiles[i]->size_policy == pol && tiles[i]->visible && tiles[i]->needLayout()) { if (tiles[i]->size_policy == pol && tiles[i]->visible && tiles[i]->needLayout()) {
float maxs = (direction == Horizontal) ? tiles[i]->maximumWidth : tiles[i]->maximumHeight; float maxs = (direction == Horizontal) ? tiles[i]->maximumWidth : tiles[i]->maximumHeight;
if (hints[i] + asizes[i] > maxs) { if (hints[i] + asizes[i] > maxs) {
max_tl << i; max_tl << i;
float pas = asizes[i]; float pas = asizes[i];
asizes[i] = maxs - hints[i]; asizes[i] = maxs - hints[i];
acnt--; acnt--;
if (acnt > 0) { if (acnt > 0) {
pas = (pas - asizes[i]) / acnt; pas = (pas - asizes[i]) / acnt;
for (int j = 0; j < tiles.size_s(); ++j) { for (int j = 0; j < tiles.size_s(); ++j) {
if (i == j) continue; if (i == j) continue;
if (max_tl[j]) continue; if (max_tl[j]) continue;
if (tiles[j]->size_policy == pol && tiles[j]->visible && tiles[j]->needLayout()) if (tiles[j]->size_policy == pol && tiles[j]->visible && tiles[j]->needLayout())
asizes[j] += pas; asizes[j] += pas;
} }
} }
} }
} }
} }
for (int i = 0; i < tiles.size_s(); ++i) { for (int i = 0; i < tiles.size_s(); ++i) {
if (tiles[i]->size_policy == pol && tiles[i]->visible && tiles[i]->needLayout()) { if (tiles[i]->size_policy == pol && tiles[i]->visible && tiles[i]->needLayout()) {
int a = piRound(asizes[i] + add_da); int a = piRound(asizes[i] + add_da);
add_da += asizes[i] - a; add_da += asizes[i] - a;
hints[i] += a; hints[i] += a;
} }
} }
} }
} }
int cx = x_ + marginLeft, cy = y_ + marginTop; int cx = x_ + marginLeft, cy = y_ + marginTop;
for (int i = 0; i < tiles.size_s(); ++i) { for (int i = 0; i < tiles.size_s(); ++i) {
PIScreenTile * t = tiles[i]; PIScreenTile * t = tiles[i];
if (!t->visible || !t->needLayout()) continue; if (!t->visible || !t->needLayout()) continue;
t->x_ = cx; t->x_ = cx;
t->y_ = cy; t->y_ = cy;
if (direction == Horizontal) { if (direction == Horizontal) {
t->width_ = hints[i]; t->width_ = hints[i];
t->height_ = ts2; t->height_ = ts2;
cx += hints[i] + spacing; cx += hints[i] + spacing;
} else { } else {
t->width_ = ts2; t->width_ = ts2;
t->height_ = hints[i]; t->height_ = hints[i];
cy += hints[i] + spacing; cy += hints[i] + spacing;
} }
if (t->pw != t->width_ || t->ph != t->height_) if (t->pw != t->width_ || t->ph != t->height_)
t->resizeEvent(t->width_, t->height_); t->resizeEvent(t->width_, t->height_);
t->pw = t->width_; t->pw = t->width_;
t->ph = t->height_; t->ph = t->height_;
t->layout(); t->layout();
} }
} }

View File

@@ -1,714 +1,714 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Various tiles for PIScreen Various tiles for PIScreen
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "piscreentiles.h" #include "piscreentiles.h"
#include "piscreendrawer.h" #include "piscreendrawer.h"
using namespace PIScreenTypes; using namespace PIScreenTypes;
TileSimple::TileSimple(const PIString & n): PIScreenTile(n) { TileSimple::TileSimple(const PIString & n): PIScreenTile(n) {
alignment = Left; alignment = Left;
} }
TileSimple::TileSimple(const TileSimple::Row & r): PIScreenTile() { TileSimple::TileSimple(const TileSimple::Row & r): PIScreenTile() {
alignment = Left; alignment = Left;
content << r; content << r;
} }
void TileSimple::sizeHint(int & w, int & h) const { void TileSimple::sizeHint(int & w, int & h) const {
w = h = 0; w = h = 0;
piForeachC (Row & r, content) piForeachC (Row & r, content)
w = piMaxi(w, r.first.size_s()); w = piMaxi(w, r.first.size_s());
h = content.size_s(); h = content.size_s();
} }
void TileSimple::drawEvent(PIScreenDrawer * d) { void TileSimple::drawEvent(PIScreenDrawer * d) {
for (int i = 0; i < content.size_s(); ++i) { for (int i = 0; i < content.size_s(); ++i) {
Row & r(content[i]); Row & r(content[i]);
int rx = 0; int rx = 0;
switch (alignment) { switch (alignment) {
case Left: rx = x_; break; case Left: rx = x_; break;
case Center: rx = x_ + (width_ - r.first.size_s()) / 2; break; case Center: rx = x_ + (width_ - r.first.size_s()) / 2; break;
case Right: rx = x_ + width_ - r.first.size_s(); break; case Right: rx = x_ + width_ - r.first.size_s(); break;
}; };
d->drawText(rx, y_ + i, r.first, (Color)r.second.color_char, (Color)r.second.color_back, r.second.flags); d->drawText(rx, y_ + i, r.first, (Color)r.second.color_char, (Color)r.second.color_back, r.second.flags);
} }
} }
TileScrollBar::TileScrollBar(const PIString & n) { TileScrollBar::TileScrollBar(const PIString & n) {
direction = Vertical; direction = Vertical;
thickness = 1; thickness = 1;
minimum_ = value_ = 0; minimum_ = value_ = 0;
maximum_ = 100; maximum_ = 100;
} }
void TileScrollBar::setMinimum(int v) { void TileScrollBar::setMinimum(int v) {
minimum_ = v; minimum_ = v;
_check(); _check();
} }
void TileScrollBar::setMaximum(int v) { void TileScrollBar::setMaximum(int v) {
maximum_ = v; maximum_ = v;
_check(); _check();
} }
void TileScrollBar::setValue(int v) { void TileScrollBar::setValue(int v) {
value_ = v; value_ = v;
_check(); _check();
} }
void TileScrollBar::_check() { void TileScrollBar::_check() {
value_ = piClampi(value_, minimum_, maximum_); value_ = piClampi(value_, minimum_, maximum_);
} }
void TileScrollBar::sizeHint(int & w, int & h) const { void TileScrollBar::sizeHint(int & w, int & h) const {
w = h = 0; w = h = 0;
if (direction == Vertical) { if (direction == Vertical) {
w = thickness; w = thickness;
h = 255; h = 255;
} else { } else {
h = thickness; h = thickness;
w = 255; w = 255;
} }
} }
void TileScrollBar::drawEvent(PIScreenDrawer * d) { void TileScrollBar::drawEvent(PIScreenDrawer * d) {
line_char = d->artChar(direction == Vertical ? PIScreenDrawer::LineVertical : PIScreenDrawer::LineHorizontal); line_char = d->artChar(direction == Vertical ? PIScreenDrawer::LineVertical : PIScreenDrawer::LineHorizontal);
d->fillRect(x_, y_, x_ + width_, y_ + height_, line_char, Green); d->fillRect(x_, y_, x_ + width_, y_ + height_, line_char, Green);
if (value_ >= minimum_ && value_ <= maximum_) { if (value_ >= minimum_ && value_ <= maximum_) {
if (direction == Vertical) { if (direction == Vertical) {
int c = piRoundf((float(value_ - minimum_) / (maximum_ - minimum_)) * (height_ - 1)); int c = piRoundf((float(value_ - minimum_) / (maximum_ - minimum_)) * (height_ - 1));
d->drawLine(x_, y_ + c, x_ + width_ - 1, y_ + c, ' ', Green, Green); d->drawLine(x_, y_ + c, x_ + width_ - 1, y_ + c, ' ', Green, Green);
} else { } else {
int c = piRoundf((float(value_ - minimum_) / (maximum_ - minimum_)) * (width_ - 1)); int c = piRoundf((float(value_ - minimum_) / (maximum_ - minimum_)) * (width_ - 1));
d->drawLine(x_ + c, y_, x_ + c, y_ + height_ - 1, ' ', Green, Green); d->drawLine(x_ + c, y_, x_ + c, y_ + height_ - 1, ' ', Green, Green);
} }
} }
} }
bool TileScrollBar::mouseEvent(PIKbdListener::MouseEvent me) { bool TileScrollBar::mouseEvent(PIKbdListener::MouseEvent me) {
return true; return true;
} }
TileList::TileList(const PIString & n): PIScreenTile(n) { TileList::TileList(const PIString & n): PIScreenTile(n) {
alignment = Left; alignment = Left;
focus_flags = CanHasFocus | NextByArrowsHorizontal | NextByTab | FocusOnMouseOrWheel; focus_flags = CanHasFocus | NextByArrowsHorizontal | NextByTab | FocusOnMouseOrWheel;
lhei = offset = cur = 0; lhei = offset = cur = 0;
mouse_sel = false; mouse_sel = false;
selection_mode = NoSelection; selection_mode = NoSelection;
scroll = new TileScrollBar(); scroll = new TileScrollBar();
scroll->size_policy = Ignore; scroll->size_policy = Ignore;
addTile(scroll); addTile(scroll);
} }
void TileList::sizeHint(int & w, int & h) const { void TileList::sizeHint(int & w, int & h) const {
w = h = 0; w = h = 0;
piForeachC (Row & r, content) piForeachC (Row & r, content)
w = piMaxi(w, r.first.size_s()); w = piMaxi(w, r.first.size_s());
h = 3; h = 3;
} }
void TileList::resizeEvent(int w, int h) { void TileList::resizeEvent(int w, int h) {
scroll->x_ = x_ + width_ - 1; scroll->x_ = x_ + width_ - 1;
scroll->y_ = y_; scroll->y_ = y_;
scroll->width_ = 1; scroll->width_ = 1;
scroll->height_ = height_; scroll->height_ = height_;
} }
void TileList::drawEvent(PIScreenDrawer * d) { void TileList::drawEvent(PIScreenDrawer * d) {
lhei = height_ - 2; lhei = height_ - 2;
int is = piClampi(offset, 0, piMaxi(0, content.size_s() - 1)), ie = piClampi(offset + lhei, 0, content.size_s()); int is = piClampi(offset, 0, piMaxi(0, content.size_s() - 1)), ie = piClampi(offset + lhei, 0, content.size_s());
if (is > 0) d->drawText(x_, y_, PIString(" /\\ ").repeat(width_ / 4), Green, Default, Bold); if (is > 0) d->drawText(x_, y_, PIString(" /\\ ").repeat(width_ / 4), Green, Default, Bold);
if (ie < content.size_s()) d->drawText(x_, y_ + height_ - 1, PIString(" \\/ ").repeat(width_ / 4), Green, Default, Bold); if (ie < content.size_s()) d->drawText(x_, y_ + height_ - 1, PIString(" \\/ ").repeat(width_ / 4), Green, Default, Bold);
//piCout << is << ie << offset << lhei << content.size_s(); //piCout << is << ie << offset << lhei << content.size_s();
for (int i = is; i < ie; ++i) { for (int i = is; i < ie; ++i) {
Row & r(content[i]); Row & r(content[i]);
bool sel = i == cur && has_focus; bool sel = i == cur && has_focus;
if (sel) { if (sel) {
int cy = y_ + i - is + 1; int cy = y_ + i - is + 1;
d->drawLine(x_, cy, x_ + width_ - 2, cy, ' ', Default, Blue); d->drawLine(x_, cy, x_ + width_ - 2, cy, ' ', Default, Blue);
} }
int rx(0); int rx(0);
switch (alignment) { switch (alignment) {
case Left: rx = x_; break; case Left: rx = x_; break;
case Center: rx = x_ + (width_ - 1 - r.first.size_s()) / 2; break; case Center: rx = x_ + (width_ - 1 - r.first.size_s()) / 2; break;
case Right: rx = x_ + width_ - 1 - r.first.size_s(); break; case Right: rx = x_ + width_ - 1 - r.first.size_s(); break;
}; };
CharFlags cf = r.second.flags; CharFlags cf = r.second.flags;
Color cc = (Color)r.second.color_char; Color cc = (Color)r.second.color_char;
if (selected[i]) { if (selected[i]) {
cf |= Bold; cf |= Bold;
cc = Yellow; cc = Yellow;
} }
d->drawText(rx, y_ + i - is + 1, r.first, cc, sel ? Blue : Default, cf); d->drawText(rx, y_ + i - is + 1, r.first, cc, sel ? Blue : Default, cf);
} }
scroll->setMaximum(piMaxi(0, content.size_s() - 1)); scroll->setMaximum(piMaxi(0, content.size_s() - 1));
scroll->setValue(cur); scroll->setValue(cur);
} }
bool TileList::keyEvent(PIKbdListener::KeyEvent key) { bool TileList::keyEvent(PIKbdListener::KeyEvent key) {
lhei = height_ - 2; lhei = height_ - 2;
int oo(0), osp = piMini(3, lhei / 4); int oo(0), osp = piMini(3, lhei / 4);
switch (key.key) { switch (key.key) {
case PIKbdListener::PageUp: case PIKbdListener::PageUp:
cur -= lhei / 2; cur -= lhei / 2;
oo -= lhei / 2; oo -= lhei / 2;
case PIKbdListener::UpArrow: case PIKbdListener::UpArrow:
cur--; cur--;
oo--; oo--;
if (key.modifiers[PIKbdListener::Ctrl]) { if (key.modifiers[PIKbdListener::Ctrl]) {
cur -= 4; cur -= 4;
oo -= 4; oo -= 4;
} }
if (cur < 0) cur = 0; if (cur < 0) cur = 0;
if (cur - offset < osp) offset += oo; if (cur - offset < osp) offset += oo;
if (offset < 0) offset = 0; if (offset < 0) offset = 0;
return true; return true;
case PIKbdListener::Space: case PIKbdListener::Space:
if (cur < 0 || cur >= content.size_s()) return true; if (cur < 0 || cur >= content.size_s()) return true;
switch (selection_mode) { switch (selection_mode) {
case NoSelection: return false; case NoSelection: return false;
case SingleSelection: case SingleSelection:
if (selected.isEmpty()) selected << cur; if (selected.isEmpty()) selected << cur;
else { else {
bool add = !selected[cur]; bool add = !selected[cur];
selected.clear(); selected.clear();
if (add) selected << cur; if (add) selected << cur;
} }
raiseEvent(TileEvent(SelectionChanged)); raiseEvent(TileEvent(SelectionChanged));
return true; return true;
case MultiSelection: case MultiSelection:
if (selected[cur]) selected.remove(cur); if (selected[cur]) selected.remove(cur);
else selected << cur; else selected << cur;
raiseEvent(TileEvent(SelectionChanged)); raiseEvent(TileEvent(SelectionChanged));
break; break;
} }
case PIKbdListener::PageDown: case PIKbdListener::PageDown:
if (key.key == PIKbdListener::PageDown) { if (key.key == PIKbdListener::PageDown) {
cur += lhei / 2; cur += lhei / 2;
oo += lhei / 2; oo += lhei / 2;
} }
case PIKbdListener::DownArrow: case PIKbdListener::DownArrow:
cur++; cur++;
oo++; oo++;
if (key.modifiers[PIKbdListener::Ctrl]) { if (key.modifiers[PIKbdListener::Ctrl]) {
cur += 4; cur += 4;
oo += 4; oo += 4;
} }
if (cur >= content.size_s()) cur = content.size_s() - 1; if (cur >= content.size_s()) cur = content.size_s() - 1;
if (cur - offset >= lhei - osp) offset += oo; if (cur - offset >= lhei - osp) offset += oo;
if (offset >= content.size_s() - lhei) offset = content.size_s() - lhei; if (offset >= content.size_s() - lhei) offset = content.size_s() - lhei;
if (offset < 0) offset = 0; if (offset < 0) offset = 0;
return true; return true;
case PIKbdListener::Home: case PIKbdListener::Home:
cur = offset = 0; cur = offset = 0;
return true; return true;
case PIKbdListener::End: case PIKbdListener::End:
cur = content.size_s() - 1; cur = content.size_s() - 1;
offset = content.size_s() - lhei; offset = content.size_s() - lhei;
if (offset < 0) offset = 0; if (offset < 0) offset = 0;
return true; return true;
case PIKbdListener::Return: case PIKbdListener::Return:
if (cur >= 0 && cur < content.size_s()) if (cur >= 0 && cur < content.size_s())
raiseEvent(TileEvent(RowPressed, cur)); raiseEvent(TileEvent(RowPressed, cur));
return true; return true;
case '*': case '*':
if (selection_mode == TileList::MultiSelection) { if (selection_mode == TileList::MultiSelection) {
PISet<int> nsel; PISet<int> nsel;
for (int i = 0; i < content.size_s(); ++i) for (int i = 0; i < content.size_s(); ++i)
if (!selected[i]) nsel << i; if (!selected[i]) nsel << i;
selected = nsel; selected = nsel;
} }
raiseEvent(TileEvent(SelectionChanged)); raiseEvent(TileEvent(SelectionChanged));
return true; return true;
case 'A': case 'A':
if (selection_mode == TileList::MultiSelection) { if (selection_mode == TileList::MultiSelection) {
selected.clear(); selected.clear();
for (int i = 0; i < content.size_s(); ++i) for (int i = 0; i < content.size_s(); ++i)
selected << i; selected << i;
} }
raiseEvent(TileEvent(SelectionChanged)); raiseEvent(TileEvent(SelectionChanged));
return true; return true;
} }
return PIScreenTile::keyEvent(key); return PIScreenTile::keyEvent(key);
} }
bool TileList::mouseEvent(PIKbdListener::MouseEvent me) { bool TileList::mouseEvent(PIKbdListener::MouseEvent me) {
if (me.action == PIKbdListener::MouseButtonRelease) return true; if (me.action == PIKbdListener::MouseButtonRelease) return true;
int mp = me.y - y() - 1 + offset; int mp = me.y - y() - 1 + offset;
if (mp < 0 || mp >= content.size_s()) return true; if (mp < 0 || mp >= content.size_s()) return true;
cur = mp; cur = mp;
switch (me.action) { switch (me.action) {
case PIKbdListener::MouseButtonPress: case PIKbdListener::MouseButtonPress:
mouse_sel = !selected.contains(cur); mouse_sel = !selected.contains(cur);
break; break;
case PIKbdListener::MouseButtonDblClick: case PIKbdListener::MouseButtonDblClick:
keyEvent(PIKbdListener::KeyEvent(PIKbdListener::Return)); keyEvent(PIKbdListener::KeyEvent(PIKbdListener::Return));
return true; return true;
default: break; default: break;
} }
if (me.buttons[PIKbdListener::MouseRight]) { if (me.buttons[PIKbdListener::MouseRight]) {
switch (selection_mode) { switch (selection_mode) {
case SingleSelection: case SingleSelection:
selected.clear(); selected.clear();
selected << cur; selected << cur;
raiseEvent(TileEvent(SelectionChanged)); raiseEvent(TileEvent(SelectionChanged));
break; break;
case MultiSelection: case MultiSelection:
if (mouse_sel) selected << cur; if (mouse_sel) selected << cur;
else selected.remove(cur); else selected.remove(cur);
raiseEvent(TileEvent(SelectionChanged)); raiseEvent(TileEvent(SelectionChanged));
break; break;
default: break; default: break;
} }
} }
return true; return true;
} }
bool TileList::wheelEvent(PIKbdListener::WheelEvent we) { bool TileList::wheelEvent(PIKbdListener::WheelEvent we) {
keyEvent(PIKbdListener::KeyEvent(we.direction ? PIKbdListener::PageUp : PIKbdListener::PageDown)); keyEvent(PIKbdListener::KeyEvent(we.direction ? PIKbdListener::PageUp : PIKbdListener::PageDown));
return true; return true;
} }
TileButton::TileButton(const PIString & n): PIScreenTile(n) { TileButton::TileButton(const PIString & n): PIScreenTile(n) {
focus_flags = CanHasFocus | NextByTab | NextByArrowsAll | FocusOnMouse; focus_flags = CanHasFocus | NextByTab | NextByArrowsAll | FocusOnMouse;
} }
void TileButton::sizeHint(int & w, int & h) const { void TileButton::sizeHint(int & w, int & h) const {
w = text.size_s() + 2; w = text.size_s() + 2;
h = 1; h = 1;
} }
void TileButton::drawEvent(PIScreenDrawer * d) { void TileButton::drawEvent(PIScreenDrawer * d) {
Color cb = has_focus ? Blue : Cyan; Color cb = has_focus ? Blue : Cyan;
Color ct = has_focus ? White : Black; Color ct = has_focus ? White : Black;
int ff = has_focus ? Bold : 0; int ff = has_focus ? Bold : 0;
d->fillRect(x_, y_, x_ + width_, y_ + 1, ' ', Default, cb); d->fillRect(x_, y_, x_ + width_, y_ + 1, ' ', Default, cb);
d->drawText(x_, y_, "[", ct, Transparent, ff); d->drawText(x_, y_, "[", ct, Transparent, ff);
d->drawText(x_ + (width_ - text.size_s()) / 2, y_, text, ct, Transparent, ff); d->drawText(x_ + (width_ - text.size_s()) / 2, y_, text, ct, Transparent, ff);
d->drawText(x_ + width_ - 1, y_, "]", ct, Transparent, ff); d->drawText(x_ + width_ - 1, y_, "]", ct, Transparent, ff);
} }
bool TileButton::keyEvent(PIKbdListener::KeyEvent key) { bool TileButton::keyEvent(PIKbdListener::KeyEvent key) {
if (key.key == PIKbdListener::Space || key.key == PIKbdListener::Return) { if (key.key == PIKbdListener::Space || key.key == PIKbdListener::Return) {
raiseEvent(TileEvent(ButtonClicked)); raiseEvent(TileEvent(ButtonClicked));
return true; return true;
} }
return PIScreenTile::keyEvent(key); return PIScreenTile::keyEvent(key);
} }
bool TileButton::mouseEvent(PIKbdListener::MouseEvent me) { bool TileButton::mouseEvent(PIKbdListener::MouseEvent me) {
if (me.action != PIKbdListener::MouseButtonRelease) return true; if (me.action != PIKbdListener::MouseButtonRelease) return true;
keyEvent(PIKbdListener::KeyEvent(PIKbdListener::Return)); keyEvent(PIKbdListener::KeyEvent(PIKbdListener::Return));
return true; return true;
} }
TileButtons::TileButtons(const PIString & n): PIScreenTile(n) { TileButtons::TileButtons(const PIString & n): PIScreenTile(n) {
focus_flags = CanHasFocus | NextByTab | FocusOnMouse; focus_flags = CanHasFocus | NextByTab | FocusOnMouse;
direction = Horizontal; direction = Horizontal;
alignment = PIScreenTypes::Center; alignment = PIScreenTypes::Center;
cur = 0; cur = 0;
} }
void TileButtons::sizeHint(int & w, int & h) const { void TileButtons::sizeHint(int & w, int & h) const {
w = h = 0; w = h = 0;
if (direction == Horizontal) { if (direction == Horizontal) {
piForeachC (Button & b, content) piForeachC (Button & b, content)
w += b.first.size_s() + 4; w += b.first.size_s() + 4;
w += piMaxi(0, content.size_s() - 1) * 2; w += piMaxi(0, content.size_s() - 1) * 2;
h += 1; h += 1;
} else { } else {
piForeachC (Button & b, content) piForeachC (Button & b, content)
w = piMaxi(w, b.first.size_s() + 4); w = piMaxi(w, b.first.size_s() + 4);
h += content.size_s(); h += content.size_s();
h += piMaxi(0, content.size_s() - 1); h += piMaxi(0, content.size_s() - 1);
} }
} }
void TileButtons::drawEvent(PIScreenDrawer * d) { void TileButtons::drawEvent(PIScreenDrawer * d) {
int cx = x_, cy = y_, shw, shh; int cx = x_, cy = y_, shw, shh;
sizeHint(shw, shh); sizeHint(shw, shh);
btn_rects.resize(content.size()); btn_rects.resize(content.size());
int dx = 0; int dx = 0;
switch (alignment) { switch (alignment) {
case PIScreenTypes::Center: dx = (width_ - shw) / 2; break; case PIScreenTypes::Center: dx = (width_ - shw) / 2; break;
case PIScreenTypes::Right: dx = width_ - shw; break; case PIScreenTypes::Right: dx = width_ - shw; break;
default: break; default: break;
} }
if (direction == PIScreenTypes::Horizontal) if (direction == PIScreenTypes::Horizontal)
cx += dx; cx += dx;
for (int i = 0; i < content.size_s(); ++i) { for (int i = 0; i < content.size_s(); ++i) {
Color cb = Cyan; Color cb = Cyan;
Color ct = Black; Color ct = Black;
int ff = 0; int ff = 0;
if (i == cur && has_focus) { if (i == cur && has_focus) {
cb = Blue; cb = Blue;
ct = White; ct = White;
ff = Bold; ff = Bold;
} }
Button & b(content[i]); Button & b(content[i]);
int cw = b.first.size_s() + 2, xo(0); int cw = b.first.size_s() + 2, xo(0);
if (direction == Vertical) { if (direction == Vertical) {
cw = width_ - 2; cw = width_ - 2;
xo = (cw - b.first.size_s()) / 2 - 1; xo = (cw - b.first.size_s()) / 2 - 1;
} }
btn_rects[i] = Rect(cx, cy, cx + cw + 2, cy + 1); btn_rects[i] = Rect(cx, cy, cx + cw + 2, cy + 1);
d->fillRect(cx, cy, cx + cw + 2, cy + 1, ' ', Default, cb); d->fillRect(cx, cy, cx + cw + 2, cy + 1, ' ', Default, cb);
d->drawText(cx, cy, "[", ct, Transparent, ff); d->drawText(cx, cy, "[", ct, Transparent, ff);
d->drawText(cx + xo + 2, cy, b.first, ct, Transparent, ff); d->drawText(cx + xo + 2, cy, b.first, ct, Transparent, ff);
d->drawText(cx + cw + 1, cy, "]", ct, Transparent, ff); d->drawText(cx + cw + 1, cy, "]", ct, Transparent, ff);
if (direction == Horizontal) if (direction == Horizontal)
cx += b.first.size_s() + 6; cx += b.first.size_s() + 6;
else else
cy += 2; cy += 2;
} }
} }
bool TileButtons::keyEvent(PIKbdListener::KeyEvent key) { bool TileButtons::keyEvent(PIKbdListener::KeyEvent key) {
switch (key.key) { switch (key.key) {
case PIKbdListener::LeftArrow: case PIKbdListener::LeftArrow:
case PIKbdListener::UpArrow: case PIKbdListener::UpArrow:
cur--; cur--;
if (cur < 0) cur = 0; if (cur < 0) cur = 0;
return true; return true;
case PIKbdListener::RightArrow: case PIKbdListener::RightArrow:
case PIKbdListener::DownArrow: case PIKbdListener::DownArrow:
cur++; cur++;
if (cur >= content.size_s()) cur = content.size_s() - 1; if (cur >= content.size_s()) cur = content.size_s() - 1;
return true; return true;
case PIKbdListener::Space: case PIKbdListener::Space:
case PIKbdListener::Return: case PIKbdListener::Return:
raiseEvent(TileEvent(ButtonSelected, cur)); raiseEvent(TileEvent(ButtonSelected, cur));
return true; return true;
}; };
return PIScreenTile::keyEvent(key); return PIScreenTile::keyEvent(key);
} }
bool TileButtons::mouseEvent(PIKbdListener::MouseEvent me) { bool TileButtons::mouseEvent(PIKbdListener::MouseEvent me) {
if (me.action == PIKbdListener::MouseMove || me.action == PIKbdListener::MouseButtonPress) { if (me.action == PIKbdListener::MouseMove || me.action == PIKbdListener::MouseButtonPress) {
for (int i = 0; i < btn_rects.size_s(); ++i) for (int i = 0; i < btn_rects.size_s(); ++i)
if (me.x >= btn_rects[i].x0 && me.x < btn_rects[i].x1 && if (me.x >= btn_rects[i].x0 && me.x < btn_rects[i].x1 &&
me.y >= btn_rects[i].y0 && me.y < btn_rects[i].y1) { me.y >= btn_rects[i].y0 && me.y < btn_rects[i].y1) {
cur = i; cur = i;
break; break;
} }
return true; return true;
} }
if (me.action != PIKbdListener::MouseButtonRelease) return true; if (me.action != PIKbdListener::MouseButtonRelease) return true;
keyEvent(PIKbdListener::KeyEvent(PIKbdListener::Return)); keyEvent(PIKbdListener::KeyEvent(PIKbdListener::Return));
return true; return true;
} }
TileCheck::TileCheck(const PIString & n): PIScreenTile(n) { TileCheck::TileCheck(const PIString & n): PIScreenTile(n) {
focus_flags = CanHasFocus | NextByTab | NextByArrowsAll | FocusOnMouse; focus_flags = CanHasFocus | NextByTab | NextByArrowsAll | FocusOnMouse;
toggled = false; toggled = false;
} }
void TileCheck::sizeHint(int & w, int & h) const { void TileCheck::sizeHint(int & w, int & h) const {
w = text.size_s() + 4; w = text.size_s() + 4;
h = 1; h = 1;
} }
void TileCheck::drawEvent(PIScreenDrawer * d) { void TileCheck::drawEvent(PIScreenDrawer * d) {
Color cb = has_focus ? Blue : Cyan; Color cb = has_focus ? Blue : Cyan;
Color ct = has_focus ? White : Black; Color ct = has_focus ? White : Black;
int ff = has_focus ? Bold : 0; int ff = has_focus ? Bold : 0;
PIString cs("[ ]"); PIString cs("[ ]");
if (toggled) cs[1] = '*'; if (toggled) cs[1] = '*';
d->fillRect(x_, y_, x_ + width_, y_ + 1, ' ', Default, cb); d->fillRect(x_, y_, x_ + width_, y_ + 1, ' ', Default, cb);
d->drawText(x_, y_, cs, ct, Transparent, ff); d->drawText(x_, y_, cs, ct, Transparent, ff);
d->drawText(x_ + 4, y_, text, ct, Transparent, ff); d->drawText(x_ + 4, y_, text, ct, Transparent, ff);
} }
bool TileCheck::keyEvent(PIKbdListener::KeyEvent key) { bool TileCheck::keyEvent(PIKbdListener::KeyEvent key) {
if (key.key == PIKbdListener::Space || key.key == PIKbdListener::Return) { if (key.key == PIKbdListener::Space || key.key == PIKbdListener::Return) {
toggled = !toggled; toggled = !toggled;
raiseEvent(TileEvent(Toggled, toggled)); raiseEvent(TileEvent(Toggled, toggled));
return true; return true;
} }
return PIScreenTile::keyEvent(key); return PIScreenTile::keyEvent(key);
} }
bool TileCheck::mouseEvent(PIKbdListener::MouseEvent me) { bool TileCheck::mouseEvent(PIKbdListener::MouseEvent me) {
if (me.action == PIKbdListener::MouseButtonPress) { if (me.action == PIKbdListener::MouseButtonPress) {
keyEvent(PIKbdListener::KeyEvent(PIKbdListener::Return)); keyEvent(PIKbdListener::KeyEvent(PIKbdListener::Return));
return true; return true;
} }
return false; return false;
} }
TileProgress::TileProgress(const PIString & n): PIScreenTile(n) { TileProgress::TileProgress(const PIString & n): PIScreenTile(n) {
maximum = 100.; maximum = 100.;
value = 0.; value = 0.;
suffix = " %"; suffix = " %";
} }
void TileProgress::sizeHint(int & w, int & h) const { void TileProgress::sizeHint(int & w, int & h) const {
w = 20; w = 20;
h = 1; h = 1;
} }
void TileProgress::drawEvent(PIScreenDrawer * d) { void TileProgress::drawEvent(PIScreenDrawer * d) {
int v = maximum == 0. ? 0 : piClampd(piRoundd(value / maximum * 100.), 0, 100); int v = maximum == 0. ? 0 : piClampd(piRoundd(value / maximum * 100.), 0, 100);
PIString s = prefix + PIString::fromNumber(piRoundd(value)) + suffix; PIString s = prefix + PIString::fromNumber(piRoundd(value)) + suffix;
int w = piRoundd(v / 100. * width_), sx = (width_ - s.size_s()) / 2; int w = piRoundd(v / 100. * width_), sx = (width_ - s.size_s()) / 2;
d->fillRect(x_, y_, x_ + width_, y_ + 1, ' ', Default, Cyan); d->fillRect(x_, y_, x_ + width_, y_ + 1, ' ', Default, Cyan);
d->fillRect(x_, y_, x_ + w, y_ + 1, ' ', Default, Blue); d->fillRect(x_, y_, x_ + w, y_ + 1, ' ', Default, Blue);
if (w < sx) if (w < sx)
d->drawText(x_ + sx, y_, s, Black, Transparent); d->drawText(x_ + sx, y_, s, Black, Transparent);
else if (w >= sx + s.size_s()) else if (w >= sx + s.size_s())
d->drawText(x_ + sx, y_, s, White, Transparent); d->drawText(x_ + sx, y_, s, White, Transparent);
else { else {
int fw = w - sx; int fw = w - sx;
d->drawText(x_ + sx, y_, s.left(fw), White, Transparent); d->drawText(x_ + sx, y_, s.left(fw), White, Transparent);
d->drawText(x_ + sx + fw, y_, s.cutLeft(fw), Black, Transparent); d->drawText(x_ + sx + fw, y_, s.cutLeft(fw), Black, Transparent);
} }
} }
TilePICout::TilePICout(const PIString & n): TileList(n) { TilePICout::TilePICout(const PIString & n): TileList(n) {
max_lines = 1024; max_lines = 1024;
selection_mode = TileList::SingleSelection; selection_mode = TileList::SingleSelection;
PICout::setOutputDevices(PICout::Buffer); PICout::setOutputDevices(PICout::Buffer);
PICout::setBufferActive(true); PICout::setBufferActive(true);
} }
void TilePICout::drawEvent(PIScreenDrawer * d) { void TilePICout::drawEvent(PIScreenDrawer * d) {
PIString out = PICout::buffer(true); PIString out = PICout::buffer(true);
if (!out.isEmpty()) { if (!out.isEmpty()) {
PIStringList l = out.split("\n"); PIStringList l = out.split("\n");
bool scroll = (cur == content.size_s() - 1) || !has_focus; bool scroll = (cur == content.size_s() - 1) || !has_focus;
piForeachC (PIString & s, l) piForeachC (PIString & s, l)
content << TileList::Row(s.trimmed(), format); content << TileList::Row(s.trimmed(), format);
if (content.size_s() > max_lines) if (content.size_s() > max_lines)
content.remove(0, content.size_s() - max_lines); content.remove(0, content.size_s() - max_lines);
if (scroll) { if (scroll) {
offset = piMaxi(0, content.size_s() - lhei); offset = piMaxi(0, content.size_s() - lhei);
cur = content.size_s() - 1; cur = content.size_s() - 1;
} }
} }
TileList::drawEvent(d); TileList::drawEvent(d);
} }
bool TilePICout::keyEvent(PIKbdListener::KeyEvent key) { bool TilePICout::keyEvent(PIKbdListener::KeyEvent key) {
if (key.key == 'C') { if (key.key == 'C') {
content.clear(); content.clear();
cur = offset = 0; cur = offset = 0;
return true; return true;
} }
return TileList::keyEvent(key); return TileList::keyEvent(key);
} }
TileInput::TileInput(const PIString & n): PIScreenTile(n) { TileInput::TileInput(const PIString & n): PIScreenTile(n) {
focus_flags = CanHasFocus | NextByTab | FocusOnMouse; focus_flags = CanHasFocus | NextByTab | FocusOnMouse;
back_format.color_back = White; back_format.color_back = White;
format.color_char = Black; format.color_char = Black;
format.color_back = White; format.color_back = White;
max_length = 1024; max_length = 1024;
cur = offset = 0; cur = offset = 0;
inv = false; inv = false;
} }
void TileInput::sizeHint(int & w, int & h) const { void TileInput::sizeHint(int & w, int & h) const {
w = 32; w = 32;
h = 1; h = 1;
} }
void TileInput::drawEvent(PIScreenDrawer * d) { void TileInput::drawEvent(PIScreenDrawer * d) {
PIString ps = text.mid(offset, width_ - 2); PIString ps = text.mid(offset, width_ - 2);
d->drawText(x_ + 1, y_, ps, (Color)format.color_char, Transparent, (CharFlags)format.flags); d->drawText(x_ + 1, y_, ps, (Color)format.color_char, Transparent, (CharFlags)format.flags);
if (offset > 0) if (offset > 0)
d->drawText(x_, y_, "<", Green, Black, Bold); d->drawText(x_, y_, "<", Green, Black, Bold);
if (text.size_s() - offset >= width_ - 2) if (text.size_s() - offset >= width_ - 2)
d->drawText(x_ + width_ - 1, y_, ">", Green, Black, Bold); d->drawText(x_ + width_ - 1, y_, ">", Green, Black, Bold);
if (!has_focus) return; if (!has_focus) return;
Color cb = (Color)format.color_char, cc = (Color)format.color_back; Color cb = (Color)format.color_char, cc = (Color)format.color_back;
if (tm_blink.elapsed_m() >= 650) { if (tm_blink.elapsed_m() >= 650) {
tm_blink.reset(); tm_blink.reset();
inv = !inv; inv = !inv;
} }
if (inv) piSwap(cb, cc); if (inv) piSwap(cb, cc);
d->drawText(x_ + 1 + cur - offset, y_, text.mid(cur, 1).expandLeftTo(1, ' '), cc, cb, (CharFlags)format.flags); d->drawText(x_ + 1 + cur - offset, y_, text.mid(cur, 1).expandLeftTo(1, ' '), cc, cb, (CharFlags)format.flags);
} }
bool TileInput::keyEvent(PIKbdListener::KeyEvent key) { bool TileInput::keyEvent(PIKbdListener::KeyEvent key) {
int lwid = piMaxi(0, width_ - 2); int lwid = piMaxi(0, width_ - 2);
int oo(0), osp = piMini(3, lwid / 4); int oo(0), osp = piMini(3, lwid / 4);
lwid--; lwid--;
switch (key.key) { switch (key.key) {
case PIKbdListener::LeftArrow: case PIKbdListener::LeftArrow:
cur--; cur--;
oo--; oo--;
if (key.modifiers[PIKbdListener::Ctrl]) { if (key.modifiers[PIKbdListener::Ctrl]) {
cur -= 4; cur -= 4;
oo -= 4; oo -= 4;
} }
if (cur < 0) cur = 0; if (cur < 0) cur = 0;
if (cur - offset < osp) offset += oo; if (cur - offset < osp) offset += oo;
if (offset < 0) offset = 0; if (offset < 0) offset = 0;
reserCursor(); reserCursor();
return true; return true;
case PIKbdListener::RightArrow: case PIKbdListener::RightArrow:
cur++; cur++;
oo++; oo++;
if (key.modifiers[PIKbdListener::Ctrl]) { if (key.modifiers[PIKbdListener::Ctrl]) {
cur += 4; cur += 4;
oo += 4; oo += 4;
} }
if (cur > text.size_s()) cur = text.size_s(); if (cur > text.size_s()) cur = text.size_s();
if (cur - offset >= lwid - osp) offset += oo; if (cur - offset >= lwid - osp) offset += oo;
if (offset >= text.size_s() - lwid) offset = text.size_s() - lwid; if (offset >= text.size_s() - lwid) offset = text.size_s() - lwid;
if (offset < 0) offset = 0; if (offset < 0) offset = 0;
reserCursor(); reserCursor();
return true; return true;
case PIKbdListener::Home: case PIKbdListener::Home:
cur = offset = 0; cur = offset = 0;
reserCursor(); reserCursor();
return true; return true;
case PIKbdListener::End: case PIKbdListener::End:
cur = text.size_s(); cur = text.size_s();
offset = text.size_s() - lwid; offset = text.size_s() - lwid;
if (offset < 0) offset = 0; if (offset < 0) offset = 0;
reserCursor(); reserCursor();
return true; return true;
case PIKbdListener::Backspace: case PIKbdListener::Backspace:
if (cur > text.size_s() || text.isEmpty()) if (cur > text.size_s() || text.isEmpty())
return true; return true;
text.remove(cur - 1, 1); text.remove(cur - 1, 1);
cur--; cur--;
if (cur > text.size_s()) cur = text.size_s(); if (cur > text.size_s()) cur = text.size_s();
if (cur - offset >= lwid - osp) offset += oo; if (cur - offset >= lwid - osp) offset += oo;
if (offset >= text.size_s() - lwid) offset = text.size_s() - lwid; if (offset >= text.size_s() - lwid) offset = text.size_s() - lwid;
if (offset < 0) offset = 0; if (offset < 0) offset = 0;
reserCursor(); reserCursor();
return true; return true;
case PIKbdListener::Delete: case PIKbdListener::Delete:
if (cur >= text.size_s() || text.isEmpty()) if (cur >= text.size_s() || text.isEmpty())
return true; return true;
text.remove(cur, 1); text.remove(cur, 1);
if (cur < 0) cur = 0; if (cur < 0) cur = 0;
if (cur > text.size_s()) cur = text.size_s(); if (cur > text.size_s()) cur = text.size_s();
if (cur - offset < osp) offset += oo; if (cur - offset < osp) offset += oo;
if (offset < 0) offset = 0; if (offset < 0) offset = 0;
reserCursor(); reserCursor();
return true; return true;
case PIKbdListener::UpArrow: case PIKbdListener::UpArrow:
case PIKbdListener::DownArrow: case PIKbdListener::DownArrow:
case PIKbdListener::PageUp: case PIKbdListener::PageUp:
case PIKbdListener::PageDown: case PIKbdListener::PageDown:
case PIKbdListener::Insert: case PIKbdListener::Insert:
case PIKbdListener::Return: case PIKbdListener::Return:
case PIKbdListener::Esc: case PIKbdListener::Esc:
case PIKbdListener::F1: case PIKbdListener::F1:
case PIKbdListener::F2: case PIKbdListener::F2:
case PIKbdListener::F3: case PIKbdListener::F3:
case PIKbdListener::F4: case PIKbdListener::F4:
case PIKbdListener::F5: case PIKbdListener::F5:
case PIKbdListener::F6: case PIKbdListener::F6:
case PIKbdListener::F7: case PIKbdListener::F7:
case PIKbdListener::F8: case PIKbdListener::F8:
case PIKbdListener::F9: case PIKbdListener::F9:
case PIKbdListener::F10: case PIKbdListener::F10:
case PIKbdListener::F11: case PIKbdListener::F11:
case PIKbdListener::F12: case PIKbdListener::F12:
break; break;
default: default:
PIChar tc PIChar tc
#ifdef WINDOWS #ifdef WINDOWS
= PIChar(key.key); = PIChar(key.key);
#else #else
= PIChar::fromUTF8((char *)&(key.key)); = PIChar::fromUTF8((char *)&(key.key));
#endif #endif
text.insert(cur, tc); text.insert(cur, tc);
cur++; cur++;
oo++; oo++;
if (cur - offset >= lwid - osp) offset += oo; if (cur - offset >= lwid - osp) offset += oo;
if (offset >= text.size_s() - lwid) offset = text.size_s() - lwid; if (offset >= text.size_s() - lwid) offset = text.size_s() - lwid;
if (offset < 0) offset = 0; if (offset < 0) offset = 0;
reserCursor(); reserCursor();
return true; return true;
} }
return PIScreenTile::keyEvent(key); return PIScreenTile::keyEvent(key);
} }
void TileInput::reserCursor() { void TileInput::reserCursor() {
tm_blink.reset(); tm_blink.reset();
inv = false; inv = false;
} }

View File

@@ -1,920 +1,920 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Virtual terminal Virtual terminal
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "piincludes_p.h" #include "piincludes_p.h"
#include "piterminal.h" #include "piterminal.h"
#include "pisharedmemory.h" #include "pisharedmemory.h"
#ifndef FREERTOS #ifndef FREERTOS
#ifdef WINDOWS #ifdef WINDOWS
# include <windows.h> # include <windows.h>
# include <wincon.h> # include <wincon.h>
# include <winuser.h> # include <winuser.h>
#else #else
# include "piprocess.h" # include "piprocess.h"
# include <csignal> # include <csignal>
# include <fcntl.h> # include <fcntl.h>
# include <sys/ioctl.h> # include <sys/ioctl.h>
# if defined(QNX) || defined(BLACKBERRY) # if defined(QNX) || defined(BLACKBERRY)
# include <unix.h> # include <unix.h>
# else # else
# ifdef MAC_OS # ifdef MAC_OS
# include <util.h> # include <util.h>
# else # else
# include <pty.h> # include <pty.h>
# endif # endif
# endif # endif
# ifdef ANDROID # ifdef ANDROID
# if __ANDROID_API__ >= 23 # if __ANDROID_API__ >= 23
# define HAS_FORKPTY # define HAS_FORKPTY
# endif # endif
# else # else
# define HAS_FORKPTY # define HAS_FORKPTY
# endif # endif
#endif #endif
//extern PIMutex PICout::__mutex__; //extern PIMutex PICout::__mutex__;
#ifdef WINDOWS #ifdef WINDOWS
# define PIPE_BUFFER_SIZE 1024 # define PIPE_BUFFER_SIZE 1024
enum PITerminalAuxMessageType { enum PITerminalAuxMessageType {
mtKey = 1, mtKey = 1,
mtResize, mtResize,
mtScroll mtScroll
}; };
struct PITerminalAuxData { struct PITerminalAuxData {
int cursor_x; int cursor_x;
int cursor_y; int cursor_y;
int size_x; int size_x;
int size_y; int size_y;
int cells_size; int cells_size;
}; };
#else #else
# define BUFFER_SIZE 4096 # define BUFFER_SIZE 4096
enum DECType { enum DECType {
CKM = 1 CKM = 1
}; };
#endif #endif
PRIVATE_DEFINITION_START(PITerminal) PRIVATE_DEFINITION_START(PITerminal)
#ifdef WINDOWS #ifdef WINDOWS
PISharedMemory * shm; PISharedMemory * shm;
HANDLE hConBuf; HANDLE hConBuf;
STARTUPINFOA si; STARTUPINFOA si;
PROCESS_INFORMATION pi; PROCESS_INFORMATION pi;
HANDLE pipe; HANDLE pipe;
#else #else
PIString shell; PIString shell;
PIByteArray read_buf, tmp_buf; PIByteArray read_buf, tmp_buf;
PIScreenTypes::CellFormat cur_format, line_format; PIScreenTypes::CellFormat cur_format, line_format;
int term_type; int term_type;
int fd, cur_x, cur_y; int fd, cur_x, cur_y;
int save_cur_x, save_cur_y; int save_cur_x, save_cur_y;
int win_y0, win_y1; int win_y0, win_y1;
pid_t pid; pid_t pid;
PIString esc_seq; PIString esc_seq;
bool is_esc_seq, last_read; bool is_esc_seq, last_read;
PIMap<int, bool> DEC; PIMap<int, bool> DEC;
PIVector<PIVector<PIScreenTypes::Cell> > cells_save; PIVector<PIVector<PIScreenTypes::Cell> > cells_save;
#endif #endif
PRIVATE_DEFINITION_END(PITerminal) PRIVATE_DEFINITION_END(PITerminal)
#ifdef WINDOWS #ifdef WINDOWS
int writePipe(HANDLE pipe, const PIByteArray & ba) { int writePipe(HANDLE pipe, const PIByteArray & ba) {
DWORD wrote[2]; DWORD wrote[2];
int sz = ba.size_s(); int sz = ba.size_s();
WriteFile(pipe, &sz, 4, &(wrote[0]), 0); WriteFile(pipe, &sz, 4, &(wrote[0]), 0);
WriteFile(pipe, ba.data(), ba.size_s(), &(wrote[1]), 0); WriteFile(pipe, ba.data(), ba.size_s(), &(wrote[1]), 0);
//piCout << "send" << ba.size_s(); //piCout << "send" << ba.size_s();
return int(wrote[0] + wrote[1]); return int(wrote[0] + wrote[1]);
} }
#endif #endif
PITerminal::PITerminal(): PIThread() { PITerminal::PITerminal(): PIThread() {
setName("terminal"); setName("terminal");
initPrivate(); initPrivate();
cursor_blink = false; cursor_blink = false;
cursor_x = cursor_y = 0; cursor_x = cursor_y = 0;
dsize_x = 80; dsize_x = 80;
dsize_y = 24; dsize_y = 24;
#ifdef WINDOWS #ifdef WINDOWS
PRIVATE->shm = 0; PRIVATE->shm = 0;
#endif #endif
} }
PITerminal::~PITerminal() { PITerminal::~PITerminal() {
if (isRunning()) if (isRunning())
stop(); stop();
PIThread::waitForFinish(10); PIThread::waitForFinish(10);
destroy(); destroy();
#ifdef WINDOWS #ifdef WINDOWS
if (PRIVATE->shm) delete PRIVATE->shm; if (PRIVATE->shm) delete PRIVATE->shm;
#endif #endif
} }
void PITerminal::write(const PIByteArray & d) { void PITerminal::write(const PIByteArray & d) {
#ifdef WINDOWS #ifdef WINDOWS
PIByteArray msg; PIByteArray msg;
PIVector<PIKbdListener::KeyEvent> ke; PIVector<PIKbdListener::KeyEvent> ke;
for (int i = 0; i < d.size_s(); ++i) for (int i = 0; i < d.size_s(); ++i)
ke << PIKbdListener::KeyEvent(d[i]); ke << PIKbdListener::KeyEvent(d[i]);
msg << int(mtKey) << ke; msg << int(mtKey) << ke;
writePipe(PRIVATE->pipe, msg); writePipe(PRIVATE->pipe, msg);
#else #else
# ifdef HAS_FORKPTY # ifdef HAS_FORKPTY
if (PRIVATE->fd == 0) return; if (PRIVATE->fd == 0) return;
//ssize_t wrote = 0; //ssize_t wrote = 0;
//wrote = //wrote =
::write(PRIVATE->fd, d.data(), d.size_s()); ::write(PRIVATE->fd, d.data(), d.size_s());
//piCout << "wrote" << wrote << d; //piCout << "wrote" << wrote << d;
# endif # endif
#endif #endif
cursor_tm.reset(); cursor_tm.reset();
cursor_blink = true; cursor_blink = true;
} }
void PITerminal::write(PIKbdListener::SpecialKey k, PIKbdListener::KeyModifiers m) { void PITerminal::write(PIKbdListener::SpecialKey k, PIKbdListener::KeyModifiers m) {
PIByteArray ba; PIByteArray ba;
#ifdef WINDOWS #ifdef WINDOWS
switch (k) { switch (k) {
case PIKbdListener::Tab: ba << uchar('\t'); break; case PIKbdListener::Tab: ba << uchar('\t'); break;
case PIKbdListener::Return: ba << uchar('\r') << uchar('\n'); break; case PIKbdListener::Return: ba << uchar('\r') << uchar('\n'); break;
case PIKbdListener::Space: ba << uchar(' '); break; case PIKbdListener::Space: ba << uchar(' '); break;
default: break; default: break;
} }
//piCout << "write" << ba.size(); //piCout << "write" << ba.size();
if (!ba.isEmpty()) write(ba); if (!ba.isEmpty()) write(ba);
else { else {
PIByteArray msg; PIByteArray msg;
PIVector<PIKbdListener::KeyEvent> ke; PIVector<PIKbdListener::KeyEvent> ke;
ke << PIKbdListener::KeyEvent(k, m); ke << PIKbdListener::KeyEvent(k, m);
msg << int(mtKey) << ke; msg << int(mtKey) << ke;
writePipe(PRIVATE->pipe, msg); writePipe(PRIVATE->pipe, msg);
} }
#else #else
int term = PRIVATE->term_type; int term = PRIVATE->term_type;
int flags = 0; int flags = 0;
switch (k) { switch (k) {
case PIKbdListener::Tab: ba << uchar('\t'); break; case PIKbdListener::Tab: ba << uchar('\t'); break;
case PIKbdListener::Return: ba << uchar('\n'); break; case PIKbdListener::Return: ba << uchar('\n'); break;
case PIKbdListener::Esc: ba << uchar('\e'); break; case PIKbdListener::Esc: ba << uchar('\e'); break;
case PIKbdListener::Space: ba << uchar(' '); break; case PIKbdListener::Space: ba << uchar(' '); break;
case PIKbdListener::Backspace: ba << uchar(0x7f); break; case PIKbdListener::Backspace: ba << uchar(0x7f); break;
case PIKbdListener::UpArrow: case PIKbdListener::UpArrow:
case PIKbdListener::DownArrow: case PIKbdListener::DownArrow:
case PIKbdListener::RightArrow: case PIKbdListener::RightArrow:
case PIKbdListener::LeftArrow: if (PRIVATE->DEC.value(CKM, false)) flags = 1; case PIKbdListener::LeftArrow: if (PRIVATE->DEC.value(CKM, false)) flags = 1;
/*case PIKbdListener::Home: //break; /*case PIKbdListener::Home: //break;
case PIKbdListener::End: //break; case PIKbdListener::End: //break;
case PIKbdListener::PageUp: //ba << uchar('\e') << uchar('[') << uchar('5') << uchar('~'); break; case PIKbdListener::PageUp: //ba << uchar('\e') << uchar('[') << uchar('5') << uchar('~'); break;
case PIKbdListener::PageDown: //ba << uchar('\e') << uchar('[') << uchar('6') << uchar('~'); break; case PIKbdListener::PageDown: //ba << uchar('\e') << uchar('[') << uchar('6') << uchar('~'); break;
case PIKbdListener::Insert: //ba << uchar('\e') << uchar('[') << uchar('2') << uchar('~'); break; case PIKbdListener::Insert: //ba << uchar('\e') << uchar('[') << uchar('2') << uchar('~'); break;
case PIKbdListener::Delete: //ba << uchar('\e') << uchar('[') << uchar('3') << uchar('~'); break; case PIKbdListener::Delete: //ba << uchar('\e') << uchar('[') << uchar('3') << uchar('~'); break;
case PIKbdListener::F1: //break; case PIKbdListener::F1: //break;
case PIKbdListener::F2: //break; case PIKbdListener::F2: //break;
case PIKbdListener::F3: //break; case PIKbdListener::F3: //break;
case PIKbdListener::F4: //break; case PIKbdListener::F4: //break;
case PIKbdListener::F5: //break; case PIKbdListener::F5: //break;
case PIKbdListener::F6: //break; case PIKbdListener::F6: //break;
case PIKbdListener::F7: //break; case PIKbdListener::F7: //break;
case PIKbdListener::F8: //break; case PIKbdListener::F8: //break;
case PIKbdListener::F9: //break; case PIKbdListener::F9: //break;
case PIKbdListener::F10: //break; case PIKbdListener::F10: //break;
case PIKbdListener::F11: //break; case PIKbdListener::F11: //break;
case PIKbdListener::F12: //break; case PIKbdListener::F12: //break;
*/ */
default: { default: {
//piCout << flags; //piCout << flags;
//int mod = 0; //int mod = 0;
if (m[PIKbdListener::Shift]) m |= 1; if (m[PIKbdListener::Shift]) m |= 1;
if (m[PIKbdListener::Alt]) m |= 2; if (m[PIKbdListener::Alt]) m |= 2;
if (m[PIKbdListener::Ctrl]) m |= 4; if (m[PIKbdListener::Ctrl]) m |= 4;
for (int i = 0; ; ++i) { for (int i = 0; ; ++i) {
const PIKbdListener::EscSeq & e(PIKbdListener::esc_seq[i]); const PIKbdListener::EscSeq & e(PIKbdListener::esc_seq[i]);
if (!e.seq) break; if (!e.seq) break;
//piCout << "search" << rc[1] << esc_seq[i].seq; //piCout << "search" << rc[1] << esc_seq[i].seq;
if (e.key == k && e.mod == m) { if (e.key == k && e.mod == m) {
if (((e.vt & term) == term) || (((e.flags & flags) == flags) && (flags != 0))) { if (((e.vt & term) == term) || (((e.flags & flags) == flags) && (flags != 0))) {
//piCout << "found key" << PIString(e.seq).replaceAll("\e", "\\e"); //piCout << "found key" << PIString(e.seq).replaceAll("\e", "\\e");
PIByteArray d = ("\e" + PIString(e.seq)).toByteArray(); PIByteArray d = ("\e" + PIString(e.seq)).toByteArray();
write(d); write(d);
break; break;
} }
} }
} }
} break; } break;
} }
//piCout << "write" << ba.size(); //piCout << "write" << ba.size();
if (!ba.isEmpty()) write(ba); if (!ba.isEmpty()) write(ba);
#endif #endif
cursor_tm.reset(); cursor_tm.reset();
cursor_blink = true; cursor_blink = true;
} }
void PITerminal::write(PIKbdListener::KeyEvent ke) { void PITerminal::write(PIKbdListener::KeyEvent ke) {
if (isSpecialKey(ke.key)) write((PIKbdListener::SpecialKey)ke.key, ke.modifiers); if (isSpecialKey(ke.key)) write((PIKbdListener::SpecialKey)ke.key, ke.modifiers);
else { else {
PIByteArray ba; PIByteArray ba;
#ifdef WINDOWS #ifdef WINDOWS
ba << uchar(PIChar(ke.key).toConsole1Byte()); ba << uchar(PIChar(ke.key).toConsole1Byte());
#else #else
ba = PIString(PIChar(ke.key)).toUTF8(); ba = PIString(PIChar(ke.key)).toUTF8();
#endif #endif
write(ba); write(ba);
} }
} }
PIVector<PIVector<PIScreenTypes::Cell> > PITerminal::content() { PIVector<PIVector<PIScreenTypes::Cell> > PITerminal::content() {
readConsole(); readConsole();
PIVector<PIVector<PIScreenTypes::Cell> > ret = cells; PIVector<PIVector<PIScreenTypes::Cell> > ret = cells;
if (cursor_blink && cursor_visible) if (cursor_blink && cursor_visible)
if (cursor_x >= 0 && cursor_x < size_x) if (cursor_x >= 0 && cursor_x < size_x)
if (cursor_y >= 0 && cursor_y < size_y) if (cursor_y >= 0 && cursor_y < size_y)
ret[cursor_y][cursor_x].format.flags ^= PIScreenTypes::Inverse; ret[cursor_y][cursor_x].format.flags ^= PIScreenTypes::Inverse;
return ret; return ret;
} }
bool PITerminal::isSpecialKey(int k) { bool PITerminal::isSpecialKey(int k) {
switch (k) { switch (k) {
case PIKbdListener::Tab: case PIKbdListener::Tab:
case PIKbdListener::Return: case PIKbdListener::Return:
case PIKbdListener::Esc: case PIKbdListener::Esc:
case PIKbdListener::Space: case PIKbdListener::Space:
case PIKbdListener::Backspace: case PIKbdListener::Backspace:
case PIKbdListener::UpArrow: case PIKbdListener::UpArrow:
case PIKbdListener::DownArrow: case PIKbdListener::DownArrow:
case PIKbdListener::RightArrow: case PIKbdListener::RightArrow:
case PIKbdListener::LeftArrow: case PIKbdListener::LeftArrow:
case PIKbdListener::Home: case PIKbdListener::Home:
case PIKbdListener::End: case PIKbdListener::End:
case PIKbdListener::PageUp: case PIKbdListener::PageUp:
case PIKbdListener::PageDown: case PIKbdListener::PageDown:
case PIKbdListener::Insert: case PIKbdListener::Insert:
case PIKbdListener::Delete: case PIKbdListener::Delete:
case PIKbdListener::F1: case PIKbdListener::F1:
case PIKbdListener::F2: case PIKbdListener::F2:
case PIKbdListener::F3: case PIKbdListener::F3:
case PIKbdListener::F4: case PIKbdListener::F4:
case PIKbdListener::F5: case PIKbdListener::F5:
case PIKbdListener::F6: case PIKbdListener::F6:
case PIKbdListener::F7: case PIKbdListener::F7:
case PIKbdListener::F8: case PIKbdListener::F8:
case PIKbdListener::F9: case PIKbdListener::F9:
case PIKbdListener::F10: case PIKbdListener::F10:
case PIKbdListener::F11: case PIKbdListener::F11:
case PIKbdListener::F12: return true; case PIKbdListener::F12: return true;
default: return false; default: return false;
} }
return false; return false;
} }
void PITerminal::initPrivate() { void PITerminal::initPrivate() {
#ifdef WINDOWS #ifdef WINDOWS
PRIVATE->hConBuf = INVALID_HANDLE_VALUE; PRIVATE->hConBuf = INVALID_HANDLE_VALUE;
PRIVATE->pipe = INVALID_HANDLE_VALUE; PRIVATE->pipe = INVALID_HANDLE_VALUE;
PRIVATE->pi.hProcess = 0; PRIVATE->pi.hProcess = 0;
#else #else
PRIVATE->shell = "/bin/bash"; PRIVATE->shell = "/bin/bash";
PRIVATE->read_buf.reserve(BUFFER_SIZE); PRIVATE->read_buf.reserve(BUFFER_SIZE);
PRIVATE->read_buf.fill(0); PRIVATE->read_buf.fill(0);
PRIVATE->fd = PRIVATE->cur_x = PRIVATE->cur_y = 0; PRIVATE->fd = PRIVATE->cur_x = PRIVATE->cur_y = 0;
PRIVATE->save_cur_x = PRIVATE->save_cur_y = 0; PRIVATE->save_cur_x = PRIVATE->save_cur_y = 0;
PRIVATE->pid = 0; PRIVATE->pid = 0;
PRIVATE->term_type = 0; PRIVATE->term_type = 0;
PRIVATE->is_esc_seq = false; PRIVATE->is_esc_seq = false;
PRIVATE->last_read = true; PRIVATE->last_read = true;
PRIVATE->esc_seq.clear(); PRIVATE->esc_seq.clear();
PRIVATE->cur_format = PIScreenTypes::CellFormat(); PRIVATE->cur_format = PIScreenTypes::CellFormat();
#endif #endif
cursor_blink = cursor_visible = true; cursor_blink = cursor_visible = true;
size_x = size_y = 0; size_x = size_y = 0;
} }
void PITerminal::readConsole() { void PITerminal::readConsole() {
#ifdef WINDOWS #ifdef WINDOWS
if (!PRIVATE->shm) return; if (!PRIVATE->shm) return;
PITerminalAuxData data; PITerminalAuxData data;
PRIVATE->shm->read(&data, sizeof(data)); PRIVATE->shm->read(&data, sizeof(data));
if (data.cells_size <= 4) return; if (data.cells_size <= 4) return;
cursor_x = data.cursor_x; cursor_x = data.cursor_x;
cursor_y = data.cursor_y; cursor_y = data.cursor_y;
size_x = data.size_x; size_x = data.size_x;
size_y = data.size_y; size_y = data.size_y;
PIByteArray ba; PIByteArray ba;
ba.resize(data.cells_size); ba.resize(data.cells_size);
PRIVATE->shm->read(ba.data(), ba.size_s(), sizeof(data)); PRIVATE->shm->read(ba.data(), ba.size_s(), sizeof(data));
ba >> cells; ba >> cells;
#endif #endif
//piCout << cursor_x << cursor_y; //piCout << cursor_x << cursor_y;
} }
void PITerminal::getCursor(int & x, int & y) { void PITerminal::getCursor(int & x, int & y) {
#ifdef WINDOWS #ifdef WINDOWS
if (!PRIVATE->shm) return; if (!PRIVATE->shm) return;
int sz = 0; int sz = 0;
PRIVATE->shm->read(&sz, 4); PRIVATE->shm->read(&sz, 4);
#else #else
x = PRIVATE->cur_x; x = PRIVATE->cur_x;
y = PRIVATE->cur_y; y = PRIVATE->cur_y;
#endif #endif
} }
uchar PITerminal::invertColor(uchar c) { uchar PITerminal::invertColor(uchar c) {
switch ((PIScreenTypes::Color)c) { switch ((PIScreenTypes::Color)c) {
case PIScreenTypes::Black: return PIScreenTypes::White; case PIScreenTypes::Black: return PIScreenTypes::White;
case PIScreenTypes::Red: return PIScreenTypes::Cyan; case PIScreenTypes::Red: return PIScreenTypes::Cyan;
case PIScreenTypes::Green: return PIScreenTypes::Magenta; case PIScreenTypes::Green: return PIScreenTypes::Magenta;
case PIScreenTypes::Blue: return PIScreenTypes::Yellow; case PIScreenTypes::Blue: return PIScreenTypes::Yellow;
case PIScreenTypes::Cyan: return PIScreenTypes::Red; case PIScreenTypes::Cyan: return PIScreenTypes::Red;
case PIScreenTypes::Magenta: return PIScreenTypes::Green; case PIScreenTypes::Magenta: return PIScreenTypes::Green;
case PIScreenTypes::Yellow: return PIScreenTypes::Blue; case PIScreenTypes::Yellow: return PIScreenTypes::Blue;
case PIScreenTypes::White: return PIScreenTypes::Black; case PIScreenTypes::White: return PIScreenTypes::Black;
default: break; default: break;
} }
return PIScreenTypes::White; return PIScreenTypes::White;
} }
void PITerminal::run() { void PITerminal::run() {
getCursor(cursor_x, cursor_y); getCursor(cursor_x, cursor_y);
if (cursor_tm.elapsed_m() >= 500) { if (cursor_tm.elapsed_m() >= 500) {
cursor_tm.reset(); cursor_tm.reset();
cursor_blink = !cursor_blink; cursor_blink = !cursor_blink;
} }
#ifndef WINDOWS #ifndef WINDOWS
# ifdef HAS_FORKPTY # ifdef HAS_FORKPTY
if (PRIVATE->fd == 0) return; if (PRIVATE->fd == 0) return;
PRIVATE->tmp_buf.resize(BUFFER_SIZE); PRIVATE->tmp_buf.resize(BUFFER_SIZE);
int readed = ::read(PRIVATE->fd, PRIVATE->tmp_buf.data(), BUFFER_SIZE - PRIVATE->read_buf.size_s()); int readed = ::read(PRIVATE->fd, PRIVATE->tmp_buf.data(), BUFFER_SIZE - PRIVATE->read_buf.size_s());
bool used = false; bool used = false;
if (readed > 0) { if (readed > 0) {
PRIVATE->last_read = true; PRIVATE->last_read = true;
//piCoutObj << "readed" << readed << PIString(PRIVATE->tmp_buf.resized(readed)).replaceAll("\e", "\\e"); //piCoutObj << "readed" << readed << PIString(PRIVATE->tmp_buf.resized(readed)).replaceAll("\e", "\\e");
//piCoutObj << "readed" << readed << (PRIVATE->tmp_buf.resized(readed)); //piCoutObj << "readed" << readed << (PRIVATE->tmp_buf.resized(readed));
PRIVATE->read_buf.append(PRIVATE->tmp_buf.resized(readed)); PRIVATE->read_buf.append(PRIVATE->tmp_buf.resized(readed));
for (;;) { for (;;) {
int ind = -1; int ind = -1;
for (int i = PRIVATE->read_buf.size_s() - 1; i >= 0; --i) for (int i = PRIVATE->read_buf.size_s() - 1; i >= 0; --i)
if (PRIVATE->read_buf[i] == uchar('\n') || PRIVATE->read_buf[i] == uchar('\e')) { if (PRIVATE->read_buf[i] == uchar('\n') || PRIVATE->read_buf[i] == uchar('\e')) {
ind = i; ind = i;
break; break;
} }
if (ind <= 0) break; if (ind <= 0) break;
used = true; used = true;
parseInput(PIString((const char *)PRIVATE->read_buf.data(), ind)); parseInput(PIString((const char *)PRIVATE->read_buf.data(), ind));
PRIVATE->read_buf.remove(0, ind); PRIVATE->read_buf.remove(0, ind);
} }
bool parse = PRIVATE->read_buf.size_s() >= BUFFER_SIZE; bool parse = PRIVATE->read_buf.size_s() >= BUFFER_SIZE;
if (PRIVATE->read_buf.size_s() == 1) if (PRIVATE->read_buf.size_s() == 1)
if (PRIVATE->read_buf[0] < 0x80) if (PRIVATE->read_buf[0] < 0x80)
parse = true; parse = true;
if (parse) { if (parse) {
parseInput(PIString(PRIVATE->read_buf)); parseInput(PIString(PRIVATE->read_buf));
PRIVATE->read_buf.clear(); PRIVATE->read_buf.clear();
} }
//printf("%s", PRIVATE->read_buf.data()); //printf("%s", PRIVATE->read_buf.data());
} }
if (!used && !PRIVATE->last_read && !PRIVATE->read_buf.isEmpty()) { if (!used && !PRIVATE->last_read && !PRIVATE->read_buf.isEmpty()) {
parseInput(PIString(PRIVATE->read_buf)); parseInput(PIString(PRIVATE->read_buf));
PRIVATE->read_buf.clear(); PRIVATE->read_buf.clear();
} }
PRIVATE->last_read = false; PRIVATE->last_read = false;
# endif # endif
#endif #endif
} }
#ifndef WINDOWS #ifndef WINDOWS
void PITerminal::parseInput(const PIString & s) { void PITerminal::parseInput(const PIString & s) {
//piCoutObj << s.replaceAll("\e", "\\e"); //piCoutObj << s.replaceAll("\e", "\\e");
//printf("%s", s.data()); //printf("%s", s.data());
for (int i = 0; i < s.size_s(); ++i) { for (int i = 0; i < s.size_s(); ++i) {
if (s[i].unicode16Code() == 0) break; if (s[i].unicode16Code() == 0) break;
if (PRIVATE->is_esc_seq) { if (PRIVATE->is_esc_seq) {
if (s[i] == '\e') { if (s[i] == '\e') {
applyEscSeq(PRIVATE->esc_seq); applyEscSeq(PRIVATE->esc_seq);
PRIVATE->esc_seq.clear(); PRIVATE->esc_seq.clear();
PRIVATE->is_esc_seq = true; PRIVATE->is_esc_seq = true;
} else { } else {
PRIVATE->esc_seq += s[i]; PRIVATE->esc_seq += s[i];
if (isCompleteEscSeq(PRIVATE->esc_seq)) { if (isCompleteEscSeq(PRIVATE->esc_seq)) {
PRIVATE->is_esc_seq = false; PRIVATE->is_esc_seq = false;
applyEscSeq(PRIVATE->esc_seq); applyEscSeq(PRIVATE->esc_seq);
//piCoutObj << PRIVATE->esc_seq; //piCoutObj << PRIVATE->esc_seq;
} }
} }
} else { } else {
if (s[i] == '\e') { if (s[i] == '\e') {
PRIVATE->esc_seq.clear(); PRIVATE->esc_seq.clear();
PRIVATE->is_esc_seq = true; PRIVATE->is_esc_seq = true;
} else { } else {
if (s[i] == '\a') continue; if (s[i] == '\a') continue;
if (s[i] == '\b') { if (s[i] == '\b') {
moveCursor(-1, 0); moveCursor(-1, 0);
continue; continue;
} }
if (s[i] == '\r') continue; if (s[i] == '\r') continue;
if (s[i] == '\n') { if (s[i] == '\n') {
//piCoutObj << "new line"; //piCoutObj << "new line";
for (int i = PRIVATE->cur_x; i < size_x; ++i) cells[PRIVATE->cur_y][i].format = PRIVATE->cur_format; for (int i = PRIVATE->cur_x; i < size_x; ++i) cells[PRIVATE->cur_y][i].format = PRIVATE->cur_format;
PRIVATE->line_format = PRIVATE->cur_format; PRIVATE->line_format = PRIVATE->cur_format;
PRIVATE->cur_x = 0; PRIVATE->cur_x = 0;
moveCursor(0, 1); moveCursor(0, 1);
continue; continue;
} }
//piCoutObj << "char" << s[i] << s[i].unicode16Code() << "at" << PRIVATE->cur_x << PRIVATE->cur_y; //piCoutObj << "char" << s[i] << s[i].unicode16Code() << "at" << PRIVATE->cur_x << PRIVATE->cur_y;
cells[PRIVATE->cur_y][PRIVATE->cur_x].symbol = s[i]; cells[PRIVATE->cur_y][PRIVATE->cur_x].symbol = s[i];
cells[PRIVATE->cur_y][PRIVATE->cur_x].format = PRIVATE->cur_format; cells[PRIVATE->cur_y][PRIVATE->cur_x].format = PRIVATE->cur_format;
moveCursor(1, 0); moveCursor(1, 0);
} }
} }
} }
} }
bool PITerminal::isCompleteEscSeq(const PIString & es) { bool PITerminal::isCompleteEscSeq(const PIString & es) {
if (es.size_s() < 2) return false; if (es.size_s() < 2) return false;
if (es.front() == ']') { if (es.front() == ']') {
if (es.back().toAscii() == '\\' || es.back().toAscii() == '\a') return true; if (es.back().toAscii() == '\\' || es.back().toAscii() == '\a') return true;
} else { } else {
if (es.back().toAscii() >= 64 && es.back().toAscii() <= 126) return true; if (es.back().toAscii() >= 64 && es.back().toAscii() <= 126) return true;
} }
return false; return false;
} }
void PITerminal::applyEscSeq(PIString es) { void PITerminal::applyEscSeq(PIString es) {
piCoutObj << es; piCoutObj << es;
if (es.size_s() < 2) return; if (es.size_s() < 2) return;
// PIScreenTypes::Cell line_cell = PIScreenTypes::Cell(' ', PRIVATE->line_format); // PIScreenTypes::Cell line_cell = PIScreenTypes::Cell(' ', PRIVATE->line_format);
PIScreenTypes::Cell def_cell = PIScreenTypes::Cell(' ', PRIVATE->cur_format); PIScreenTypes::Cell def_cell = PIScreenTypes::Cell(' ', PRIVATE->cur_format);
if (es[1] == '?' && es.size_s() >= 2) { if (es[1] == '?' && es.size_s() >= 2) {
char a = es.takeRight(1)[0].toAscii(); char a = es.takeRight(1)[0].toAscii();
bool val = false; bool val = false;
if (a == 'l') val = false; if (a == 'l') val = false;
if (a == 'h') val = true; if (a == 'h') val = true;
int dec = es.mid(2).toInt(); int dec = es.mid(2).toInt();
piCoutObj << "DEC" << dec << val; piCoutObj << "DEC" << dec << val;
PRIVATE->DEC[dec] = val; PRIVATE->DEC[dec] = val;
switch (dec) { switch (dec) {
case 25: cursor_visible = val; break; case 25: cursor_visible = val; break;
case 1049: case 1049:
if (val) { if (val) {
PRIVATE->save_cur_x = PRIVATE->cur_x; PRIVATE->save_cur_x = PRIVATE->cur_x;
PRIVATE->save_cur_y = PRIVATE->cur_y; PRIVATE->save_cur_y = PRIVATE->cur_y;
} else { } else {
PRIVATE->cur_x = PRIVATE->save_cur_x; PRIVATE->cur_x = PRIVATE->save_cur_x;
PRIVATE->cur_y = PRIVATE->save_cur_y; PRIVATE->cur_y = PRIVATE->save_cur_y;
} }
case 1047: case 1047:
if (val) { if (val) {
PRIVATE->cells_save = cells; PRIVATE->cells_save = cells;
for (int i = 0; i < size_y; ++i) cells[i].fill(def_cell); for (int i = 0; i < size_y; ++i) cells[i].fill(def_cell);
} else { } else {
cells = PRIVATE->cells_save; cells = PRIVATE->cells_save;
} }
break; break;
} }
} }
if (es[0] == '[') { // CSI if (es[0] == '[') { // CSI
if (es.back() == 'm') { if (es.back() == 'm') {
es.cutLeft(1).cutRight(1); es.cutLeft(1).cutRight(1);
if (es.isEmpty()) { if (es.isEmpty()) {
PRIVATE->cur_format = PIScreenTypes::CellFormat(); PRIVATE->cur_format = PIScreenTypes::CellFormat();
return; return;
} }
PIStringList args = es.split(";"); PIStringList args = es.split(";");
piForeachC (PIString & a, args) { piForeachC (PIString & a, args) {
int av = a.toInt(); int av = a.toInt();
switch (av) { switch (av) {
case 0: PRIVATE->cur_format = PIScreenTypes::CellFormat(); break; case 0: PRIVATE->cur_format = PIScreenTypes::CellFormat(); break;
case 1: PRIVATE->cur_format.flags |= PIScreenTypes::Bold; break; case 1: PRIVATE->cur_format.flags |= PIScreenTypes::Bold; break;
case 4: PRIVATE->cur_format.flags |= PIScreenTypes::Underline; break; case 4: PRIVATE->cur_format.flags |= PIScreenTypes::Underline; break;
case 5: PRIVATE->cur_format.flags |= PIScreenTypes::Blink; break; case 5: PRIVATE->cur_format.flags |= PIScreenTypes::Blink; break;
case 7: PRIVATE->cur_format.flags |= PIScreenTypes::Inverse; break; case 7: PRIVATE->cur_format.flags |= PIScreenTypes::Inverse; break;
default: { default: {
bool col = false, target = false; bool col = false, target = false;
int cid = av % 10; int cid = av % 10;
if (av >= 30 && av <= 37) {col = true; target = false;} if (av >= 30 && av <= 37) {col = true; target = false;}
if (av >= 40 && av <= 47) {col = true; target = true;} if (av >= 40 && av <= 47) {col = true; target = true;}
if (col) { if (col) {
int cfl = 0; int cfl = 0;
switch (cid) { switch (cid) {
case 0: cfl = PIScreenTypes::Black; break; case 0: cfl = PIScreenTypes::Black; break;
case 1: cfl = PIScreenTypes::Red; break; case 1: cfl = PIScreenTypes::Red; break;
case 2: cfl = PIScreenTypes::Green; break; case 2: cfl = PIScreenTypes::Green; break;
case 3: cfl = PIScreenTypes::Yellow; break; case 3: cfl = PIScreenTypes::Yellow; break;
case 4: cfl = PIScreenTypes::Blue; break; case 4: cfl = PIScreenTypes::Blue; break;
case 5: cfl = PIScreenTypes::Magenta; break; case 5: cfl = PIScreenTypes::Magenta; break;
case 6: cfl = PIScreenTypes::Cyan; break; case 6: cfl = PIScreenTypes::Cyan; break;
case 7: cfl = PIScreenTypes::White; break; case 7: cfl = PIScreenTypes::White; break;
} }
if (target) if (target)
PRIVATE->cur_format.color_back = cfl; PRIVATE->cur_format.color_back = cfl;
else else
PRIVATE->cur_format.color_char = cfl; PRIVATE->cur_format.color_char = cfl;
break; break;
} }
} break; } break;
} }
} }
/*if ((PRIVATE->cur_format.flags & PIScreenTypes::Inverse) == PIScreenTypes::Inverse) { /*if ((PRIVATE->cur_format.flags & PIScreenTypes::Inverse) == PIScreenTypes::Inverse) {
uchar t = PRIVATE->cur_format.color_char; uchar t = PRIVATE->cur_format.color_char;
PRIVATE->cur_format.color_char = PRIVATE->cur_format.color_back; PRIVATE->cur_format.color_char = PRIVATE->cur_format.color_back;
PRIVATE->cur_format.color_back = t; PRIVATE->cur_format.color_back = t;
}*/ }*/
} }
if (es.back() == 'r') { if (es.back() == 'r') {
piCoutObj << es; piCoutObj << es;
es.cutLeft(1).cutRight(1); es.cutLeft(1).cutRight(1);
PIStringList args = es.split(";"); PIStringList args = es.split(";");
args.resize(2); args.resize(2);
int y0(0), y1(0); int y0(0), y1(0);
if (!args[0].isEmpty()) y0 = args[0].toInt() - 1; if (!args[0].isEmpty()) y0 = args[0].toInt() - 1;
if (!args[1].isEmpty()) y1 = args[1].toInt() - 1; if (!args[1].isEmpty()) y1 = args[1].toInt() - 1;
PRIVATE->win_y0 = piClamp(y0, 0, size_y - 1); PRIVATE->win_y0 = piClamp(y0, 0, size_y - 1);
PRIVATE->win_y1 = piClamp(y1, 0, size_y - 1); PRIVATE->win_y1 = piClamp(y1, 0, size_y - 1);
} }
if (es.back() == 's') { if (es.back() == 's') {
PRIVATE->save_cur_x = PRIVATE->cur_x; PRIVATE->save_cur_x = PRIVATE->cur_x;
PRIVATE->save_cur_y = PRIVATE->cur_y; PRIVATE->save_cur_y = PRIVATE->cur_y;
} }
if (es.back() == 'u') { if (es.back() == 'u') {
PRIVATE->cur_x = PRIVATE->save_cur_x; PRIVATE->cur_x = PRIVATE->save_cur_x;
PRIVATE->cur_y = PRIVATE->save_cur_y; PRIVATE->cur_y = PRIVATE->save_cur_y;
} }
if (es.back() == 'H' || es.back() == 'f' || es.back() == 'r') { if (es.back() == 'H' || es.back() == 'f' || es.back() == 'r') {
es.cutLeft(1).cutRight(1); es.cutLeft(1).cutRight(1);
PIStringList args = es.split(";"); PIStringList args = es.split(";");
args.resize(2); args.resize(2);
int x(0), y(0); int x(0), y(0);
if (!args[0].isEmpty()) y = args[0].toInt() - 1; if (!args[0].isEmpty()) y = args[0].toInt() - 1;
if (!args[1].isEmpty()) x = args[1].toInt() - 1; if (!args[1].isEmpty()) x = args[1].toInt() - 1;
//piCoutObj << x << y; //piCoutObj << x << y;
PRIVATE->cur_x = piClamp(x, 0, size_x - 1); PRIVATE->cur_x = piClamp(x, 0, size_x - 1);
PRIVATE->cur_y = piClamp(y, 0, size_y - 1); PRIVATE->cur_y = piClamp(y, 0, size_y - 1);
PRIVATE->line_format = PRIVATE->cur_format; PRIVATE->line_format = PRIVATE->cur_format;
} }
if (es.back() == 'A') { // cursor up if (es.back() == 'A') { // cursor up
es.cutLeft(1).cutRight(1); es.cutLeft(1).cutRight(1);
int v = es.toInt(); if (v == 0) v = 1; int v = es.toInt(); if (v == 0) v = 1;
PRIVATE->cur_y = piClamp(PRIVATE->cur_y - v, 0, size_y - 1); PRIVATE->cur_y = piClamp(PRIVATE->cur_y - v, 0, size_y - 1);
PRIVATE->line_format = PRIVATE->cur_format; PRIVATE->line_format = PRIVATE->cur_format;
} }
if (es.back() == 'B') { // cursor down if (es.back() == 'B') { // cursor down
es.cutLeft(1).cutRight(1); es.cutLeft(1).cutRight(1);
int v = es.toInt(); if (v == 0) v = 1; int v = es.toInt(); if (v == 0) v = 1;
PRIVATE->cur_y = piClamp(PRIVATE->cur_y + v, 0, size_y - 1); PRIVATE->cur_y = piClamp(PRIVATE->cur_y + v, 0, size_y - 1);
PRIVATE->line_format = PRIVATE->cur_format; PRIVATE->line_format = PRIVATE->cur_format;
} }
if (es.back() == 'C' || es.back() == 'a') { // cursor forward, next column if (es.back() == 'C' || es.back() == 'a') { // cursor forward, next column
es.cutLeft(1).cutRight(1); es.cutLeft(1).cutRight(1);
int v = es.toInt(); if (v == 0) v = 1; int v = es.toInt(); if (v == 0) v = 1;
PRIVATE->cur_x = piClamp(PRIVATE->cur_x + v, 0, size_x - 1); PRIVATE->cur_x = piClamp(PRIVATE->cur_x + v, 0, size_x - 1);
PRIVATE->line_format = PRIVATE->cur_format; PRIVATE->line_format = PRIVATE->cur_format;
} }
if (es.back() == 'D') { // cursor back if (es.back() == 'D') { // cursor back
es.cutLeft(1).cutRight(1); es.cutLeft(1).cutRight(1);
int v = es.toInt(); if (v == 0) v = 1; int v = es.toInt(); if (v == 0) v = 1;
PRIVATE->cur_x = piClamp(PRIVATE->cur_x - v, 0, size_x - 1); PRIVATE->cur_x = piClamp(PRIVATE->cur_x - v, 0, size_x - 1);
PRIVATE->line_format = PRIVATE->cur_format; PRIVATE->line_format = PRIVATE->cur_format;
} }
if (es.back() == 'G' || es.back() == '`') { // goto column if (es.back() == 'G' || es.back() == '`') { // goto column
es.cutLeft(1).cutRight(1); es.cutLeft(1).cutRight(1);
int v = es.toInt(); int v = es.toInt();
if (v) PRIVATE->cur_x = piClamp(v - 1, 0, size_x - 1); if (v) PRIVATE->cur_x = piClamp(v - 1, 0, size_x - 1);
PRIVATE->line_format = PRIVATE->cur_format; PRIVATE->line_format = PRIVATE->cur_format;
} }
if (es.back() == 'd') { // goto line if (es.back() == 'd') { // goto line
es.cutLeft(1).cutRight(1); es.cutLeft(1).cutRight(1);
int v = es.toInt(); if (v == 0) v = 1; int v = es.toInt(); if (v == 0) v = 1;
PRIVATE->cur_x = 0; PRIVATE->cur_x = 0;
PRIVATE->cur_y = piClamp(v - 1, 0, size_y - 1); PRIVATE->cur_y = piClamp(v - 1, 0, size_y - 1);
PRIVATE->line_format = PRIVATE->cur_format; PRIVATE->line_format = PRIVATE->cur_format;
} }
if (es.back() == 'E' || es.back() == 'e') { // next line if (es.back() == 'E' || es.back() == 'e') { // next line
es.cutLeft(1).cutRight(1); es.cutLeft(1).cutRight(1);
int v = es.toInt(); if (v == 0) v = 1; int v = es.toInt(); if (v == 0) v = 1;
PRIVATE->cur_x = 0; PRIVATE->cur_x = 0;
PRIVATE->cur_y = piClamp(PRIVATE->cur_y + v, 0, size_y - 1); PRIVATE->cur_y = piClamp(PRIVATE->cur_y + v, 0, size_y - 1);
PRIVATE->line_format = PRIVATE->cur_format; PRIVATE->line_format = PRIVATE->cur_format;
} }
if (es.back() == 'F') { // previous line if (es.back() == 'F') { // previous line
es.cutLeft(1).cutRight(1); es.cutLeft(1).cutRight(1);
int v = es.toInt(); if (v == 0) v = 1; int v = es.toInt(); if (v == 0) v = 1;
PRIVATE->cur_x = 0; PRIVATE->cur_x = 0;
PRIVATE->cur_y = piClamp(PRIVATE->cur_y - v, 0, size_y - 1); PRIVATE->cur_y = piClamp(PRIVATE->cur_y - v, 0, size_y - 1);
PRIVATE->line_format = PRIVATE->cur_format; PRIVATE->line_format = PRIVATE->cur_format;
} }
if (es.back() == 'L') { // insert lines if (es.back() == 'L') { // insert lines
es.cutLeft(1).cutRight(1); es.cutLeft(1).cutRight(1);
int v = es.toInt(); if (v == 0) v = 1; int v = es.toInt(); if (v == 0) v = 1;
for (int i = piClamp(size_y - 1, PRIVATE->win_y0, PRIVATE->win_y1); i >= piClamp(PRIVATE->cur_y + v, PRIVATE->win_y0, PRIVATE->win_y1); --i) cells[i] = cells[i - v]; for (int i = piClamp(size_y - 1, PRIVATE->win_y0, PRIVATE->win_y1); i >= piClamp(PRIVATE->cur_y + v, PRIVATE->win_y0, PRIVATE->win_y1); --i) cells[i] = cells[i - v];
for (int j = piClamp(PRIVATE->cur_y, PRIVATE->win_y0, PRIVATE->win_y1); j < piClamp(PRIVATE->cur_y + v, PRIVATE->win_y0, PRIVATE->win_y1); ++j) for (int j = piClamp(PRIVATE->cur_y, PRIVATE->win_y0, PRIVATE->win_y1); j < piClamp(PRIVATE->cur_y + v, PRIVATE->win_y0, PRIVATE->win_y1); ++j)
for (int i = 0; i < PRIVATE->cur_x; ++i) cells[j][i] = def_cell; for (int i = 0; i < PRIVATE->cur_x; ++i) cells[j][i] = def_cell;
} }
if (es.back() == 'M') { // delete lines if (es.back() == 'M') { // delete lines
es.cutLeft(1).cutRight(1); es.cutLeft(1).cutRight(1);
int v = es.toInt(); if (v == 0) v = 1; int v = es.toInt(); if (v == 0) v = 1;
for (int i = piClamp(PRIVATE->cur_y, PRIVATE->win_y0, PRIVATE->win_y1); i < piClamp(size_y - v, PRIVATE->win_y0, PRIVATE->win_y1); ++i) cells[i] = cells[i + v]; for (int i = piClamp(PRIVATE->cur_y, PRIVATE->win_y0, PRIVATE->win_y1); i < piClamp(size_y - v, PRIVATE->win_y0, PRIVATE->win_y1); ++i) cells[i] = cells[i + v];
for (int j = piClamp(size_y - v, PRIVATE->win_y0, PRIVATE->win_y1); j < piClamp(size_y, PRIVATE->win_y0, PRIVATE->win_y1); ++j) for (int j = piClamp(size_y - v, PRIVATE->win_y0, PRIVATE->win_y1); j < piClamp(size_y, PRIVATE->win_y0, PRIVATE->win_y1); ++j)
for (int i = 0; i < PRIVATE->cur_x; ++i) cells[j][i] = def_cell; for (int i = 0; i < PRIVATE->cur_x; ++i) cells[j][i] = def_cell;
} }
if (es.back() == 'P') { // delete characters if (es.back() == 'P') { // delete characters
es.cutLeft(1).cutRight(1); es.cutLeft(1).cutRight(1);
int v = es.toInt(); if (v == 0) v = 1; int v = es.toInt(); if (v == 0) v = 1;
for (int i = PRIVATE->cur_x; i < size_x - v; ++i) cells[PRIVATE->cur_y][i] = cells[PRIVATE->cur_y][i + v]; for (int i = PRIVATE->cur_x; i < size_x - v; ++i) cells[PRIVATE->cur_y][i] = cells[PRIVATE->cur_y][i + v];
for (int i = size_x - v; i < size_x; ++i) cells[PRIVATE->cur_y][i] = def_cell; for (int i = size_x - v; i < size_x; ++i) cells[PRIVATE->cur_y][i] = def_cell;
} }
if (es.back() == '@') { // delete characters if (es.back() == '@') { // delete characters
es.cutLeft(1).cutRight(1); es.cutLeft(1).cutRight(1);
int v = es.toInt(); if (v == 0) v = 1; int v = es.toInt(); if (v == 0) v = 1;
for (int i = size_x - 1; i >= PRIVATE->cur_x + v; --i) cells[PRIVATE->cur_y][i] = cells[PRIVATE->cur_y][i - v]; for (int i = size_x - 1; i >= PRIVATE->cur_x + v; --i) cells[PRIVATE->cur_y][i] = cells[PRIVATE->cur_y][i - v];
for (int i = PRIVATE->cur_x; i < PRIVATE->cur_x + v; ++i) cells[PRIVATE->cur_y][i] = def_cell; for (int i = PRIVATE->cur_x; i < PRIVATE->cur_x + v; ++i) cells[PRIVATE->cur_y][i] = def_cell;
} }
if (es.back() == 'J') { // erase data if (es.back() == 'J') { // erase data
es.cutLeft(1).cutRight(1); es.cutLeft(1).cutRight(1);
int v = es.toInt(); int v = es.toInt();
switch (v) { switch (v) {
case 0: case 0:
for (int i = PRIVATE->cur_x; i < size_x; ++i) cells[PRIVATE->cur_y][i] = def_cell; for (int i = PRIVATE->cur_x; i < size_x; ++i) cells[PRIVATE->cur_y][i] = def_cell;
for (int i = PRIVATE->cur_y + 1; i < size_y; ++i) cells[i].fill(def_cell); for (int i = PRIVATE->cur_y + 1; i < size_y; ++i) cells[i].fill(def_cell);
break; break;
case 1: case 1:
for (int i = 0; i <= PRIVATE->cur_x; ++i) cells[PRIVATE->cur_y][i] = def_cell; for (int i = 0; i <= PRIVATE->cur_x; ++i) cells[PRIVATE->cur_y][i] = def_cell;
for (int i = 0; i < PRIVATE->cur_y; ++i) cells[i].fill(def_cell); for (int i = 0; i < PRIVATE->cur_y; ++i) cells[i].fill(def_cell);
break; break;
case 2: case 2:
for (int i = 0; i < size_y; ++i) cells[i].fill(def_cell); for (int i = 0; i < size_y; ++i) cells[i].fill(def_cell);
//PRIVATE->cur_x = PRIVATE->cur_y = 0; //PRIVATE->cur_x = PRIVATE->cur_y = 0;
break; break;
} }
} }
if (es.back() == 'K') { // erase in line if (es.back() == 'K') { // erase in line
es.cutLeft(1).cutRight(1); es.cutLeft(1).cutRight(1);
int v = es.toInt(); int v = es.toInt();
switch (v) { switch (v) {
case 0: case 0:
for (int i = PRIVATE->cur_x; i < size_x; ++i) cells[PRIVATE->cur_y][i] = def_cell; for (int i = PRIVATE->cur_x; i < size_x; ++i) cells[PRIVATE->cur_y][i] = def_cell;
break; break;
case 1: case 1:
for (int i = 0; i <= PRIVATE->cur_x; ++i) cells[PRIVATE->cur_y][i] = def_cell; for (int i = 0; i <= PRIVATE->cur_x; ++i) cells[PRIVATE->cur_y][i] = def_cell;
break; break;
case 2: case 2:
cells[PRIVATE->cur_y].fill(def_cell); cells[PRIVATE->cur_y].fill(def_cell);
break; break;
} }
} }
} }
} }
void PITerminal::moveCursor(int dx, int dy) { void PITerminal::moveCursor(int dx, int dy) {
PRIVATE->cur_x += dx; PRIVATE->cur_x += dx;
PRIVATE->cur_y += dy; PRIVATE->cur_y += dy;
if (PRIVATE->cur_x < 0) PRIVATE->cur_x = 0; if (PRIVATE->cur_x < 0) PRIVATE->cur_x = 0;
if (PRIVATE->cur_y < 0) PRIVATE->cur_y = 0; if (PRIVATE->cur_y < 0) PRIVATE->cur_y = 0;
if (PRIVATE->cur_x >= size_x) { if (PRIVATE->cur_x >= size_x) {
PRIVATE->line_format = PRIVATE->cur_format; PRIVATE->line_format = PRIVATE->cur_format;
PRIVATE->cur_x = 0; PRIVATE->cur_x = 0;
PRIVATE->cur_y++; PRIVATE->cur_y++;
} }
if (PRIVATE->cur_y >= size_y) { if (PRIVATE->cur_y >= size_y) {
int scroll = piMini(PRIVATE->cur_y - size_y + 1, size_y - 1); int scroll = piMini(PRIVATE->cur_y - size_y + 1, size_y - 1);
//piCout << "scroll" << size_x << size_y << size_y - scroll - 1; //piCout << "scroll" << size_x << size_y << size_y - scroll - 1;
PRIVATE->cur_y = size_y - 1; PRIVATE->cur_y = size_y - 1;
for (int y = 0; y < size_y - scroll; ++y) for (int y = 0; y < size_y - scroll; ++y)
cells[y] = cells[y + scroll]; cells[y] = cells[y + scroll];
for (int y = size_y - scroll; y < size_y; ++y) for (int y = size_y - scroll; y < size_y; ++y)
cells[y].fill(PIScreenTypes::Cell()); cells[y].fill(PIScreenTypes::Cell());
} }
} }
int PITerminal::termType(const PIString & t) { int PITerminal::termType(const PIString & t) {
if (t == "xterm") return PIKbdListener::vt_xterm; if (t == "xterm") return PIKbdListener::vt_xterm;
else if (t == "linux") return PIKbdListener::vt_linux; else if (t == "linux") return PIKbdListener::vt_linux;
return PIKbdListener::vt_none; return PIKbdListener::vt_none;
} }
#endif #endif
bool PITerminal::initialize() { bool PITerminal::initialize() {
destroy(); destroy();
#ifdef WINDOWS #ifdef WINDOWS
/*SECURITY_ATTRIBUTES sa; /*SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = true; sa.bInheritHandle = true;
sa.lpSecurityDescriptor = 0; sa.lpSecurityDescriptor = 0;
if (!CreatePipe(&(PRIVATE->pipe_in[0]), &(PRIVATE->pipe_in[1]), &sa, 0)) { if (!CreatePipe(&(PRIVATE->pipe_in[0]), &(PRIVATE->pipe_in[1]), &sa, 0)) {
piCoutObj << "CreatePipe error," << errorString(); piCoutObj << "CreatePipe error," << errorString();
initPrivate(); initPrivate();
return false; return false;
} }
PRIVATE->hConBuf = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0, &sa, CONSOLE_TEXTMODE_BUFFER, 0); PRIVATE->hConBuf = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0, &sa, CONSOLE_TEXTMODE_BUFFER, 0);
if (PRIVATE->hConBuf == INVALID_HANDLE_VALUE) { if (PRIVATE->hConBuf == INVALID_HANDLE_VALUE) {
piCoutObj << "CreateConsoleScreenBuffer error," << errorString(); piCoutObj << "CreateConsoleScreenBuffer error," << errorString();
destroy(); destroy();
return false; return false;
}*/ }*/
//CreatePipe(&(PRIVATE->pipe_out[0]), &(PRIVATE->pipe_out[1]), &sa, 0); //CreatePipe(&(PRIVATE->pipe_out[0]), &(PRIVATE->pipe_out[1]), &sa, 0);
//SetHandleInformation(PRIVATE->pipe_in[1], HANDLE_FLAG_INHERIT, 0); //SetHandleInformation(PRIVATE->pipe_in[1], HANDLE_FLAG_INHERIT, 0);
//SetHandleInformation(PRIVATE->hConBuf, HANDLE_FLAG_INHERIT, 0); //SetHandleInformation(PRIVATE->hConBuf, HANDLE_FLAG_INHERIT, 0);
//GetStartupInfoA(&PRIVATE->si); //GetStartupInfoA(&PRIVATE->si);
memset(&PRIVATE->si, 0, sizeof(PRIVATE->si)); memset(&PRIVATE->si, 0, sizeof(PRIVATE->si));
PRIVATE->si.cb = sizeof(STARTUPINFO); PRIVATE->si.cb = sizeof(STARTUPINFO);
//PRIVATE->si.dwFlags |= STARTF_USESTDHANDLES; //PRIVATE->si.dwFlags |= STARTF_USESTDHANDLES;
PRIVATE->si.dwFlags |= STARTF_USESHOWWINDOW; PRIVATE->si.dwFlags |= STARTF_USESHOWWINDOW;
PRIVATE->si.dwFlags |= STARTF_USECOUNTCHARS; PRIVATE->si.dwFlags |= STARTF_USECOUNTCHARS;
//PRIVATE->si.hStdInput = PRIVATE->pipe; //PRIVATE->si.hStdInput = PRIVATE->pipe;
//PRIVATE->si.hStdOutput = PRIVATE->hConBuf; //PRIVATE->si.hStdOutput = PRIVATE->hConBuf;
//PRIVATE->si.hStdError = PRIVATE->hConBuf; //PRIVATE->si.hStdError = PRIVATE->hConBuf;
PRIVATE->si.wShowWindow = SW_HIDE; PRIVATE->si.wShowWindow = SW_HIDE;
PRIVATE->si.dwXCountChars = 80; PRIVATE->si.dwXCountChars = 80;
PRIVATE->si.dwYCountChars = 24; PRIVATE->si.dwYCountChars = 24;
memset(&PRIVATE->pi, 0, sizeof(PRIVATE->pi)); memset(&PRIVATE->pi, 0, sizeof(PRIVATE->pi));
PIString shmh = PIString::fromNumber(randomi() % 10000); PIString shmh = PIString::fromNumber(randomi() % 10000);
PIString pname = "\\\\.\\pipe\\piterm" + shmh; PIString pname = "\\\\.\\pipe\\piterm" + shmh;
PIString cmd = "piterminal \"" + shmh + "\" \"" + pname + "\""; PIString cmd = "piterminal \"" + shmh + "\" \"" + pname + "\"";
if(!CreateProcessA(0, (LPSTR)cmd.dataAscii(), 0, 0, false, CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP, 0, 0, &PRIVATE->si, &PRIVATE->pi)) { if(!CreateProcessA(0, (LPSTR)cmd.dataAscii(), 0, 0, false, CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP, 0, 0, &PRIVATE->si, &PRIVATE->pi)) {
piCoutObj << "CreateProcess error," << errorString(); piCoutObj << "CreateProcess error," << errorString();
destroy(); destroy();
return false; return false;
} }
PRIVATE->pipe = CreateNamedPipe((LPSTR)pname.dataAscii(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 2, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, 1000, NULL); PRIVATE->pipe = CreateNamedPipe((LPSTR)pname.dataAscii(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 2, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, 1000, NULL);
if (PRIVATE->pipe == INVALID_HANDLE_VALUE) { if (PRIVATE->pipe == INVALID_HANDLE_VALUE) {
piCoutObj << "CreateNamedPipe error," << errorString(); piCoutObj << "CreateNamedPipe error," << errorString();
destroy(); destroy();
return false; return false;
} }
PITimeMeasurer tm; PITimeMeasurer tm;
bool ok = false; bool ok = false;
while (tm.elapsed_m() < 1000) { while (tm.elapsed_m() < 1000) {
if (ConnectNamedPipe(PRIVATE->pipe, 0) == TRUE) { if (ConnectNamedPipe(PRIVATE->pipe, 0) == TRUE) {
ok = true; ok = true;
break; break;
} }
} }
if (!ok) { if (!ok) {
piCoutObj << "ConnectNamedPipe error," << errorString(); piCoutObj << "ConnectNamedPipe error," << errorString();
destroy(); destroy();
return false; return false;
} }
if (PRIVATE->shm) delete PRIVATE->shm; if (PRIVATE->shm) delete PRIVATE->shm;
PRIVATE->shm = new PISharedMemory("piterm_aux" + shmh, 1024*1024); PRIVATE->shm = new PISharedMemory("piterm_aux" + shmh, 1024*1024);
CloseHandle(PRIVATE->pi.hThread); CloseHandle(PRIVATE->pi.hThread);
resize(dsize_x, dsize_y); resize(dsize_x, dsize_y);
#else #else
# ifdef HAS_FORKPTY # ifdef HAS_FORKPTY
char pty[256]; memset(pty, 0, 256); char pty[256]; memset(pty, 0, 256);
winsize ws; winsize ws;
ws.ws_col = dsize_x; ws.ws_col = dsize_x;
ws.ws_row = dsize_y; ws.ws_row = dsize_y;
PIStringList env = PIProcess::currentEnvironment(); PIStringList env = PIProcess::currentEnvironment();
piForeachC (PIString & e, env) piForeachC (PIString & e, env)
if (e.startsWith("TERM=")) { if (e.startsWith("TERM=")) {
PRIVATE->term_type = termType(e.mid(5).trim().toLowerCase()); PRIVATE->term_type = termType(e.mid(5).trim().toLowerCase());
//piCout << PRIVATE->term_type; //piCout << PRIVATE->term_type;
piBreak; piBreak;
} }
pid_t fr = forkpty(&(PRIVATE->fd), pty, 0, &ws); pid_t fr = forkpty(&(PRIVATE->fd), pty, 0, &ws);
//piCoutObj << fr << PRIVATE->fd << pty; //piCoutObj << fr << PRIVATE->fd << pty;
if (fr == 0) { if (fr == 0) {
char ** argv = new char*[2]; char ** argv = new char*[2];
argv[0] = new char[PRIVATE->shell.lengthAscii() + 1]; argv[0] = new char[PRIVATE->shell.lengthAscii() + 1];
memcpy(argv[0], PRIVATE->shell.dataAscii(), PRIVATE->shell.lengthAscii()); memcpy(argv[0], PRIVATE->shell.dataAscii(), PRIVATE->shell.lengthAscii());
argv[0][PRIVATE->shell.lengthAscii()] = 0; argv[0][PRIVATE->shell.lengthAscii()] = 0;
argv[1] = 0; argv[1] = 0;
execvp(PRIVATE->shell.dataAscii(), argv); execvp(PRIVATE->shell.dataAscii(), argv);
delete[] argv[0]; delete[] argv[0];
delete[] argv; delete[] argv;
exit(0); exit(0);
} else { } else {
if (fr < 0 || PRIVATE->fd < 0) { if (fr < 0 || PRIVATE->fd < 0) {
piCoutObj << "forkpty error," << errorString(); piCoutObj << "forkpty error," << errorString();
initPrivate(); initPrivate();
return false; return false;
} }
PRIVATE->pid = fr; PRIVATE->pid = fr;
fcntl(PRIVATE->fd, F_SETFL, O_NONBLOCK); fcntl(PRIVATE->fd, F_SETFL, O_NONBLOCK);
/* /*
tcgetattr(PRIVATE->fd, &PRIVATE->desc); tcgetattr(PRIVATE->fd, &PRIVATE->desc);
PRIVATE->desc.c_oflag = PRIVATE->desc.c_lflag = PRIVATE->desc.c_cflag = 0; PRIVATE->desc.c_oflag = PRIVATE->desc.c_lflag = PRIVATE->desc.c_cflag = 0;
PRIVATE->desc.c_iflag = IGNBRK; PRIVATE->desc.c_iflag = IGNBRK;
PRIVATE->desc.c_cflag = CLOCAL | HUPCL; PRIVATE->desc.c_cflag = CLOCAL | HUPCL;
PRIVATE->desc.c_cflag |= (CSIZE & CS8); PRIVATE->desc.c_cflag |= (CSIZE & CS8);
PRIVATE->desc.c_cflag |= CREAD; PRIVATE->desc.c_cflag |= CREAD;
PRIVATE->desc.c_cc[VMIN] = 1; PRIVATE->desc.c_cc[VMIN] = 1;
PRIVATE->desc.c_cc[VTIME] = 1; PRIVATE->desc.c_cc[VTIME] = 1;
cfsetispeed(&PRIVATE->desc, B38400); cfsetispeed(&PRIVATE->desc, B38400);
cfsetospeed(&PRIVATE->desc, B38400); cfsetospeed(&PRIVATE->desc, B38400);
if (tcsetattr(PRIVATE->fd, TCSANOW, &PRIVATE->desc) < 0) { if (tcsetattr(PRIVATE->fd, TCSANOW, &PRIVATE->desc) < 0) {
piCoutObj << "Can`t set attributes for \"" << pty << "\""; piCoutObj << "Can`t set attributes for \"" << pty << "\"";
destroy(); destroy();
return false; return false;
} }
*/ */
size_x = dsize_x; size_x = dsize_x;
size_y = dsize_y; size_y = dsize_y;
resize(size_x, size_y); resize(size_x, size_y);
} }
# endif # endif
#endif #endif
cursor_blink = false; cursor_blink = false;
cursor_tm.reset(); cursor_tm.reset();
start(40); start(40);
return true; return true;
} }
void PITerminal::destroy() { void PITerminal::destroy() {
//piCout << "destroy ..."; //piCout << "destroy ...";
stop(); stop();
waitForFinish(1000); waitForFinish(1000);
#ifdef WINDOWS #ifdef WINDOWS
if (PRIVATE->pi.hProcess) { if (PRIVATE->pi.hProcess) {
//piCout << "term"; //piCout << "term";
//TerminateProcess(PRIVATE->pi.hProcess, 0); //TerminateProcess(PRIVATE->pi.hProcess, 0);
GenerateConsoleCtrlEvent(CTRL_C_EVENT, PRIVATE->pi.dwProcessId); GenerateConsoleCtrlEvent(CTRL_C_EVENT, PRIVATE->pi.dwProcessId);
CloseHandle(PRIVATE->pi.hProcess); CloseHandle(PRIVATE->pi.hProcess);
} }
if (PRIVATE->pipe != INVALID_HANDLE_VALUE) CloseHandle(PRIVATE->pipe); if (PRIVATE->pipe != INVALID_HANDLE_VALUE) CloseHandle(PRIVATE->pipe);
if (PRIVATE->hConBuf != INVALID_HANDLE_VALUE) CloseHandle(PRIVATE->hConBuf); if (PRIVATE->hConBuf != INVALID_HANDLE_VALUE) CloseHandle(PRIVATE->hConBuf);
//piCout << "destroy" << size_y; //piCout << "destroy" << size_y;
#else #else
# ifdef HAS_FORKPTY # ifdef HAS_FORKPTY
if (PRIVATE->pid != 0) if (PRIVATE->pid != 0)
kill(PRIVATE->pid, SIGKILL); kill(PRIVATE->pid, SIGKILL);
if (PRIVATE->fd != 0) if (PRIVATE->fd != 0)
::close(PRIVATE->fd); ::close(PRIVATE->fd);
# endif # endif
#endif #endif
initPrivate(); initPrivate();
} }
bool PITerminal::resize(int cols, int rows) { bool PITerminal::resize(int cols, int rows) {
bool ret = true; bool ret = true;
dsize_x = cols; dsize_x = cols;
dsize_y = rows; dsize_y = rows;
#ifdef WINDOWS #ifdef WINDOWS
if (PRIVATE->pipe == INVALID_HANDLE_VALUE) return false; if (PRIVATE->pipe == INVALID_HANDLE_VALUE) return false;
PIByteArray msg; PIByteArray msg;
msg << int(mtResize) << dsize_x << dsize_y; msg << int(mtResize) << dsize_x << dsize_y;
writePipe(PRIVATE->pipe, msg); writePipe(PRIVATE->pipe, msg);
#else #else
# ifdef HAS_FORKPTY # ifdef HAS_FORKPTY
if (PRIVATE->fd == 0) return false; if (PRIVATE->fd == 0) return false;
size_x = dsize_x; size_x = dsize_x;
size_y = dsize_y; size_y = dsize_y;
//piCout << "resize" << PRIVATE->fd << size_x << size_y; //piCout << "resize" << PRIVATE->fd << size_x << size_y;
winsize ws; winsize ws;
ws.ws_col = cols; ws.ws_col = cols;
ws.ws_row = rows; ws.ws_row = rows;
ioctl(PRIVATE->fd, TIOCSWINSZ, &ws); ioctl(PRIVATE->fd, TIOCSWINSZ, &ws);
PRIVATE->win_y0 = 0; PRIVATE->win_y0 = 0;
PRIVATE->win_y1 = size_y - 1; PRIVATE->win_y1 = size_y - 1;
PRIVATE->cells_save.resize(size_y); PRIVATE->cells_save.resize(size_y);
for (int i = 0; i < size_y; ++i) for (int i = 0; i < size_y; ++i)
PRIVATE->cells_save[i].resize(size_x); PRIVATE->cells_save[i].resize(size_x);
# endif # endif
#endif #endif
cells.resize(size_y); cells.resize(size_y);
for (int i = 0; i < size_y; ++i) for (int i = 0; i < size_y; ++i)
cells[i].resize(size_x); cells[i].resize(size_x);
return ret; return ret;
} }
#endif // FREERTOS #endif // FREERTOS

View File

@@ -1,5 +1,5 @@
add_executable(piterminal "main.cpp") add_executable(piterminal "main.cpp")
target_link_libraries(piterminal pip) target_link_libraries(piterminal pip pip_console)
if (DEFINED LIB) if (DEFINED LIB)
install(TARGETS piterminal DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) install(TARGETS piterminal DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
endif () endif ()

View File

@@ -1,280 +1,280 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Terminal client for windows, used by PITerminal and pisd Terminal client for windows, used by PITerminal and pisd
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "piincludes_p.h" #include "piincludes_p.h"
#ifndef WINDOWS #ifndef WINDOWS
int main (int argc, char * argv[]) { int main (int argc, char * argv[]) {
return 0; return 0;
} }
#else #else
# include "piscreentypes.h" # include "piscreentypes.h"
# include "pisharedmemory.h" # include "pisharedmemory.h"
# include "piterminal.cpp" # include "../../lib/console/piterminal.cpp"
# include "pifile.h" # include "pifile.h"
# include <wincon.h> # include <wincon.h>
PIVector<PIVector<PIScreenTypes::Cell> > cells; PIVector<PIVector<PIScreenTypes::Cell> > cells;
CONSOLE_SCREEN_BUFFER_INFO sbi; CONSOLE_SCREEN_BUFFER_INFO sbi;
CHAR_INFO * chars = 0; CHAR_INFO * chars = 0;
HANDLE console = 0, cstdin = 0, pipe = 0, cmd_proc = 0; HANDLE console = 0, cstdin = 0, pipe = 0, cmd_proc = 0;
PITerminalAuxData data_out; PITerminalAuxData data_out;
PIMutex con_mutex; PIMutex con_mutex;
int con_w = -1, con_h = -1; int con_w = -1, con_h = -1;
PIScreenTypes::Cell CharInfo2Cell(const CHAR_INFO & c) { PIScreenTypes::Cell CharInfo2Cell(const CHAR_INFO & c) {
PIScreenTypes::Cell ret; PIScreenTypes::Cell ret;
ret.symbol = PIChar::fromConsole(c.Char.AsciiChar); ret.symbol = PIChar::fromConsole(c.Char.AsciiChar);
ret.format.color_char = PIScreenTypes::Black; ret.format.color_char = PIScreenTypes::Black;
if ((c.Attributes & (FOREGROUND_RED)) == FOREGROUND_RED) ret.format.color_char = PIScreenTypes::Red; if ((c.Attributes & (FOREGROUND_RED)) == FOREGROUND_RED) ret.format.color_char = PIScreenTypes::Red;
if ((c.Attributes & (FOREGROUND_GREEN)) == FOREGROUND_GREEN) ret.format.color_char = PIScreenTypes::Green; if ((c.Attributes & (FOREGROUND_GREEN)) == FOREGROUND_GREEN) ret.format.color_char = PIScreenTypes::Green;
if ((c.Attributes & (FOREGROUND_BLUE)) == FOREGROUND_BLUE) ret.format.color_char = PIScreenTypes::Blue; if ((c.Attributes & (FOREGROUND_BLUE)) == FOREGROUND_BLUE) ret.format.color_char = PIScreenTypes::Blue;
if ((c.Attributes & (FOREGROUND_GREEN | FOREGROUND_BLUE)) == (FOREGROUND_GREEN | FOREGROUND_BLUE)) ret.format.color_char = PIScreenTypes::Cyan; if ((c.Attributes & (FOREGROUND_GREEN | FOREGROUND_BLUE)) == (FOREGROUND_GREEN | FOREGROUND_BLUE)) ret.format.color_char = PIScreenTypes::Cyan;
if ((c.Attributes & (FOREGROUND_RED | FOREGROUND_BLUE)) == (FOREGROUND_RED | FOREGROUND_BLUE)) ret.format.color_char = PIScreenTypes::Magenta; if ((c.Attributes & (FOREGROUND_RED | FOREGROUND_BLUE)) == (FOREGROUND_RED | FOREGROUND_BLUE)) ret.format.color_char = PIScreenTypes::Magenta;
if ((c.Attributes & (FOREGROUND_RED | FOREGROUND_GREEN)) == (FOREGROUND_RED | FOREGROUND_GREEN)) ret.format.color_char = PIScreenTypes::Yellow; if ((c.Attributes & (FOREGROUND_RED | FOREGROUND_GREEN)) == (FOREGROUND_RED | FOREGROUND_GREEN)) ret.format.color_char = PIScreenTypes::Yellow;
if ((c.Attributes & (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)) == (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)) ret.format.color_char = PIScreenTypes::White; if ((c.Attributes & (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)) == (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)) ret.format.color_char = PIScreenTypes::White;
ret.format.color_back = PIScreenTypes::Black; ret.format.color_back = PIScreenTypes::Black;
if ((c.Attributes & (BACKGROUND_RED)) == (BACKGROUND_RED)) ret.format.color_back = PIScreenTypes::Red; if ((c.Attributes & (BACKGROUND_RED)) == (BACKGROUND_RED)) ret.format.color_back = PIScreenTypes::Red;
if ((c.Attributes & (BACKGROUND_GREEN)) == (BACKGROUND_GREEN)) ret.format.color_back = PIScreenTypes::Green; if ((c.Attributes & (BACKGROUND_GREEN)) == (BACKGROUND_GREEN)) ret.format.color_back = PIScreenTypes::Green;
if ((c.Attributes & (BACKGROUND_BLUE)) == (BACKGROUND_BLUE)) ret.format.color_back = PIScreenTypes::Blue; if ((c.Attributes & (BACKGROUND_BLUE)) == (BACKGROUND_BLUE)) ret.format.color_back = PIScreenTypes::Blue;
if ((c.Attributes & (BACKGROUND_GREEN | BACKGROUND_BLUE)) == (BACKGROUND_GREEN | BACKGROUND_BLUE)) ret.format.color_back = PIScreenTypes::Cyan; if ((c.Attributes & (BACKGROUND_GREEN | BACKGROUND_BLUE)) == (BACKGROUND_GREEN | BACKGROUND_BLUE)) ret.format.color_back = PIScreenTypes::Cyan;
if ((c.Attributes & (BACKGROUND_RED | BACKGROUND_BLUE)) == (BACKGROUND_RED | BACKGROUND_BLUE)) ret.format.color_back = PIScreenTypes::Magenta; if ((c.Attributes & (BACKGROUND_RED | BACKGROUND_BLUE)) == (BACKGROUND_RED | BACKGROUND_BLUE)) ret.format.color_back = PIScreenTypes::Magenta;
if ((c.Attributes & (BACKGROUND_RED | BACKGROUND_GREEN)) == (BACKGROUND_RED | BACKGROUND_GREEN)) ret.format.color_back = PIScreenTypes::Yellow; if ((c.Attributes & (BACKGROUND_RED | BACKGROUND_GREEN)) == (BACKGROUND_RED | BACKGROUND_GREEN)) ret.format.color_back = PIScreenTypes::Yellow;
if ((c.Attributes & (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)) == (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)) ret.format.color_back = PIScreenTypes::White; if ((c.Attributes & (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)) == (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)) ret.format.color_back = PIScreenTypes::White;
if ((c.Attributes & (FOREGROUND_INTENSITY)) > 0) ret.format.flags |= PIScreenTypes::Bold; if ((c.Attributes & (FOREGROUND_INTENSITY)) > 0) ret.format.flags |= PIScreenTypes::Bold;
return ret; return ret;
} }
int SpecialKey2VirtualKeyCode(PIKbdListener::SpecialKey k) { int SpecialKey2VirtualKeyCode(PIKbdListener::SpecialKey k) {
switch (k) { switch (k) {
case PIKbdListener::Tab : return '\t'; break; case PIKbdListener::Tab : return '\t'; break;
case PIKbdListener::Return : return '\n'; break; case PIKbdListener::Return : return '\n'; break;
case PIKbdListener::Space : return ' '; break; case PIKbdListener::Space : return ' '; break;
case PIKbdListener::Backspace : return 8 ; case PIKbdListener::Backspace : return 8 ;
case PIKbdListener::PageUp : return 33 ; case PIKbdListener::PageUp : return 33 ;
case PIKbdListener::PageDown : return 34 ; case PIKbdListener::PageDown : return 34 ;
case PIKbdListener::End : return 35 ; case PIKbdListener::End : return 35 ;
case PIKbdListener::Home : return 36 ; case PIKbdListener::Home : return 36 ;
case PIKbdListener::LeftArrow : return 37 ; case PIKbdListener::LeftArrow : return 37 ;
case PIKbdListener::UpArrow : return 38 ; case PIKbdListener::UpArrow : return 38 ;
case PIKbdListener::RightArrow: return 39 ; case PIKbdListener::RightArrow: return 39 ;
case PIKbdListener::DownArrow : return 40 ; case PIKbdListener::DownArrow : return 40 ;
case PIKbdListener::Insert : return 45 ; case PIKbdListener::Insert : return 45 ;
case PIKbdListener::Delete : return 46 ; case PIKbdListener::Delete : return 46 ;
case PIKbdListener::F1 : return 112; case PIKbdListener::F1 : return 112;
case PIKbdListener::F2 : return 113; case PIKbdListener::F2 : return 113;
case PIKbdListener::F3 : return 114; case PIKbdListener::F3 : return 114;
case PIKbdListener::F4 : return 115; case PIKbdListener::F4 : return 115;
case PIKbdListener::F5 : return 116; case PIKbdListener::F5 : return 116;
case PIKbdListener::F6 : return 117; case PIKbdListener::F6 : return 117;
case PIKbdListener::F7 : return 118; case PIKbdListener::F7 : return 118;
case PIKbdListener::F8 : return 119; case PIKbdListener::F8 : return 119;
case PIKbdListener::F9 : return 120; case PIKbdListener::F9 : return 120;
case PIKbdListener::F10 : return 121; case PIKbdListener::F10 : return 121;
case PIKbdListener::F11 : return 122; case PIKbdListener::F11 : return 122;
case PIKbdListener::F12 : return 123; case PIKbdListener::F12 : return 123;
default: break; default: break;
} }
return 0; return 0;
} }
int KeyModifiers2ControlKeyState(PIKbdListener::KeyModifiers m) { int KeyModifiers2ControlKeyState(PIKbdListener::KeyModifiers m) {
int ret(0); int ret(0);
if (m[PIKbdListener::Ctrl]) ret |= LEFT_CTRL_PRESSED; if (m[PIKbdListener::Ctrl]) ret |= LEFT_CTRL_PRESSED;
if (m[PIKbdListener::Shift]) ret |= SHIFT_PRESSED; if (m[PIKbdListener::Shift]) ret |= SHIFT_PRESSED;
if (m[PIKbdListener::Alt]) ret |= LEFT_ALT_PRESSED; if (m[PIKbdListener::Alt]) ret |= LEFT_ALT_PRESSED;
return ret; return ret;
} }
void readConsole(int x, int y, int w, int h) { void readConsole(int x, int y, int w, int h) {
GetConsoleScreenBufferInfo(console, &sbi); GetConsoleScreenBufferInfo(console, &sbi);
COORD bs, bc; COORD bs, bc;
bs.X = w; bs.X = w;
bs.Y = h; bs.Y = h;
bc.X = bc.Y = 0; bc.X = bc.Y = 0;
memset(chars, 0, w * h * sizeof(CHAR_INFO)); memset(chars, 0, w * h * sizeof(CHAR_INFO));
ReadConsoleOutput(console, chars, bs, bc, &(sbi.srWindow)); ReadConsoleOutput(console, chars, bs, bc, &(sbi.srWindow));
for (int i = 0; i < h; ++i) for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j) for (int j = 0; j < w; ++j)
cells[i][j] = CharInfo2Cell(chars[i * w + j]); cells[i][j] = CharInfo2Cell(chars[i * w + j]);
} }
void resizeCells(int w, int h) { void resizeCells(int w, int h) {
if (chars) delete[] chars; if (chars) delete[] chars;
chars = new CHAR_INFO[w * h]; chars = new CHAR_INFO[w * h];
cells.resize(h); cells.resize(h);
for (int i = 0; i < h; ++i) for (int i = 0; i < h; ++i)
cells[i].resize(w); cells[i].resize(w);
} }
void resizeConsole(int w, int h) { void resizeConsole(int w, int h) {
if (con_w == w && con_h == h) return; if (con_w == w && con_h == h) return;
con_w = w; con_w = w;
con_h = h; con_h = h;
GetConsoleScreenBufferInfo(console, &sbi); GetConsoleScreenBufferInfo(console, &sbi);
sbi.srWindow.Left = 0; sbi.srWindow.Left = 0;
sbi.srWindow.Right = sbi.srWindow.Left + w - 1; sbi.srWindow.Right = sbi.srWindow.Left + w - 1;
sbi.srWindow.Bottom = sbi.srWindow.Top + h - 1; sbi.srWindow.Bottom = sbi.srWindow.Top + h - 1;
COORD sz; sz.X = w; sz.Y = h; COORD sz; sz.X = w; sz.Y = h;
SetConsoleScreenBufferSize(console, sz); SetConsoleScreenBufferSize(console, sz);
SetConsoleWindowInfo(console, TRUE, &(sbi.srWindow)); SetConsoleWindowInfo(console, TRUE, &(sbi.srWindow));
//system(("mode CON: COLS=" + PIString::fromNumber(w) + " LINES=" + PIString::fromNumber(h)).dataAscii()); //system(("mode CON: COLS=" + PIString::fromNumber(w) + " LINES=" + PIString::fromNumber(h)).dataAscii());
resizeCells(w, h); resizeCells(w, h);
} }
class PipeReader: public PIThread { class PipeReader: public PIThread {
public: public:
PipeReader(): PIThread() { PipeReader(): PIThread() {
wrote = readed = 0; wrote = readed = 0;
msg_size = 0; msg_size = 0;
start(1); start(1);
} }
~PipeReader() { ~PipeReader() {
stop(); stop();
} }
void run() { void run() {
in.resize(PIPE_BUFFER_SIZE); in.resize(PIPE_BUFFER_SIZE);
ReadFile(pipe, in.data(), in.size_s(), &readed, 0); ReadFile(pipe, in.data(), in.size_s(), &readed, 0);
if (GetLastError() == ERROR_BROKEN_PIPE) { if (GetLastError() == ERROR_BROKEN_PIPE) {
stop(); stop();
return; return;
} }
//piCout << errorString(); //piCout << errorString();
if (readed > 0) { if (readed > 0) {
in.resize(readed); in.resize(readed);
stream.append(in); stream.append(in);
if (msg_size == 0) { if (msg_size == 0) {
if (stream.size_s() < 4) return; if (stream.size_s() < 4) return;
stream >> msg_size; stream >> msg_size;
} }
if (stream.size_s() >= msg_size) { if (stream.size_s() >= msg_size) {
msg = PIByteArray(stream.data(), msg_size); msg = PIByteArray(stream.data(), msg_size);
stream.remove(0, msg_size); stream.remove(0, msg_size);
msg_size = 0; msg_size = 0;
parseMessage(); parseMessage();
} }
if (msg_size == 0 && stream.size_s() < 4) return; if (msg_size == 0 && stream.size_s() < 4) return;
} }
} }
void parseMessage() { void parseMessage() {
if (msg.size_s() < 4) return; if (msg.size_s() < 4) return;
PIMutexLocker _ml(con_mutex); PIMutexLocker _ml(con_mutex);
int type; msg >> type; int type; msg >> type;
//piCout << "msg" << type; //piCout << "msg" << type;
switch ((PITerminalAuxMessageType)type) { switch ((PITerminalAuxMessageType)type) {
case mtKey: { case mtKey: {
PIVector<PIKbdListener::KeyEvent> ke; PIVector<PIKbdListener::KeyEvent> ke;
msg >> ke; msg >> ke;
PIVector<INPUT_RECORD> ir(ke.size() * 2); PIVector<INPUT_RECORD> ir(ke.size() * 2);
for (int i = 0; i < ke.size_s(); ++i) { for (int i = 0; i < ke.size_s(); ++i) {
PIKbdListener::KeyEvent k(ke[i]); PIKbdListener::KeyEvent k(ke[i]);
int j = i+i, z = j+1; int j = i+i, z = j+1;
ir[j].EventType = KEY_EVENT; ir[j].EventType = KEY_EVENT;
ir[j].Event.KeyEvent.wRepeatCount = 1; ir[j].Event.KeyEvent.wRepeatCount = 1;
ir[j].Event.KeyEvent.dwControlKeyState = KeyModifiers2ControlKeyState(k.modifiers); ir[j].Event.KeyEvent.dwControlKeyState = KeyModifiers2ControlKeyState(k.modifiers);
if (PITerminal::isSpecialKey(k.key)) { if (PITerminal::isSpecialKey(k.key)) {
ir[j].Event.KeyEvent.wVirtualKeyCode = SpecialKey2VirtualKeyCode((PIKbdListener::SpecialKey)k.key); ir[j].Event.KeyEvent.wVirtualKeyCode = SpecialKey2VirtualKeyCode((PIKbdListener::SpecialKey)k.key);
ir[j].Event.KeyEvent.uChar.AsciiChar = PIChar(piMaxi(k.key, 0)).toAscii(); ir[j].Event.KeyEvent.uChar.AsciiChar = PIChar(piMaxi(k.key, 0)).toAscii();
} else } else
ir[j].Event.KeyEvent.uChar.UnicodeChar = PIChar(piMaxi(k.key, 0)).toWChar(); ir[j].Event.KeyEvent.uChar.UnicodeChar = PIChar(piMaxi(k.key, 0)).toWChar();
//piCout << ir[j].Event.KeyEvent.wVirtualKeyCode << int(ir[j].Event.KeyEvent.uChar.AsciiChar); //piCout << ir[j].Event.KeyEvent.wVirtualKeyCode << int(ir[j].Event.KeyEvent.uChar.AsciiChar);
ir[j].Event.KeyEvent.bKeyDown = true; ir[j].Event.KeyEvent.bKeyDown = true;
ir[z] = ir[j]; ir[z] = ir[j];
ir[z].Event.KeyEvent.bKeyDown = false; ir[z].Event.KeyEvent.bKeyDown = false;
} }
WriteConsoleInput(cstdin, ir.data(), ir.size_s(), &wrote); WriteConsoleInput(cstdin, ir.data(), ir.size_s(), &wrote);
} break; } break;
case mtResize: { case mtResize: {
int rw, rh; int rw, rh;
msg >> rw >> rh; msg >> rw >> rh;
resizeConsole(rw, rh); resizeConsole(rw, rh);
} break; } break;
default: break; default: break;
} }
} }
DWORD wrote, readed; DWORD wrote, readed;
int msg_size; int msg_size;
PIByteArray in, stream, msg; PIByteArray in, stream, msg;
}; };
void getCursor(int & x, int & y) { void getCursor(int & x, int & y) {
GetConsoleScreenBufferInfo(console, &sbi); GetConsoleScreenBufferInfo(console, &sbi);
x = sbi.dwCursorPosition.X - sbi.srWindow.Left; x = sbi.dwCursorPosition.X - sbi.srWindow.Left;
y = sbi.dwCursorPosition.Y - sbi.srWindow.Top; y = sbi.dwCursorPosition.Y - sbi.srWindow.Top;
} }
int main (int argc, char * argv[]) { int main (int argc, char * argv[]) {
//piCout << "start"; //piCout << "start";
STARTUPINFO si; STARTUPINFO si;
PROCESS_INFORMATION pi; PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si)); memset(&si, 0, sizeof(si));
memset(&pi, 0, sizeof(pi)); memset(&pi, 0, sizeof(pi));
memset(&sbi, 0, sizeof(sbi)); memset(&sbi, 0, sizeof(sbi));
PIString shmh, pname; PIString shmh, pname;
if (argc > 1) shmh = argv[1]; if (argc > 1) shmh = argv[1];
if (argc > 2) pname = argv[2]; if (argc > 2) pname = argv[2];
if(!CreateProcessA(0, (LPSTR)"cmd", 0, 0, true, 0, 0, 0, &si, &pi)) { if(!CreateProcessA(0, (LPSTR)"cmd", 0, 0, true, 0, 0, 0, &si, &pi)) {
return 1; return 1;
} }
PISharedMemory shm("piterm_aux" + shmh, 1024*1024); PISharedMemory shm("piterm_aux" + shmh, 1024*1024);
pipe = CreateFile((LPSTR)pname.dataAscii(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); pipe = CreateFile((LPSTR)pname.dataAscii(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if (pipe == INVALID_HANDLE_VALUE) { if (pipe == INVALID_HANDLE_VALUE) {
return 1; return 1;
} }
CloseHandle(pi.hThread); CloseHandle(pi.hThread);
cmd_proc = pi.hProcess; cmd_proc = pi.hProcess;
console = GetStdHandle(STD_OUTPUT_HANDLE); console = GetStdHandle(STD_OUTPUT_HANDLE);
cstdin = GetStdHandle(STD_INPUT_HANDLE); cstdin = GetStdHandle(STD_INPUT_HANDLE);
resizeConsole(80, 24); resizeConsole(80, 24);
PipeReader pipe_reader; PipeReader pipe_reader;
pipe_reader.waitForStart(); pipe_reader.waitForStart();
PIByteArray scr; PIByteArray scr;
while (true) { while (true) {
//piCout << "loop"; //piCout << "loop";
if (!pipe_reader.isRunning()) break; if (!pipe_reader.isRunning()) break;
con_mutex.lock(); con_mutex.lock();
getCursor(data_out.cursor_x, data_out.cursor_y); getCursor(data_out.cursor_x, data_out.cursor_y);
readConsole(0, 0, con_w, con_h); readConsole(0, 0, con_w, con_h);
scr.clear(); scr.clear();
scr << cells; scr << cells;
data_out.size_x = con_w; data_out.size_x = con_w;
data_out.size_y = con_h; data_out.size_y = con_h;
data_out.cells_size = scr.size_s(); data_out.cells_size = scr.size_s();
con_mutex.unlock(); con_mutex.unlock();
shm.write(&data_out, sizeof(data_out)); shm.write(&data_out, sizeof(data_out));
shm.write(scr, sizeof(data_out)); shm.write(scr, sizeof(data_out));
piMSleep(25); piMSleep(25);
} }
//piCout << "exit"; //piCout << "exit";
TerminateProcess(pi.hProcess, 0); TerminateProcess(pi.hProcess, 0);
CloseHandle(pi.hProcess); CloseHandle(pi.hProcess);
return 0; return 0;
} }
#endif #endif

View File

@@ -1,38 +1,38 @@
/*! \file piccloudclient.h /*! \file piccloudclient.h
* \brief PICloud Client * \brief PICloud Client
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PICloud Client PICloud Client
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PICCLOUDCLIENT_H #ifndef PICCLOUDCLIENT_H
#define PICCLOUDCLIENT_H #define PICCLOUDCLIENT_H
#include "piiodevice.h" #include "piiodevice.h"
class PIP_EXPORT PICloudClient { class PIP_EXPORT PICloudClient {
public: public:
//! //!
explicit PICloudClient(); explicit PICloudClient();
private: private:
}; };
#endif // PICCLOUDCLIENT_H #endif // PICCLOUDCLIENT_H

View File

@@ -1,39 +1,39 @@
/*! \file piccloudserver.h /*! \file piccloudserver.h
* \brief PICloud Server * \brief PICloud Server
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PICloud Server PICloud Server
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PICCLOUDSERVER_H #ifndef PICCLOUDSERVER_H
#define PICCLOUDSERVER_H #define PICCLOUDSERVER_H
#include "piiodevice.h" #include "piiodevice.h"
class PIP_EXPORT PICloudServer { class PIP_EXPORT PICloudServer {
public: public:
//! //!
explicit PICloudServer(); explicit PICloudServer();
private: private:
}; };
#endif // PICCLOUDSERVER_H #endif // PICCLOUDSERVER_H

View File

@@ -1,38 +1,38 @@
/*! \file piccloudtcp.h /*! \file piccloudtcp.h
* \brief PICloud TCP transport * \brief PICloud TCP transport
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PICloud TCP transport PICloud TCP transport
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PICCLOUDTCP_H #ifndef PICCLOUDTCP_H
#define PICCLOUDTCP_H #define PICCLOUDTCP_H
#include "pistring.h" #include "pistring.h"
class PIP_EXPORT PICloudTCP { class PIP_EXPORT PICloudTCP {
public: public:
//! //!
PICloudTCP(); PICloudTCP();
private: private:
}; };
#endif // PICCLOUDTCP_H #endif // PICCLOUDTCP_H

View File

View File

View File

View File

View File

@@ -1,63 +1,63 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Stephan Fomenko Stephan Fomenko
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PIP_TESTS_EXECUTOR_H #ifndef PIP_TESTS_EXECUTOR_H
#define PIP_TESTS_EXECUTOR_H #define PIP_TESTS_EXECUTOR_H
#include "piblockingdequeue.h" #include "piblockingdequeue.h"
/** /**
* @brief Thread pools address two different problems: they usually provide improved performance when executing large * @brief Thread pools address two different problems: they usually provide improved performance when executing large
* numbers of asynchronous tasks, due to reduced per-task invocation overhead, and they provide a means of bounding and * numbers of asynchronous tasks, due to reduced per-task invocation overhead, and they provide a means of bounding and
* managing the resources, including threads, consumed when executing a collection of tasks. * managing the resources, including threads, consumed when executing a collection of tasks.
*/ */
class PIThreadPoolExecutor { class PIThreadPoolExecutor {
public: public:
explicit PIThreadPoolExecutor(size_t corePoolSize = 1, PIBlockingDequeue<std::function<void()> >* taskQueue_ = new PIBlockingDequeue<std::function<void()> >()); explicit PIThreadPoolExecutor(size_t corePoolSize = 1, PIBlockingDequeue<std::function<void()> >* taskQueue_ = new PIBlockingDequeue<std::function<void()> >());
virtual ~PIThreadPoolExecutor(); virtual ~PIThreadPoolExecutor();
/** /**
* @brief Executes the given task sometime in the future. The task execute in an existing pooled thread. If the task * @brief Executes the given task sometime in the future. The task execute in an existing pooled thread. If the task
* cannot be submitted for execution, either because this executor has been shutdown or because its capacity has been * cannot be submitted for execution, either because this executor has been shutdown or because its capacity has been
* reached. * reached.
* *
* @param runnable not empty function for thread pool execution * @param runnable not empty function for thread pool execution
*/ */
void execute(const std::function<void()>& runnable); void execute(const std::function<void()>& runnable);
void shutdownNow(); void shutdownNow();
/** /**
* @brief Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be * @brief Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be
* accepted. Invocation has no additional effect if already shut down. This method does not wait for previously * accepted. Invocation has no additional effect if already shut down. This method does not wait for previously
* submitted tasks to complete execution. Use awaitTermination to do that. * submitted tasks to complete execution. Use awaitTermination to do that.
*/ */
void shutdown(); void shutdown();
volatile bool isShutdown() const; volatile bool isShutdown() const;
bool awaitTermination(int timeoutMs); bool awaitTermination(int timeoutMs);
private: private:
volatile bool isShutdown_; volatile bool isShutdown_;
PIBlockingDequeue<std::function<void()> >* taskQueue; PIBlockingDequeue<std::function<void()> >* taskQueue;
PIVector<PIThread*> threadPool; PIVector<PIThread*> threadPool;
}; };
#endif //PIP_TESTS_EXECUTOR_H #endif //PIP_TESTS_EXECUTOR_H

View File

@@ -1,223 +1,223 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Stephan Fomenko Stephan Fomenko
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PIP_TESTS_PIBLOCKINGDEQUEUE_H #ifndef PIP_TESTS_PIBLOCKINGDEQUEUE_H
#define PIP_TESTS_PIBLOCKINGDEQUEUE_H #define PIP_TESTS_PIBLOCKINGDEQUEUE_H
#include "pideque.h" #include "pideque.h"
#include "piconditionvar.h" #include "piconditionvar.h"
/** /**
* @brief A Queue that supports operations that wait for the queue to become non-empty when retrieving an element, and * @brief A Queue that supports operations that wait for the queue to become non-empty when retrieving an element, and
* wait for space to become available in the queue when storing an element. * wait for space to become available in the queue when storing an element.
*/ */
template <typename T> template <typename T>
class PIBlockingDequeue: private PIDeque<T> { class PIBlockingDequeue: private PIDeque<T> {
public: public:
/** /**
* @brief Constructor * @brief Constructor
*/ */
explicit inline PIBlockingDequeue(size_t capacity = SIZE_MAX, explicit inline PIBlockingDequeue(size_t capacity = SIZE_MAX,
PIConditionVariable* cond_var_add = new PIConditionVariable(), PIConditionVariable* cond_var_add = new PIConditionVariable(),
PIConditionVariable* cond_var_rem = new PIConditionVariable()) PIConditionVariable* cond_var_rem = new PIConditionVariable())
: cond_var_add(cond_var_add), cond_var_rem(cond_var_rem), max_size(capacity) { } : cond_var_add(cond_var_add), cond_var_rem(cond_var_rem), max_size(capacity) { }
/** /**
* @brief Copy constructor. Initialize queue with copy of other queue elements. Not thread-safe for other queue. * @brief Copy constructor. Initialize queue with copy of other queue elements. Not thread-safe for other queue.
*/ */
explicit inline PIBlockingDequeue(const PIDeque<T>& other) : cond_var_add(new PIConditionVariable()), cond_var_rem(new PIConditionVariable()) { explicit inline PIBlockingDequeue(const PIDeque<T>& other) : cond_var_add(new PIConditionVariable()), cond_var_rem(new PIConditionVariable()) {
mutex.lock(); mutex.lock();
max_size = SIZE_MAX; max_size = SIZE_MAX;
PIDeque<T>::append(other); PIDeque<T>::append(other);
mutex.unlock(); mutex.unlock();
} }
/** /**
* @brief Thread-safe copy constructor. Initialize queue with copy of other queue elements. * @brief Thread-safe copy constructor. Initialize queue with copy of other queue elements.
*/ */
inline PIBlockingDequeue(PIBlockingDequeue<T> & other) : cond_var_add(new PIConditionVariable()), cond_var_rem(new PIConditionVariable()) { inline PIBlockingDequeue(PIBlockingDequeue<T> & other) : cond_var_add(new PIConditionVariable()), cond_var_rem(new PIConditionVariable()) {
other.mutex.lock(); other.mutex.lock();
mutex.lock(); mutex.lock();
max_size = other.max_size; max_size = other.max_size;
PIDeque<T>::append(static_cast<PIDeque<T>&>(other)); PIDeque<T>::append(static_cast<PIDeque<T>&>(other));
mutex.unlock(); mutex.unlock();
other.mutex.unlock(); other.mutex.unlock();
} }
~PIBlockingDequeue() { ~PIBlockingDequeue() {
delete cond_var_add; delete cond_var_add;
delete cond_var_rem; delete cond_var_rem;
} }
/** /**
* @brief Inserts the specified element into this queue, waiting if necessary for space to become available. * @brief Inserts the specified element into this queue, waiting if necessary for space to become available.
* *
* @param v the element to add * @param v the element to add
*/ */
void put(const T & v) { void put(const T & v) {
mutex.lock(); mutex.lock();
cond_var_rem->wait(mutex, [&]() { return PIDeque<T>::size() < max_size; }); cond_var_rem->wait(mutex, [&]() { return PIDeque<T>::size() < max_size; });
PIDeque<T>::push_back(v); PIDeque<T>::push_back(v);
mutex.unlock(); mutex.unlock();
cond_var_add->notifyOne(); cond_var_add->notifyOne();
} }
/** /**
* @brief Inserts the specified element at the end of this queue if it is possible to do so immediately without * @brief Inserts the specified element at the end of this queue if it is possible to do so immediately without
* exceeding the queue's capacity, returning true upon success and false if this queue is full. * exceeding the queue's capacity, returning true upon success and false if this queue is full.
* *
* @param v the element to add * @param v the element to add
* @return true if the element was added to this queue, else false * @return true if the element was added to this queue, else false
*/ */
bool offer(const T & v) { bool offer(const T & v) {
mutex.lock(); mutex.lock();
if (PIDeque<T>::size() >= max_size) { if (PIDeque<T>::size() >= max_size) {
mutex.unlock(); mutex.unlock();
return false; return false;
} }
PIDeque<T>::push_back(v); PIDeque<T>::push_back(v);
mutex.unlock(); mutex.unlock();
cond_var_add->notifyOne(); cond_var_add->notifyOne();
return true; return true;
} }
/** /**
* @brief Inserts the specified element into this queue, waiting up to the specified wait time if necessary for * @brief Inserts the specified element into this queue, waiting up to the specified wait time if necessary for
* space to become available. * space to become available.
* *
* @param v the element to add * @param v the element to add
* @param timeoutMs how long to wait before giving up, in milliseconds * @param timeoutMs how long to wait before giving up, in milliseconds
* @return true if successful, or false if the specified waiting time elapses before space is available * @return true if successful, or false if the specified waiting time elapses before space is available
*/ */
bool offer(const T & v, int timeoutMs) { bool offer(const T & v, int timeoutMs) {
mutex.lock(); mutex.lock();
bool isOk = cond_var_rem->waitFor(mutex, timeoutMs, [&]() { return PIDeque<T>::size() < max_size; } ); bool isOk = cond_var_rem->waitFor(mutex, timeoutMs, [&]() { return PIDeque<T>::size() < max_size; } );
if (isOk) PIDeque<T>::push_back(v); if (isOk) PIDeque<T>::push_back(v);
mutex.unlock(); mutex.unlock();
if (isOk) cond_var_add->notifyOne(); if (isOk) cond_var_add->notifyOne();
return isOk; return isOk;
} }
/** /**
* @brief Retrieves and removes the head of this queue, waiting if necessary until an element becomes available. * @brief Retrieves and removes the head of this queue, waiting if necessary until an element becomes available.
* *
* @return the head of this queue * @return the head of this queue
*/ */
T take() { T take() {
T t; T t;
mutex.lock(); mutex.lock();
cond_var_add->wait(mutex, [&]() { return !PIDeque<T>::isEmpty(); }); cond_var_add->wait(mutex, [&]() { return !PIDeque<T>::isEmpty(); });
t = T(PIDeque<T>::take_front()); t = T(PIDeque<T>::take_front());
mutex.unlock(); mutex.unlock();
cond_var_rem->notifyOne(); cond_var_rem->notifyOne();
return t; return t;
} }
/** /**
* @brief Retrieves and removes the head of this queue, waiting up to the specified wait time if necessary for an * @brief Retrieves and removes the head of this queue, waiting up to the specified wait time if necessary for an
* element to become available. * element to become available.
* *
* @param timeoutMs how long to wait before giving up, in milliseconds * @param timeoutMs how long to wait before giving up, in milliseconds
* @param defaultVal value, which returns if the specified waiting time elapses before an element is available * @param defaultVal value, which returns if the specified waiting time elapses before an element is available
* @return the head of this queue, or defaultVal if the specified waiting time elapses before an element is available * @return the head of this queue, or defaultVal if the specified waiting time elapses before an element is available
*/ */
T poll(int timeoutMs, const T & defaultVal, bool* isOk = nullptr) { T poll(int timeoutMs, const T & defaultVal, bool* isOk = nullptr) {
T t; T t;
mutex.lock(); mutex.lock();
bool isNotEmpty = cond_var_add->waitFor(mutex, timeoutMs, [&]() { return !PIDeque<T>::isEmpty(); }); bool isNotEmpty = cond_var_add->waitFor(mutex, timeoutMs, [&]() { return !PIDeque<T>::isEmpty(); });
t = isNotEmpty ? T(PIDeque<T>::take_front()) : defaultVal; t = isNotEmpty ? T(PIDeque<T>::take_front()) : defaultVal;
mutex.unlock(); mutex.unlock();
if (isNotEmpty) cond_var_rem->notifyOne(); if (isNotEmpty) cond_var_rem->notifyOne();
if (isOk != nullptr) *isOk = isNotEmpty; if (isOk != nullptr) *isOk = isNotEmpty;
return t; return t;
} }
/** /**
* @brief Returns the number of elements that this queue can ideally (in the absence of memory or resource * @brief Returns the number of elements that this queue can ideally (in the absence of memory or resource
* constraints) contains. This is always equal to the initial capacity of this queue less the current size of this queue. * constraints) contains. This is always equal to the initial capacity of this queue less the current size of this queue.
* *
* @return the capacity * @return the capacity
*/ */
size_t capacity() { size_t capacity() {
size_t c; size_t c;
mutex.lock(); mutex.lock();
c = max_size; c = max_size;
mutex.unlock(); mutex.unlock();
return c; return c;
} }
/** /**
* @brief Returns the number of additional elements that this queue can ideally (in the absence of memory or resource * @brief Returns the number of additional elements that this queue can ideally (in the absence of memory or resource
* constraints) accept. This is always equal to the initial capacity of this queue less the current size of this queue. * constraints) accept. This is always equal to the initial capacity of this queue less the current size of this queue.
* *
* @return the remaining capacity * @return the remaining capacity
*/ */
size_t remainingCapacity() { size_t remainingCapacity() {
mutex.lock(); mutex.lock();
size_t c = max_size - PIDeque<T>::size(); size_t c = max_size - PIDeque<T>::size();
mutex.unlock(); mutex.unlock();
return c; return c;
} }
/** /**
* @brief Returns the number of elements in this collection. * @brief Returns the number of elements in this collection.
*/ */
size_t size() { size_t size() {
mutex.lock(); mutex.lock();
size_t s = PIDeque<T>::size(); size_t s = PIDeque<T>::size();
mutex.unlock(); mutex.unlock();
return s; return s;
} }
/** /**
* @brief Removes all available elements from this queue and adds them to other given queue. * @brief Removes all available elements from this queue and adds them to other given queue.
*/ */
size_t drainTo(PIDeque<T>& other, size_t maxCount = SIZE_MAX) { size_t drainTo(PIDeque<T>& other, size_t maxCount = SIZE_MAX) {
mutex.lock(); mutex.lock();
size_t count = maxCount > PIDeque<T>::size() ? PIDeque<T>::size() : maxCount; size_t count = maxCount > PIDeque<T>::size() ? PIDeque<T>::size() : maxCount;
for (size_t i = 0; i < count; ++i) other.push_back(PIDeque<T>::take_front()); for (size_t i = 0; i < count; ++i) other.push_back(PIDeque<T>::take_front());
mutex.unlock(); mutex.unlock();
return count; return count;
} }
/** /**
* @brief Removes all available elements from this queue and adds them to other given queue. * @brief Removes all available elements from this queue and adds them to other given queue.
*/ */
size_t drainTo(PIBlockingDequeue<T>& other, size_t maxCount = SIZE_MAX) { size_t drainTo(PIBlockingDequeue<T>& other, size_t maxCount = SIZE_MAX) {
mutex.lock(); mutex.lock();
other.mutex.lock(); other.mutex.lock();
size_t count = maxCount > PIDeque<T>::size() ? PIDeque<T>::size() : maxCount; size_t count = maxCount > PIDeque<T>::size() ? PIDeque<T>::size() : maxCount;
size_t otherRemainingCapacity = other.max_size - static_cast<PIDeque<T> >(other).size(); size_t otherRemainingCapacity = other.max_size - static_cast<PIDeque<T> >(other).size();
if (count > otherRemainingCapacity) count = otherRemainingCapacity; if (count > otherRemainingCapacity) count = otherRemainingCapacity;
for (size_t i = 0; i < count; ++i) other.push_back(PIDeque<T>::take_front()); for (size_t i = 0; i < count; ++i) other.push_back(PIDeque<T>::take_front());
other.mutex.unlock(); other.mutex.unlock();
mutex.unlock(); mutex.unlock();
return count; return count;
} }
private: private:
PIConditionLock mutex; PIConditionLock mutex;
PIConditionVariable* cond_var_add; PIConditionVariable* cond_var_add;
PIConditionVariable* cond_var_rem; PIConditionVariable* cond_var_rem;
size_t max_size; size_t max_size;
}; };
#endif //PIP_TESTS_PIBLOCKINGDEQUEUE_H #endif //PIP_TESTS_PIBLOCKINGDEQUEUE_H

View File

@@ -1,51 +1,51 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Stephan Fomenko Stephan Fomenko
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef AWRCANFLASHER_PICONDITIONLOCK_H #ifndef AWRCANFLASHER_PICONDITIONLOCK_H
#define AWRCANFLASHER_PICONDITIONLOCK_H #define AWRCANFLASHER_PICONDITIONLOCK_H
#include "pimutex.h" #include "pimutex.h"
/** /**
* @brief Continued * @brief Continued
*/ */
class PIP_EXPORT PIConditionLock { class PIP_EXPORT PIConditionLock {
public: public:
explicit PIConditionLock(); explicit PIConditionLock();
~PIConditionLock(); ~PIConditionLock();
//! \brief lock //! \brief lock
void lock(); void lock();
//! \brief unlock //! \brief unlock
void unlock(); void unlock();
//! \brief tryLock //! \brief tryLock
bool tryLock(); bool tryLock();
void * handle(); void * handle();
private: private:
NO_COPY_CLASS(PIConditionLock) NO_COPY_CLASS(PIConditionLock)
PRIVATE_DECLARATION PRIVATE_DECLARATION
}; };
#endif //AWRCANFLASHER_PICONDITIONLOCK_H #endif //AWRCANFLASHER_PICONDITIONLOCK_H

View File

@@ -1,120 +1,120 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Stephan Fomenko Stephan Fomenko
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PIP_TESTS_PICONDITIONVAR_H #ifndef PIP_TESTS_PICONDITIONVAR_H
#define PIP_TESTS_PICONDITIONVAR_H #define PIP_TESTS_PICONDITIONVAR_H
#include "piconditionlock.h" #include "piconditionlock.h"
#include "pithread.h" #include "pithread.h"
#include "piinit.h" #include "piinit.h"
/** /**
* @brief A condition variable is an object able to block the calling thread until notified to resume. * @brief A condition variable is an object able to block the calling thread until notified to resume.
* *
* It uses a PIConditionLock to lock the thread when one of its wait functions is called. The thread remains * It uses a PIConditionLock to lock the thread when one of its wait functions is called. The thread remains
* blocked until woken up by another thread that calls a notification function on the same PIConditionVariable object. * blocked until woken up by another thread that calls a notification function on the same PIConditionVariable object.
*/ */
class PIP_EXPORT PIConditionVariable { class PIP_EXPORT PIConditionVariable {
public: public:
explicit PIConditionVariable(); explicit PIConditionVariable();
virtual ~PIConditionVariable(); virtual ~PIConditionVariable();
/** /**
* @brief Unblocks one of the threads currently waiting for this condition. If no threads are waiting, the function * @brief Unblocks one of the threads currently waiting for this condition. If no threads are waiting, the function
* does nothing. If more than one, it is unspecified which of the threads is selected. * does nothing. If more than one, it is unspecified which of the threads is selected.
*/ */
void notifyOne(); void notifyOne();
/** /**
* @brief Unblocks all threads currently waiting for this condition. If no threads are waiting, the function does * @brief Unblocks all threads currently waiting for this condition. If no threads are waiting, the function does
* nothing. * nothing.
*/ */
void notifyAll(); void notifyAll();
/** /**
* @brief see wait(PIConditionLock&, const std::function<bool()>&) * @brief see wait(PIConditionLock&, const std::function<bool()>&)
*/ */
virtual void wait(PIConditionLock& lk); virtual void wait(PIConditionLock& lk);
/** /**
* @brief Wait until notified * @brief Wait until notified
* *
* The execution of the current thread (which shall have locked with lk method PIConditionLock::lock()) is blocked * The execution of the current thread (which shall have locked with lk method PIConditionLock::lock()) is blocked
* until notified. * until notified.
* *
* At the moment of blocking the thread, the function automatically calls lk.unlock() (PIConditionLock::unlock()), * At the moment of blocking the thread, the function automatically calls lk.unlock() (PIConditionLock::unlock()),
* allowing other locked threads to continue. * allowing other locked threads to continue.
* *
* Once notified (explicitly, by some other thread), the function unblocks and calls lk.lock() (PIConditionLock::lock()), * Once notified (explicitly, by some other thread), the function unblocks and calls lk.lock() (PIConditionLock::lock()),
* leaving lk in the same state as when the function was called. Then the function returns (notice that this last mutex * leaving lk in the same state as when the function was called. Then the function returns (notice that this last mutex
* locking may block again the thread before returning). * locking may block again the thread before returning).
* *
* Generally, the function is notified to wake up by a call in another thread either to member notifyOne() or to * Generally, the function is notified to wake up by a call in another thread either to member notifyOne() or to
* member notifyAll(). But certain implementations may produce spurious wake-up calls without any of these functions * member notifyAll(). But certain implementations may produce spurious wake-up calls without any of these functions
* being called. Therefore, users of this function shall ensure their condition for resumption is met. * being called. Therefore, users of this function shall ensure their condition for resumption is met.
* *
* If condition is specified, the function only blocks if condition returns false, and notifications can only unblock * If condition is specified, the function only blocks if condition returns false, and notifications can only unblock
* the thread when it becomes true (which is specially useful to check against spurious wake-up calls). * the thread when it becomes true (which is specially useful to check against spurious wake-up calls).
* *
* @param lk lock object used by method wait for data protection * @param lk lock object used by method wait for data protection
* @param condition A callable object or function that takes no arguments and returns a value that can be evaluated * @param condition A callable object or function that takes no arguments and returns a value that can be evaluated
* as a bool. This is called repeatedly until it evaluates to true. * as a bool. This is called repeatedly until it evaluates to true.
*/ */
virtual void wait(PIConditionLock& lk, const std::function<bool()>& condition); virtual void wait(PIConditionLock& lk, const std::function<bool()>& condition);
/** /**
* @brief see waitFor(PIConditionLock&, int, const std::function<bool()>&) * @brief see waitFor(PIConditionLock&, int, const std::function<bool()>&)
*/ */
virtual bool waitFor(PIConditionLock& lk, int timeoutMs); virtual bool waitFor(PIConditionLock& lk, int timeoutMs);
/** /**
* @brief Wait for timeout or until notified * @brief Wait for timeout or until notified
* *
* The execution of the current thread (which shall have locked with lk method PIConditionLock::lock()) is blocked * The execution of the current thread (which shall have locked with lk method PIConditionLock::lock()) is blocked
* during timeoutMs, or until notified (if the latter happens first). * during timeoutMs, or until notified (if the latter happens first).
* *
* At the moment of blocking the thread, the function automatically calls lk.lock() (PIConditionLock::lock()), allowing * At the moment of blocking the thread, the function automatically calls lk.lock() (PIConditionLock::lock()), allowing
* other locked threads to continue. * other locked threads to continue.
* *
* Once notified or once timeoutMs has passed, the function unblocks and calls lk.unlock() (PIConditionLock::unlock()), * Once notified or once timeoutMs has passed, the function unblocks and calls lk.unlock() (PIConditionLock::unlock()),
* leaving lk in the same state as when the function was called. Then the function returns (notice that this last * leaving lk in the same state as when the function was called. Then the function returns (notice that this last
* mutex locking may block again the thread before returning). * mutex locking may block again the thread before returning).
* *
* Generally, the function is notified to wake up by a call in another thread either to member notifyOne() or to * Generally, the function is notified to wake up by a call in another thread either to member notifyOne() or to
* member notifyAll(). But certain implementations may produce spurious wake-up calls without any of these functions * member notifyAll(). But certain implementations may produce spurious wake-up calls without any of these functions
* being called. Therefore, users of this function shall ensure their condition for resumption is met. * being called. Therefore, users of this function shall ensure their condition for resumption is met.
* *
* If condition is specified, the function only blocks if condition returns false, and notifications can only unblock * If condition is specified, the function only blocks if condition returns false, and notifications can only unblock
* the thread when it becomes true (which is especially useful to check against spurious wake-up calls). * the thread when it becomes true (which is especially useful to check against spurious wake-up calls).
* *
* @param lk lock object used by method wait for data protection * @param lk lock object used by method wait for data protection
* @param condition A callable object or function that takes no arguments and returns a value that can be evaluated * @param condition A callable object or function that takes no arguments and returns a value that can be evaluated
* as a bool. This is called repeatedly until it evaluates to true. * as a bool. This is called repeatedly until it evaluates to true.
* @return false if timeout reached or true if wakeup condition is true * @return false if timeout reached or true if wakeup condition is true
*/ */
virtual bool waitFor(PIConditionLock& lk, int timeoutMs, const std::function<bool()>& condition); virtual bool waitFor(PIConditionLock& lk, int timeoutMs, const std::function<bool()>& condition);
private: private:
NO_COPY_CLASS(PIConditionVariable) NO_COPY_CLASS(PIConditionVariable)
PRIVATE_DECLARATION PRIVATE_DECLARATION
}; };
#endif //PIP_TESTS_PICONDITIONVAR_H #endif //PIP_TESTS_PICONDITIONVAR_H

View File

@@ -1,461 +1,461 @@
/*! \file piconsole.h /*! \file piconsole.h
* \brief Console output class * \brief Console output class
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Console output/input Console output/input
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PICONSOLE_H #ifndef PICONSOLE_H
#define PICONSOLE_H #define PICONSOLE_H
#include "pikbdlistener.h" #include "pikbdlistener.h"
class PIProtocol; class PIProtocol;
class PIDiagnostics; class PIDiagnostics;
class PISystemMonitor; class PISystemMonitor;
class PIPeer; class PIPeer;
class PITimer; class PITimer;
class PIP_EXPORT PIConsole: public PIThread class PIP_EXPORT PIConsole: public PIThread
{ {
PIOBJECT_SUBCLASS(PIConsole, PIThread) PIOBJECT_SUBCLASS(PIConsole, PIThread)
public: public:
//! Constructs %PIConsole with key handler "slot" and if "startNow" start it //! Constructs %PIConsole with key handler "slot" and if "startNow" start it
explicit PIConsole(bool startNow = true, PIKbdListener::KBFunc slot = 0); explicit PIConsole(bool startNow = true, PIKbdListener::KBFunc slot = 0);
~PIConsole(); ~PIConsole();
//! Variables output format //! Variables output format
enum Format { enum Format {
Normal /** Default console format */ = 0x01, Normal /** Default console format */ = 0x01,
Bold /** Bold text */ = 0x02, Bold /** Bold text */ = 0x02,
Faint = 0x04, Faint = 0x04,
Italic = 0x08, Italic = 0x08,
Underline /** Underlined text */ = 0x10, Underline /** Underlined text */ = 0x10,
Blink /** Blinked text */ = 0x20, Blink /** Blinked text */ = 0x20,
Inverse /** Swap text and background colors */ = 0x40, Inverse /** Swap text and background colors */ = 0x40,
Black /** Black text */ = 0x100, Black /** Black text */ = 0x100,
Red /** Red text */ = 0x200, Red /** Red text */ = 0x200,
Green /** Green text */ = 0x400, Green /** Green text */ = 0x400,
Yellow /** Yellow text */ = 0x800, Yellow /** Yellow text */ = 0x800,
Blue /** Blue text */ = 0x1000, Blue /** Blue text */ = 0x1000,
Magenta /** Magenta text */ = 0x2000, Magenta /** Magenta text */ = 0x2000,
Cyan /** Cyan text */ = 0x4000, Cyan /** Cyan text */ = 0x4000,
White /** White text */ = 0x8000, White /** White text */ = 0x8000,
BackBlack /** Black background */ = 0x10000, BackBlack /** Black background */ = 0x10000,
BackRed /** Red background */ = 0x20000, BackRed /** Red background */ = 0x20000,
BackGreen /** Green background */ = 0x40000, BackGreen /** Green background */ = 0x40000,
BackYellow /** Yellow background */ = 0x80000, BackYellow /** Yellow background */ = 0x80000,
BackBlue /** Blue background */ = 0x100000, BackBlue /** Blue background */ = 0x100000,
BackMagenta /** Magenta background */ = 0x200000, BackMagenta /** Magenta background */ = 0x200000,
BackCyan /** Cyan background */ = 0x400000, BackCyan /** Cyan background */ = 0x400000,
BackWhite /** White background */ = 0x800000, BackWhite /** White background */ = 0x800000,
Dec /** Decimal base for integers */ = 0x1000000, Dec /** Decimal base for integers */ = 0x1000000,
Hex /** Hexadecimal base for integers */ = 0x2000000, Hex /** Hexadecimal base for integers */ = 0x2000000,
Oct /** Octal base for integers */ = 0x4000000, Oct /** Octal base for integers */ = 0x4000000,
Bin /** Binary base for integers */ = 0x8000000, Bin /** Binary base for integers */ = 0x8000000,
Scientific /** Scientific representation of floats */ = 0x10000000, Scientific /** Scientific representation of floats */ = 0x10000000,
SystemTimeSplit /** PISystemTime split representation (* s, * ns) */ = 0x20000000, SystemTimeSplit /** PISystemTime split representation (* s, * ns) */ = 0x20000000,
SystemTimeSeconds /** PISystemTime seconds representation (*.* s) */ = 0x40000000 SystemTimeSeconds /** PISystemTime seconds representation (*.* s) */ = 0x40000000
}; };
//! Column labels alignment //! Column labels alignment
enum Alignment { enum Alignment {
Nothing /** No alignment */ , Nothing /** No alignment */ ,
Left /** Labels align left and variables align left */ , Left /** Labels align left and variables align left */ ,
Right /** Labels align right and variables align left */ Right /** Labels align right and variables align left */
}; };
typedef PIFlags<PIConsole::Format> FormatFlags; typedef PIFlags<PIConsole::Format> FormatFlags;
//! Add to current tab to column "column" string "name" with format "format" //! Add to current tab to column "column" string "name" with format "format"
void addString(const PIString & name, int column = 1, FormatFlags format = PIConsole::Normal); 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" //! 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); 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" //! 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); 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" //! 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); 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" //! 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); 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" //! 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); 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" //! 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); 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" //! 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); 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" //! 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); 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" //! 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); 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" //! 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); 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" //! 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); 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" //! 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); 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" //! 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); 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" //! 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); 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" //! 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 PISystemTime * 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 PIDiagnostics * ptr, int column = 1, FormatFlags format = PIConsole::Normal);
void addVariable(const PIString & name, const PISystemMonitor * 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" //! 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); 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 //! Add to current tab to column "column" "count" empty lines
void addEmptyLine(int column = 1, uint count = 1); void addEmptyLine(int column = 1, uint count = 1);
PIString getString(int x, int y); PIString getString(int x, int y);
short getShort(int x, int y) {return getString(x, y).toShort();} short getShort(int x, int y) {return getString(x, y).toShort();}
int getInt(int x, int y) {return getString(x, y).toInt();} int getInt(int x, int y) {return getString(x, y).toInt();}
float getFloat(int x, int y) {return getString(x, y).toFloat();} float getFloat(int x, int y) {return getString(x, y).toFloat();}
double getDouble(int x, int y) {return getString(x, y).toDouble();} double getDouble(int x, int y) {return getString(x, y).toDouble();}
PIString getString(const PIString & name); PIString getString(const PIString & name);
short getShort(const PIString & name) {return getString(name).toShort();} short getShort(const PIString & name) {return getString(name).toShort();}
int getInt(const PIString & name) {return getString(name).toInt();} int getInt(const PIString & name) {return getString(name).toInt();}
float getFloat(const PIString & name) {return getString(name).toFloat();} float getFloat(const PIString & name) {return getString(name).toFloat();}
double getDouble(const PIString & name) {return getString(name).toDouble();} double getDouble(const PIString & name) {return getString(name).toDouble();}
//! Returns tabs count //! Returns tabs count
uint tabsCount() const {return tabs.size();} uint tabsCount() const {return tabs.size();}
//! Returns current tab name //! Returns current tab name
PIString currentTab() const {return tabs[cur_tab].name;} PIString currentTab() const {return tabs[cur_tab].name;}
//! Returns current tab index //! Returns current tab index
int currentTabIndex() const {return cur_tab;} int currentTabIndex() const {return cur_tab;}
//! Add new tab with name "name", bind key "bind_key" and returns this tab index //! Add new tab with name "name", bind key "bind_key" and returns this tab index
int addTab(const PIString & name, char bind_key = 0); int addTab(const PIString & name, char bind_key = 0);
//! Remove tab with index "index" //! Remove tab with index "index"
void removeTab(uint index); void removeTab(uint index);
//! Remove tab with name "name" //! Remove tab with name "name"
void removeTab(const PIString & name); void removeTab(const PIString & name);
//! Clear content of tab with index "index" //! Clear content of tab with index "index"
void clearTab(uint index); void clearTab(uint index);
//! Clear content of tab with name "name" //! Clear content of tab with name "name"
void clearTab(const PIString & name); void clearTab(const PIString & name);
//! Set current tab to tab with index "index", returns if tab exists //! Set current tab to tab with index "index", returns if tab exists
bool setTab(uint index); bool setTab(uint index);
//! Set current tab to tab with name "name", returns if tab exists //! Set current tab to tab with name "name", returns if tab exists
bool setTab(const PIString & name); bool setTab(const PIString & name);
//! Set tab with index "index" bind key to "bind_key", returns if tab exists //! Set tab with index "index" bind key to "bind_key", returns if tab exists
bool setTabBindKey(uint index, char bind_key); bool setTabBindKey(uint index, char bind_key);
//! Set tab with name "name" bind key to "bind_key", returns if tab exists //! Set tab with name "name" bind key to "bind_key", returns if tab exists
bool setTabBindKey(const PIString & name, char bind_key); bool setTabBindKey(const PIString & name, char bind_key);
//! Remove all tabs and if "clearScreen" clear the screen //! Remove all tabs and if "clearScreen" clear the screen
void clearTabs(bool clearScreen = true) {if (clearScreen && isRunning()) {toUpperLeft(); clearScreenLower();} tabs.clear();} void clearTabs(bool clearScreen = true) {if (clearScreen && isRunning()) {toUpperLeft(); clearScreenLower();} tabs.clear();}
//! Set custom status text of current tab to "str" //! Set custom status text of current tab to "str"
void addCustomStatus(const PIString & str) {tabs[cur_tab].status = str;} void addCustomStatus(const PIString & str) {tabs[cur_tab].status = str;}
//! Clear custom status text of current tab //! Clear custom status text of current tab
void clearCustomStatus() {tabs[cur_tab].status.clear();} void clearCustomStatus() {tabs[cur_tab].status.clear();}
//! Returns default alignment //! Returns default alignment
Alignment defaultAlignment() const {return def_align;} Alignment defaultAlignment() const {return def_align;}
//! Set default alignment to "align" //! Set default alignment to "align"
void setDefaultAlignment(Alignment align) {def_align = align;} void setDefaultAlignment(Alignment align) {def_align = align;}
//! Set column "col" alignment to "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;} 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" //! 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();} void setColumnAlignmentToAll(Alignment align) {piForeach (Tab & i, tabs) piForeach (Column & j, i.columns) j.alignment = align; fillLabels();}
//! Directly call function from \a PIKbdListener //! Directly call function from \a PIKbdListener
void enableExitCapture(char key = 'Q') {listener->enableExitCapture(key);} void enableExitCapture(char key = 'Q') {listener->enableExitCapture(key);}
//! Directly call function from \a PIKbdListener //! Directly call function from \a PIKbdListener
void disableExitCapture() {listener->disableExitCapture();} void disableExitCapture() {listener->disableExitCapture();}
//! Directly call function from \a PIKbdListener //! Directly call function from \a PIKbdListener
bool exitCaptured() const {return listener->exitCaptured();} bool exitCaptured() const {return listener->exitCaptured();}
//! Directly call function from \a PIKbdListener //! Directly call function from \a PIKbdListener
char exitKey() const {return listener->exitKey();} char exitKey() const {return listener->exitKey();}
int windowWidth() const {return width;} int windowWidth() const {return width;}
int windowHeight() const {return height;} int windowHeight() const {return height;}
PIString fstr(FormatFlags f); PIString fstr(FormatFlags f);
void update(); void update();
void pause(bool yes) {pause_ = yes;} void pause(bool yes) {pause_ = yes;}
// Server functions // Server functions
void startServer(const PIString & name); void startServer(const PIString & name);
void stopPeer(); void stopPeer();
bool isServerStarted() const {return peer != 0;} bool isServerStarted() const {return peer != 0;}
PIStringList clients() const; PIStringList clients() const;
// Client functions // Client functions
void listenServers(); void listenServers();
PIStringList availableServers() const; PIStringList availableServers() const;
PIString selectedServer() const {return server_name;} PIString selectedServer() const {return server_name;}
void connectToServer(const PIString & name); void connectToServer(const PIString & name);
void disconnect(); void disconnect();
bool isConnected() const {return state == Connected;} bool isConnected() const {return state == Connected;}
void toUpperLeft(); void toUpperLeft();
void moveRight(int n = 1); void moveRight(int n = 1);
void moveLeft(int n = 1); void moveLeft(int n = 1);
void moveTo(int x = 0, int y = 0); void moveTo(int x = 0, int y = 0);
void clearScreen(); void clearScreen();
void clearScreenLower(); void clearScreenLower();
void clearLine(); void clearLine();
void newLine(); void newLine();
void hideCursor(); void hideCursor();
void showCursor(); void showCursor();
EVENT_HANDLER0(void, clearVariables) {clearVariables(true);} EVENT_HANDLER0(void, clearVariables) {clearVariables(true);}
EVENT_HANDLER1(void, clearVariables, bool, clearScreen); EVENT_HANDLER1(void, clearVariables, bool, clearScreen);
EVENT_HANDLER0(void, waitForFinish) {WAIT_FOR_EXIT} EVENT_HANDLER0(void, waitForFinish) {WAIT_FOR_EXIT}
EVENT_HANDLER0(void, start) {start(false);} EVENT_HANDLER0(void, start) {start(false);}
EVENT_HANDLER1(void, start, bool, wait) {PIThread::start(40); if (wait) waitForFinish();} EVENT_HANDLER1(void, start, bool, wait) {PIThread::start(40); if (wait) waitForFinish();}
EVENT_HANDLER0(void, stop) {stop(false);} EVENT_HANDLER0(void, stop) {stop(false);}
EVENT_HANDLER1(void, stop, bool, clear); EVENT_HANDLER1(void, stop, bool, clear);
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void * , data) EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void * , data)
//! \handlers //! \handlers
//! \{ //! \{
//! \fn void waitForFinish() //! \fn void waitForFinish()
//! \brief block until finished (exit key will be pressed) //! \brief block until finished (exit key will be pressed)
//! \fn void clearVariables(bool clearScreen = true) //! \fn void clearVariables(bool clearScreen = true)
//! \brief Remove all columns at current tab and if "clearScreen" clear the screen //! \brief Remove all columns at current tab and if "clearScreen" clear the screen
//! \fn void start(bool wait = false) //! \fn void start(bool wait = false)
//! \brief Start console output and if "wait" block until finished (exit key will be pressed) //! \brief Start console output and if "wait" block until finished (exit key will be pressed)
//! \fn void stop(bool clear = false) //! \fn void stop(bool clear = false)
//! \brief Stop console output and if "clear" clear the screen //! \brief Stop console output and if "clear" clear the screen
//! \} //! \}
//! \events //! \events
//! \{ //! \{
//! \fn void keyPressed(PIKbdListener::KeyEvent key, void * data) //! \fn void keyPressed(PIKbdListener::KeyEvent key, void * data)
//! \brief Raise on key "key" pressed, "data" is pointer to %PIConsole object //! \brief Raise on key "key" pressed, "data" is pointer to %PIConsole object
//! \} //! \}
private: private:
void begin(); void begin();
void run(); void run();
void fillLabels(); void fillLabels();
void status(); void status();
void checkColumn(uint col) {while (columns().size() < col) columns().push_back(Column(def_align));} void checkColumn(uint col) {while (columns().size() < col) columns().push_back(Column(def_align));}
int bitsValue(const void * src, int offset, int count) const; int bitsValue(const void * src, int offset, int count) const;
const char * toBin(const void * d, int s); const char * toBin(const void * d, int s);
inline void printLine(const PIString & str, int dx = 0, FormatFlags format = PIConsole::Normal); 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 PIString & str, FormatFlags format = PIConsole::Normal);
inline int printValue(const char * 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 bool value, FormatFlags format = PIConsole::Normal);
inline int printValue(const int 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 long value, FormatFlags format = PIConsole::Normal);
inline int printValue(const llong 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 float value, FormatFlags format = PIConsole::Normal);
inline int printValue(const double 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 char value, FormatFlags format = PIConsole::Normal);
inline int printValue(const short 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 uchar value, FormatFlags format = PIConsole::Normal);
inline int printValue(const ushort 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 uint value, FormatFlags format = PIConsole::Normal);
inline int printValue(const ulong 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 ullong value, FormatFlags format = PIConsole::Normal);
inline int printValue(const PISystemTime & value, FormatFlags format = PIConsole::Normal); inline int printValue(const PISystemTime & value, FormatFlags format = PIConsole::Normal);
static void key_event(PIKbdListener::KeyEvent key, void * t); static void key_event(PIKbdListener::KeyEvent key, void * t);
struct Variable { struct Variable {
Variable() {nx = ny = type = offset = bitFrom = bitCount = size = 0; format = Normal; remote = false; ptr = 0; id = 1;} Variable() {nx = ny = type = offset = bitFrom = bitCount = size = 0; format = Normal; remote = false; ptr = 0; id = 1;}
Variable(const Variable & src) {remote = src.remote; name = src.name; format = src.format; type = src.type; offset = src.offset; size = src.size; Variable(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;} bitFrom = src.bitFrom; bitCount = src.bitCount; ptr = src.ptr; nx = src.nx; ny = src.ny; rdata = src.rdata; id = src.id;}
bool isEmpty() const {return (remote ? false : ptr == 0);} bool isEmpty() const {return (remote ? false : ptr == 0);}
const void * data() {return (remote ? rdata.data() : ptr);} const void * data() {return (remote ? rdata.data() : ptr);}
void writeData(PIByteArray & ba) { void writeData(PIByteArray & ba) {
if (remote) ba << rdata; if (remote) ba << rdata;
else { else {
if (type == 0) ba << (*(PIString * )ptr); if (type == 0) ba << (*(PIString * )ptr);
else ba << PIByteArray::RawData(ptr, size); else ba << PIByteArray::RawData(ptr, size);
} }
} }
PIString name; PIString name;
FormatFlags format; FormatFlags format;
int nx; int nx;
int ny; int ny;
int type; int type;
int offset; int offset;
int bitFrom; int bitFrom;
int bitCount; int bitCount;
int size; int size;
int id; int id;
bool remote; bool remote;
const void * ptr; const void * ptr;
PIByteArray rdata; 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; 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;} bitFrom = src.bitFrom; bitCount = src.bitCount; ptr = src.ptr; nx = src.nx; ny = src.ny; rdata = src.rdata; id = src.id;}
}; };
struct VariableContent { struct VariableContent {
int id; int id;
PIByteArray rdata; PIByteArray rdata;
}; };
struct Column { struct Column {
Column(Alignment align = PIConsole::Right) {variables.reserve(32); alignment = align;} Column(Alignment align = PIConsole::Right) {variables.reserve(32); alignment = align;}
PIVector<Variable> variables; PIVector<Variable> variables;
Alignment alignment; Alignment alignment;
uint size() const {return variables.size();} uint size() const {return variables.size();}
Variable & operator [](int index) {return variables[index];} Variable & operator [](int index) {return variables[index];}
const Variable & operator [](int index) const {return variables[index];} const Variable & operator [](int index) const {return variables[index];}
void push_back(const Variable & v) {variables.push_back(v);} void push_back(const Variable & v) {variables.push_back(v);}
void operator =(const Column & src) {variables = src.variables; alignment = src.alignment;} void operator =(const Column & src) {variables = src.variables; alignment = src.alignment;}
}; };
struct Tab { struct Tab {
Tab(PIString n = "", char k = 0) {columns.reserve(8); name = n; key = k;} Tab(PIString n = "", char k = 0) {columns.reserve(8); name = n; key = k;}
PIVector<Column> columns; PIVector<Column> columns;
PIString name; PIString name;
PIString status; PIString status;
char key; char key;
}; };
enum ConnectedState {Disconnected, FetchingData, Committing, Connected}; enum ConnectedState {Disconnected, FetchingData, Committing, Connected};
friend PIByteArray & operator <<(PIByteArray & ba, const PIConsole::VariableContent & v); friend PIByteArray & operator <<(PIByteArray & ba, const PIConsole::VariableContent & v);
friend PIByteArray & operator >>(PIByteArray & ba, 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, const PIConsole::Variable & v);
friend PIByteArray & operator >>(PIByteArray & ba, 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, const PIConsole::Column & v);
friend PIByteArray & operator >>(PIByteArray & ba, 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, const PIConsole::Tab & v);
friend PIByteArray & operator >>(PIByteArray & ba, PIConsole::Tab & v); friend PIByteArray & operator >>(PIByteArray & ba, PIConsole::Tab & v);
PIVector<Column> & columns() {return tabs[cur_tab].columns;} PIVector<Column> & columns() {return tabs[cur_tab].columns;}
Column & column(int index) {return tabs[cur_tab].columns[index - 1];} Column & column(int index) {return tabs[cur_tab].columns[index - 1];}
int couts(const PIString & v); int couts(const PIString & v);
int couts(const char * v); int couts(const char * v);
int couts(const bool v); int couts(const bool v);
int couts(const char v); int couts(const char v);
int couts(const short v); int couts(const short v);
int couts(const int v); int couts(const int v);
int couts(const long v); int couts(const long v);
int couts(const llong v); int couts(const llong v);
int couts(const uchar v); int couts(const uchar v);
int couts(const ushort v); int couts(const ushort v);
int couts(const uint v); int couts(const uint v);
int couts(const ulong v); int couts(const ulong v);
int couts(const ullong v); int couts(const ullong v);
int couts(const float v); int couts(const float v);
int couts(const double v); int couts(const double v);
int couts(const PISystemTime & v); int couts(const PISystemTime & v);
struct RemoteClient; struct RemoteClient;
void serverSendInfo(); void serverSendInfo();
void serverSendData(); void serverSendData();
RemoteClient & remoteClient(const PIString & fname); RemoteClient & remoteClient(const PIString & fname);
EVENT_HANDLER2(void, peerReceived, const PIString &, from, const PIByteArray &, data); EVENT_HANDLER2(void, peerReceived, const PIString &, from, const PIByteArray &, data);
EVENT_HANDLER2(void, peerTimer, void * , data, int, delim); EVENT_HANDLER2(void, peerTimer, void * , data, int, delim);
EVENT_HANDLER1(void, peerDisconnectedEvent, const PIString &, name); EVENT_HANDLER1(void, peerDisconnectedEvent, const PIString &, name);
PRIVATE_DECLARATION PRIVATE_DECLARATION
PIVector<Tab> tabs; PIVector<Tab> tabs;
PIString binstr, rstr; PIString binstr, rstr;
PIByteArray rba; PIByteArray rba;
Variable tv; Variable tv;
PIKbdListener * listener; PIKbdListener * listener;
Alignment def_align; Alignment def_align;
PIKbdListener::KBFunc ret_func; PIKbdListener::KBFunc ret_func;
int width, height, pwidth, pheight, col_wid, num_format, systime_format; int width, height, pwidth, pheight, col_wid, num_format, systime_format;
uint max_y; uint max_y;
int vid; int vid;
uint cur_tab, col_cnt; uint cur_tab, col_cnt;
PIPeer * peer; PIPeer * peer;
PITimer * peer_timer; PITimer * peer_timer;
PITimeMeasurer peer_tm; PITimeMeasurer peer_tm;
PIString server_name; PIString server_name;
bool server_mode, pause_; bool server_mode, pause_;
ConnectedState state; ConnectedState state;
struct RemoteClient { struct RemoteClient {
RemoteClient(const PIString & n = "") {name = n; state = Disconnected;} RemoteClient(const PIString & n = "") {name = n; state = Disconnected;}
PIString name; PIString name;
ConnectedState state; ConnectedState state;
}; };
PIVector<RemoteClient> remote_clients; PIVector<RemoteClient> remote_clients;
}; };
inline PIByteArray & operator <<(PIByteArray & ba, const PIConsole::VariableContent & v) {ba << v.id << v.rdata; return ba;} 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, 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, 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, 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, const PIConsole::Column & v) {ba << (int)v.alignment << v.variables; return ba;}
inline PIByteArray & operator >>(PIByteArray & ba, PIConsole::Column & v) {int a; ba >> a >> v.variables; v.alignment = (PIConsole::Alignment)a; return ba;} inline PIByteArray & operator >>(PIByteArray & ba, PIConsole::Column & v) {int a; ba >> a >> v.variables; v.alignment = (PIConsole::Alignment)a; 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, 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;} inline PIByteArray & operator >>(PIByteArray & ba, PIConsole::Tab & v) {ba >> v.name >> v.status >> (uchar&)v.key >> v.columns; return ba;}
#endif // PICONSOLE_H #endif // PICONSOLE_H

View File

@@ -1,159 +1,159 @@
/*! \file piscreen.h /*! \file piscreen.h
* \brief Console GUI class * \brief Console GUI class
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Console GUI Console GUI
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PISCREEN_H #ifndef PISCREEN_H
#define PISCREEN_H #define PISCREEN_H
#include "piscreentile.h" #include "piscreentile.h"
#include "piscreendrawer.h" #include "piscreendrawer.h"
class PIP_EXPORT PIScreen: public PIThread, public PIScreenTypes::PIScreenBase class PIP_EXPORT PIScreen: public PIThread, public PIScreenTypes::PIScreenBase
{ {
PIOBJECT_SUBCLASS(PIScreen, PIThread) PIOBJECT_SUBCLASS(PIScreen, PIThread)
class SystemConsole; class SystemConsole;
public: public:
//! Constructs %PIScreen with key handler "slot" and if "startNow" start it //! Constructs %PIScreen with key handler "slot" and if "startNow" start it
PIScreen(bool startNow = true, PIKbdListener::KBFunc slot = 0); PIScreen(bool startNow = true, PIKbdListener::KBFunc slot = 0);
~PIScreen(); ~PIScreen();
//! Directly call function from \a PIKbdListener //! Directly call function from \a PIKbdListener
void enableExitCapture(int key = 'Q') {listener->enableExitCapture(key);} void enableExitCapture(int key = 'Q') {listener->enableExitCapture(key);}
//! Directly call function from \a PIKbdListener //! Directly call function from \a PIKbdListener
void disableExitCapture() {listener->disableExitCapture();} void disableExitCapture() {listener->disableExitCapture();}
//! Directly call function from \a PIKbdListener //! Directly call function from \a PIKbdListener
bool exitCaptured() const {return listener->exitCaptured();} bool exitCaptured() const {return listener->exitCaptured();}
//! Directly call function from \a PIKbdListener //! Directly call function from \a PIKbdListener
int exitKey() const {return listener->exitKey();} int exitKey() const {return listener->exitKey();}
int windowWidth() const {return console.width;} int windowWidth() const {return console.width;}
int windowHeight() const {return console.height;} int windowHeight() const {return console.height;}
bool isMouseEnabled() const {return mouse_;} bool isMouseEnabled() const {return mouse_;}
void setMouseEnabled(bool on); void setMouseEnabled(bool on);
PIScreenTile * rootTile() {return &root;} PIScreenTile * rootTile() {return &root;}
PIScreenTile * tileByName(const PIString & name); PIScreenTile * tileByName(const PIString & name);
void setDialogTile(PIScreenTile * t); void setDialogTile(PIScreenTile * t);
PIScreenTile * dialogTile() const {return tile_dialog;} PIScreenTile * dialogTile() const {return tile_dialog;}
PIScreenDrawer * drawer() {return &drawer_;} PIScreenDrawer * drawer() {return &drawer_;}
void clear() {drawer_.clear();} void clear() {drawer_.clear();}
void resize(int w, int h) {console.resize(w, h);} void resize(int w, int h) {console.resize(w, h);}
EVENT_HANDLER0(void, waitForFinish); EVENT_HANDLER0(void, waitForFinish);
EVENT_HANDLER0(void, start) {start(false);} EVENT_HANDLER0(void, start) {start(false);}
EVENT_HANDLER1(void, start, bool, wait) {PIThread::start(40); if (wait) waitForFinish();} EVENT_HANDLER1(void, start, bool, wait) {PIThread::start(40); if (wait) waitForFinish();}
EVENT_HANDLER0(void, stop) {stop(false);} EVENT_HANDLER0(void, stop) {stop(false);}
EVENT_HANDLER1(void, stop, bool, clear); EVENT_HANDLER1(void, stop, bool, clear);
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void * , data) EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void * , data)
EVENT2(tileEvent, PIScreenTile * , tile, PIScreenTypes::TileEvent, e) EVENT2(tileEvent, PIScreenTile * , tile, PIScreenTypes::TileEvent, e)
//! \handlers //! \handlers
//! \{ //! \{
//! \fn void waitForFinish() //! \fn void waitForFinish()
//! \brief block until finished (exit key will be pressed) //! \brief block until finished (exit key will be pressed)
//! \fn void start(bool wait = false) //! \fn void start(bool wait = false)
//! \brief Start console output and if "wait" block until finished (exit key will be pressed) //! \brief Start console output and if "wait" block until finished (exit key will be pressed)
//! \fn void stop(bool clear = false) //! \fn void stop(bool clear = false)
//! \brief Stop console output and if "clear" clear the screen //! \brief Stop console output and if "clear" clear the screen
//! \} //! \}
//! \events //! \events
//! \{ //! \{
//! \fn void keyPressed(PIKbdListener::KeyEvent key, void * data) //! \fn void keyPressed(PIKbdListener::KeyEvent key, void * data)
//! \brief Raise on key "key" pressed, "data" is pointer to %PIConsole object //! \brief Raise on key "key" pressed, "data" is pointer to %PIConsole object
//! \fn void tileEvent(PIScreenTile * tile, PIScreenTypes::TileEvent e) //! \fn void tileEvent(PIScreenTile * tile, PIScreenTypes::TileEvent e)
//! \brief Raise on some event "e" from tile "tile" //! \brief Raise on some event "e" from tile "tile"
//! \} //! \}
private: private:
class SystemConsole { class SystemConsole {
public: public:
SystemConsole(); SystemConsole();
~SystemConsole(); ~SystemConsole();
void begin(); void begin();
void end(); void end();
void prepare(); void prepare();
void clear(); void clear();
void print(); void print();
void resize(int w, int h); void resize(int w, int h);
void toUpperLeft(); void toUpperLeft();
void moveTo(int x = 0, int y = 0); void moveTo(int x = 0, int y = 0);
void hideCursor(); void hideCursor();
void showCursor(); void showCursor();
void clearScreen(); void clearScreen();
void clearScreenLower(); void clearScreenLower();
#ifdef WINDOWS #ifdef WINDOWS
void getWinCurCoord(); void getWinCurCoord();
void clearLine(); void clearLine();
void newLine(); void newLine();
ushort attributes(const PIScreenTypes::Cell & c); ushort attributes(const PIScreenTypes::Cell & c);
#else #else
PIString formatString(const PIScreenTypes::Cell & c); PIString formatString(const PIScreenTypes::Cell & c);
#endif #endif
PRIVATE_DECLARATION PRIVATE_DECLARATION
int width, height, pwidth, pheight; int width, height, pwidth, pheight;
int mouse_x, mouse_y; int mouse_x, mouse_y;
PIVector<PIVector<PIScreenTypes::Cell> > cells, pcells; PIVector<PIVector<PIScreenTypes::Cell> > cells, pcells;
}; };
void begin(); void begin();
void run(); void run();
void end(); void end();
void key_event(PIKbdListener::KeyEvent key); void key_event(PIKbdListener::KeyEvent key);
EVENT_HANDLER1(void, mouse_event, PIKbdListener::MouseEvent, me); EVENT_HANDLER1(void, mouse_event, PIKbdListener::MouseEvent, me);
EVENT_HANDLER1(void, wheel_event, PIKbdListener::WheelEvent, we); EVENT_HANDLER1(void, wheel_event, PIKbdListener::WheelEvent, we);
static void key_eventS(PIKbdListener::KeyEvent key, void * t) {((PIScreen*)t)->key_event(key);} static void key_eventS(PIKbdListener::KeyEvent key, void * t) {((PIScreen*)t)->key_event(key);}
PIVector<PIScreenTile*> tiles() {return root.children();} PIVector<PIScreenTile*> tiles() {return root.children();}
PIVector<PIScreenTile*> prepareMouse(PIKbdListener::MouseEvent * e); PIVector<PIScreenTile*> prepareMouse(PIKbdListener::MouseEvent * e);
PIVector<PIScreenTile*> tilesUnderMouse(int x, int y); PIVector<PIScreenTile*> tilesUnderMouse(int x, int y);
bool nextFocus(PIScreenTile * rt, PIKbdListener::KeyEvent key = PIKbdListener::KeyEvent()); bool nextFocus(PIScreenTile * rt, PIKbdListener::KeyEvent key = PIKbdListener::KeyEvent());
void tileEventInternal(PIScreenTile * t, PIScreenTypes::TileEvent e); void tileEventInternal(PIScreenTile * t, PIScreenTypes::TileEvent e);
void tileRemovedInternal(PIScreenTile * t); void tileRemovedInternal(PIScreenTile * t);
void tileSetFocusInternal(PIScreenTile * t); void tileSetFocusInternal(PIScreenTile * t);
bool mouse_; bool mouse_;
SystemConsole console; SystemConsole console;
PIScreenDrawer drawer_; PIScreenDrawer drawer_;
PIKbdListener * listener; PIKbdListener * listener;
PIKbdListener::KBFunc ret_func; PIKbdListener::KBFunc ret_func;
PIScreenTile root; PIScreenTile root;
PIScreenTile * tile_focus, * tile_dialog; PIScreenTile * tile_focus, * tile_dialog;
}; };
#endif // PISCREEN_H #endif // PISCREEN_H

View File

@@ -1,77 +1,77 @@
/*! \file piscreenconsole.h /*! \file piscreenconsole.h
* \brief Tile for PIScreen with PIConsole API * \brief Tile for PIScreen with PIConsole API
* *
* This file declares TileVars * This file declares TileVars
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Tile for PIScreen with PIConsole API Tile for PIScreen with PIConsole API
Andrey Bychkov work.a.b@yandex.ru Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PISCREENCONSOLE_H #ifndef PISCREENCONSOLE_H
#define PISCREENCONSOLE_H #define PISCREENCONSOLE_H
#include "piscreentiles.h" #include "piscreentiles.h"
/// NOTE: incomplete class /// NOTE: incomplete class
/// TODO: write TileVars /// TODO: write TileVars
class PIP_EXPORT TileVars: public PIScreenTile { class PIP_EXPORT TileVars: public PIScreenTile {
public: public:
TileVars(const PIString & n = PIString()); TileVars(const PIString & n = PIString());
protected: protected:
struct Variable { struct Variable {
Variable() {nx = ny = type = offset = bitFrom = bitCount = size = 0; format = PIScreenTypes::CellFormat(); ptr = 0;} Variable() {nx = ny = type = offset = bitFrom = bitCount = size = 0; format = PIScreenTypes::CellFormat(); ptr = 0;}
bool isEmpty() const {return (ptr == 0);} bool isEmpty() const {return (ptr == 0);}
PIString name; PIString name;
PIScreenTypes::CellFormat format; PIScreenTypes::CellFormat format;
int nx; int nx;
int ny; int ny;
int type; int type;
int offset; int offset;
int bitFrom; int bitFrom;
int bitCount; int bitCount;
int size; int size;
const void * ptr; const void * ptr;
/*void operator =(const Variable & src) { /*void operator =(const Variable & src) {
name = src.name; name = src.name;
format = src.format; format = src.format;
nx = src.nx; nx = src.nx;
ny = src.ny; ny = src.ny;
type = src.type; type = src.type;
offset = src.offset; offset = src.offset;
bitFrom = src.bitFrom; bitFrom = src.bitFrom;
bitCount = src.bitCount; bitCount = src.bitCount;
size = src.size; size = src.size;
ptr = src.ptr; ptr = src.ptr;
}*/ }*/
}; };
PIVector<Variable> variables; PIVector<Variable> variables;
PIScreenTypes::Alignment alignment; PIScreenTypes::Alignment alignment;
void sizeHint(int & w, int & h) const; void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d); void drawEvent(PIScreenDrawer * d);
}; };
class PIP_EXPORT PIScreenConsoleTile : public PIScreenTile class PIP_EXPORT PIScreenConsoleTile : public PIScreenTile
{ {
public: public:
PIScreenConsoleTile(); PIScreenConsoleTile();
}; };
#endif // PISCREENCONSOLE_H #endif // PISCREENCONSOLE_H

View File

@@ -1,68 +1,68 @@
/*! \file piscreendrawer.h /*! \file piscreendrawer.h
* \brief Drawer for PIScreen * \brief Drawer for PIScreen
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Drawer for PIScreen Drawer for PIScreen
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PISCREENDRAWER_H #ifndef PISCREENDRAWER_H
#define PISCREENDRAWER_H #define PISCREENDRAWER_H
#include "piscreentypes.h" #include "piscreentypes.h"
#include "pistring.h" #include "pistring.h"
class PIP_EXPORT PIScreenDrawer class PIP_EXPORT PIScreenDrawer
{ {
friend class PIScreen; friend class PIScreen;
PIScreenDrawer(PIVector<PIVector<PIScreenTypes::Cell> > & c); PIScreenDrawer(PIVector<PIVector<PIScreenTypes::Cell> > & c);
public: public:
enum ArtChar { enum ArtChar {
LineVertical = 1, LineVertical = 1,
LineHorizontal, LineHorizontal,
Cross, Cross,
CornerTopLeft, CornerTopLeft,
CornerTopRight, CornerTopRight,
CornerBottomLeft, CornerBottomLeft,
CornerBottomRight, CornerBottomRight,
Unchecked, Unchecked,
Checked Checked
}; };
void clear(); void clear();
void clearRect(int x0, int y0, int x1, int y1) {fillRect(x0, y0, x1, y1, ' ');} void clearRect(int x0, int y0, int x1, int y1) {fillRect(x0, y0, x1, y1, ' ');}
void drawPixel(int x, int y, const PIChar & c, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0); void drawPixel(int x, int y, const PIChar & c, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0);
void drawLine(int x0, int y0, int x1, int y1, const PIChar & c, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0); void drawLine(int x0, int y0, int x1, int y1, const PIChar & c, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0);
void drawRect(int x0, int y0, int x1, int y1, const PIChar & c, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0); void drawRect(int x0, int y0, int x1, int y1, const PIChar & c, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0);
void drawFrame(int x0, int y0, int x1, int y1, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0); void drawFrame(int x0, int y0, int x1, int y1, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0);
void drawText(int x, int y, const PIString & s, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Transparent, PIScreenTypes::CharFlags flags_char = 0); void drawText(int x, int y, const PIString & s, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Transparent, PIScreenTypes::CharFlags flags_char = 0);
void fillRect(int x0, int y0, int x1, int y1, const PIChar & c, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0); void fillRect(int x0, int y0, int x1, int y1, const PIChar & c, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0);
void fillRect(int x0, int y0, int x1, int y1, PIVector<PIVector<PIScreenTypes::Cell> > & content); void fillRect(int x0, int y0, int x1, int y1, PIVector<PIVector<PIScreenTypes::Cell> > & content);
PIChar artChar(const ArtChar type) const {return arts_.value(type, PIChar(' '));} PIChar artChar(const ArtChar type) const {return arts_.value(type, PIChar(' '));}
static void clear(PIVector<PIVector<PIScreenTypes::Cell> > & cells); static void clear(PIVector<PIVector<PIScreenTypes::Cell> > & cells);
private: private:
PIVector<PIVector<PIScreenTypes::Cell> > & cells; PIVector<PIVector<PIScreenTypes::Cell> > & cells;
int width, height; int width, height;
PIMap<ArtChar, PIChar> arts_; PIMap<ArtChar, PIChar> arts_;
}; };
#endif // PISCREENDRAWER_H #endif // PISCREENDRAWER_H

View File

@@ -1,106 +1,106 @@
/*! \file piscreentile.h /*! \file piscreentile.h
* \brief Basic PIScreen tile * \brief Basic PIScreen tile
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Basic PIScreen tile Basic PIScreen tile
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PISCREENTILE_H #ifndef PISCREENTILE_H
#define PISCREENTILE_H #define PISCREENTILE_H
#include "piscreentypes.h" #include "piscreentypes.h"
#include "pikbdlistener.h" #include "pikbdlistener.h"
class PIScreenDrawer; class PIScreenDrawer;
class PIP_EXPORT PIScreenTile: public PIObject { class PIP_EXPORT PIScreenTile: public PIObject {
friend class PIScreen; friend class PIScreen;
PIOBJECT_SUBCLASS(PIScreenTile, PIObject) PIOBJECT_SUBCLASS(PIScreenTile, PIObject)
public: public:
PIScreenTile(const PIString & n = PIString(), PIScreenTypes::Direction d = PIScreenTypes::Vertical, PIScreenTypes::SizePolicy p = PIScreenTypes::Preferred); PIScreenTile(const PIString & n = PIString(), PIScreenTypes::Direction d = PIScreenTypes::Vertical, PIScreenTypes::SizePolicy p = PIScreenTypes::Preferred);
virtual ~PIScreenTile(); virtual ~PIScreenTile();
void addTile(PIScreenTile * t); void addTile(PIScreenTile * t);
void takeTile(PIScreenTile * t); void takeTile(PIScreenTile * t);
void removeTile(PIScreenTile * t); void removeTile(PIScreenTile * t);
PIScreenTile * parentTile() const {return parent;} PIScreenTile * parentTile() const {return parent;}
PIVector<PIScreenTile * > children(bool only_visible = false); PIVector<PIScreenTile * > children(bool only_visible = false);
PIScreenTile * childUnderMouse(int x, int y); PIScreenTile * childUnderMouse(int x, int y);
void show() {visible = true;} void show() {visible = true;}
void hide() {visible = false;} void hide() {visible = false;}
void setFocus(); void setFocus();
bool hasFocus() const {return has_focus;} bool hasFocus() const {return has_focus;}
void setMargins(int m) {marginLeft = marginRight = marginTop = marginBottom = m;} void setMargins(int m) {marginLeft = marginRight = marginTop = marginBottom = m;}
void setMargins(int l, int r, int t, int b) {marginLeft = l; marginRight = r; marginTop = t; marginBottom = b;} void setMargins(int l, int r, int t, int b) {marginLeft = l; marginRight = r; marginTop = t; marginBottom = b;}
int x() const {return x_;} int x() const {return x_;}
int y() const {return y_;} int y() const {return y_;}
int width() const {return width_;} int width() const {return width_;}
int height() const {return height_;} int height() const {return height_;}
PIScreenTypes::Direction direction; PIScreenTypes::Direction direction;
PIScreenTypes::SizePolicy size_policy; PIScreenTypes::SizePolicy size_policy;
PIScreenTypes::FocusFlags focus_flags; PIScreenTypes::FocusFlags focus_flags;
PIScreenTypes::CellFormat back_format; PIScreenTypes::CellFormat back_format;
PIChar back_symbol; PIChar back_symbol;
int minimumWidth, minimumHeight; int minimumWidth, minimumHeight;
int maximumWidth, maximumHeight; int maximumWidth, maximumHeight;
int marginLeft, marginRight, marginTop, marginBottom; int marginLeft, marginRight, marginTop, marginBottom;
int spacing; int spacing;
bool visible; bool visible;
protected: protected:
//! Returns desired tile size in "w" and "h" //! Returns desired tile size in "w" and "h"
virtual void sizeHint(int & w, int & h) const; virtual void sizeHint(int & w, int & h) const;
//! Tile has been resized to "w"x"h" //! Tile has been resized to "w"x"h"
virtual void resizeEvent(int w, int h) {} virtual void resizeEvent(int w, int h) {}
//! Draw tile with drawer "d" in world-space coordinates //! Draw tile with drawer "d" in world-space coordinates
virtual void drawEvent(PIScreenDrawer * d) {} virtual void drawEvent(PIScreenDrawer * d) {}
//! Return "true" if you process key //! Return "true" if you process key
virtual bool keyEvent(PIKbdListener::KeyEvent key) {return false;} virtual bool keyEvent(PIKbdListener::KeyEvent key) {return false;}
//! Return "true" if you process event //! Return "true" if you process event
virtual bool mouseEvent(PIKbdListener::MouseEvent me) {return false;} virtual bool mouseEvent(PIKbdListener::MouseEvent me) {return false;}
//! Return "true" if you process wheel //! Return "true" if you process wheel
virtual bool wheelEvent(PIKbdListener::WheelEvent we) {return false;} virtual bool wheelEvent(PIKbdListener::WheelEvent we) {return false;}
void raiseEvent(PIScreenTypes::TileEvent e); void raiseEvent(PIScreenTypes::TileEvent e);
void setScreen(PIScreenTypes::PIScreenBase * s); void setScreen(PIScreenTypes::PIScreenBase * s);
void deleteChildren(); void deleteChildren();
void drawEventInternal(PIScreenDrawer * d); void drawEventInternal(PIScreenDrawer * d);
void layout(); void layout();
bool needLayout() {return size_policy != PIScreenTypes::Ignore;} bool needLayout() {return size_policy != PIScreenTypes::Ignore;}
PIVector<PIScreenTile * > tiles; PIVector<PIScreenTile * > tiles;
PIScreenTile * parent; PIScreenTile * parent;
PIScreenTypes::PIScreenBase * screen; PIScreenTypes::PIScreenBase * screen;
int x_, y_, width_, height_; int x_, y_, width_, height_;
bool has_focus; bool has_focus;
private: private:
int pw, ph; int pw, ph;
}; };
#endif // PISCREENTILE_H #endif // PISCREENTILE_H

View File

@@ -1,213 +1,213 @@
/*! \file piscreentiles.h /*! \file piscreentiles.h
* \brief Various tiles for PIScreen * \brief Various tiles for PIScreen
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Various tiles for PIScreen Various tiles for PIScreen
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PISCREENTILES_H #ifndef PISCREENTILES_H
#define PISCREENTILES_H #define PISCREENTILES_H
#include "piscreentile.h" #include "piscreentile.h"
class PIP_EXPORT TileSimple: public PIScreenTile { class PIP_EXPORT TileSimple: public PIScreenTile {
PIOBJECT_SUBCLASS(TileSimple, PIScreenTile) PIOBJECT_SUBCLASS(TileSimple, PIScreenTile)
public: public:
typedef PIPair<PIString, PIScreenTypes::CellFormat> Row; typedef PIPair<PIString, PIScreenTypes::CellFormat> Row;
TileSimple(const PIString & n = PIString()); TileSimple(const PIString & n = PIString());
TileSimple(const Row & r); TileSimple(const Row & r);
virtual ~TileSimple() {} virtual ~TileSimple() {}
PIVector<Row> content; PIVector<Row> content;
PIScreenTypes::Alignment alignment; PIScreenTypes::Alignment alignment;
protected: protected:
void sizeHint(int & w, int & h) const; void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d); void drawEvent(PIScreenDrawer * d);
}; };
class TileList; class TileList;
class PIP_EXPORT TileScrollBar: public PIScreenTile { class PIP_EXPORT TileScrollBar: public PIScreenTile {
PIOBJECT_SUBCLASS(TileScrollBar, PIScreenTile) PIOBJECT_SUBCLASS(TileScrollBar, PIScreenTile)
friend class TileList; friend class TileList;
public: public:
TileScrollBar(const PIString & n = PIString()); TileScrollBar(const PIString & n = PIString());
virtual ~TileScrollBar() {} virtual ~TileScrollBar() {}
void setMinimum(int v); void setMinimum(int v);
void setMaximum(int v); void setMaximum(int v);
void setValue(int v); void setValue(int v);
int minimum() const {return minimum_;} int minimum() const {return minimum_;}
int maximum() const {return maximum_;} int maximum() const {return maximum_;}
int value() const {return value_;} int value() const {return value_;}
int thickness; int thickness;
protected: protected:
void _check(); void _check();
void sizeHint(int & w, int & h) const; void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d); void drawEvent(PIScreenDrawer * d);
bool mouseEvent(PIKbdListener::MouseEvent me); bool mouseEvent(PIKbdListener::MouseEvent me);
int minimum_, maximum_, value_; int minimum_, maximum_, value_;
PIChar line_char; PIChar line_char;
}; };
class PIP_EXPORT TileList: public PIScreenTile { class PIP_EXPORT TileList: public PIScreenTile {
PIOBJECT_SUBCLASS(TileList, PIScreenTile) PIOBJECT_SUBCLASS(TileList, PIScreenTile)
public: public:
TileList(const PIString & n = PIString()); TileList(const PIString & n = PIString());
virtual ~TileList() {} virtual ~TileList() {}
enum SelectionMode { enum SelectionMode {
NoSelection, NoSelection,
SingleSelection, SingleSelection,
MultiSelection MultiSelection
}; };
enum EventType { enum EventType {
SelectionChanged, SelectionChanged,
RowPressed RowPressed
}; };
typedef PIPair<PIString, PIScreenTypes::CellFormat> Row; typedef PIPair<PIString, PIScreenTypes::CellFormat> Row;
PIDeque<Row> content; PIDeque<Row> content;
PIScreenTypes::Alignment alignment; PIScreenTypes::Alignment alignment;
SelectionMode selection_mode; SelectionMode selection_mode;
PISet<int> selected; PISet<int> selected;
int lhei, cur, offset; int lhei, cur, offset;
protected: protected:
void sizeHint(int & w, int & h) const; void sizeHint(int & w, int & h) const;
void resizeEvent(int w, int h); void resizeEvent(int w, int h);
void drawEvent(PIScreenDrawer * d); void drawEvent(PIScreenDrawer * d);
bool keyEvent(PIKbdListener::KeyEvent key); bool keyEvent(PIKbdListener::KeyEvent key);
bool mouseEvent(PIKbdListener::MouseEvent me); bool mouseEvent(PIKbdListener::MouseEvent me);
bool wheelEvent(PIKbdListener::WheelEvent we); bool wheelEvent(PIKbdListener::WheelEvent we);
TileScrollBar * scroll; TileScrollBar * scroll;
bool mouse_sel; bool mouse_sel;
}; };
class PIP_EXPORT TileButton: public PIScreenTile { class PIP_EXPORT TileButton: public PIScreenTile {
PIOBJECT_SUBCLASS(TileButton, PIScreenTile) PIOBJECT_SUBCLASS(TileButton, PIScreenTile)
public: public:
TileButton(const PIString & n = PIString()); TileButton(const PIString & n = PIString());
virtual ~TileButton() {} virtual ~TileButton() {}
enum EventType { enum EventType {
ButtonClicked ButtonClicked
}; };
PIScreenTypes::CellFormat format; PIScreenTypes::CellFormat format;
PIString text; PIString text;
protected: protected:
void sizeHint(int & w, int & h) const; void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d); void drawEvent(PIScreenDrawer * d);
bool keyEvent(PIKbdListener::KeyEvent key); bool keyEvent(PIKbdListener::KeyEvent key);
bool mouseEvent(PIKbdListener::MouseEvent me); bool mouseEvent(PIKbdListener::MouseEvent me);
}; };
class PIP_EXPORT TileButtons: public PIScreenTile { class PIP_EXPORT TileButtons: public PIScreenTile {
PIOBJECT_SUBCLASS(TileButtons, PIScreenTile) PIOBJECT_SUBCLASS(TileButtons, PIScreenTile)
public: public:
TileButtons(const PIString & n = PIString()); TileButtons(const PIString & n = PIString());
virtual ~TileButtons() {} virtual ~TileButtons() {}
enum EventType { enum EventType {
ButtonSelected ButtonSelected
}; };
typedef PIPair<PIString, PIScreenTypes::CellFormat> Button; typedef PIPair<PIString, PIScreenTypes::CellFormat> Button;
PIScreenTypes::Alignment alignment; PIScreenTypes::Alignment alignment;
PIVector<Button> content; PIVector<Button> content;
int cur; int cur;
protected: protected:
void sizeHint(int & w, int & h) const; void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d); void drawEvent(PIScreenDrawer * d);
bool keyEvent(PIKbdListener::KeyEvent key); bool keyEvent(PIKbdListener::KeyEvent key);
bool mouseEvent(PIKbdListener::MouseEvent me); bool mouseEvent(PIKbdListener::MouseEvent me);
struct Rect { struct Rect {
Rect(int _x0 = 0, int _y0 = 0, int _x1 = 0, int _y1 = 0): x0(_x0),y0(_y0),x1(_x1),y1(_y1) {} Rect(int _x0 = 0, int _y0 = 0, int _x1 = 0, int _y1 = 0): x0(_x0),y0(_y0),x1(_x1),y1(_y1) {}
int x0,y0,x1,y1; int x0,y0,x1,y1;
}; };
PIVector<Rect> btn_rects; PIVector<Rect> btn_rects;
}; };
class PIP_EXPORT TileCheck: public PIScreenTile { class PIP_EXPORT TileCheck: public PIScreenTile {
PIOBJECT_SUBCLASS(TileCheck, PIScreenTile) PIOBJECT_SUBCLASS(TileCheck, PIScreenTile)
public: public:
TileCheck(const PIString & n = PIString()); TileCheck(const PIString & n = PIString());
virtual ~TileCheck() {} virtual ~TileCheck() {}
enum EventType { enum EventType {
Toggled Toggled
}; };
PIScreenTypes::CellFormat format; PIScreenTypes::CellFormat format;
PIString text; PIString text;
bool toggled; bool toggled;
protected: protected:
void sizeHint(int & w, int & h) const; void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d); void drawEvent(PIScreenDrawer * d);
bool keyEvent(PIKbdListener::KeyEvent key); bool keyEvent(PIKbdListener::KeyEvent key);
bool mouseEvent(PIKbdListener::MouseEvent me); bool mouseEvent(PIKbdListener::MouseEvent me);
}; };
class PIP_EXPORT TileProgress: public PIScreenTile { class PIP_EXPORT TileProgress: public PIScreenTile {
PIOBJECT_SUBCLASS(TileProgress, PIScreenTile) PIOBJECT_SUBCLASS(TileProgress, PIScreenTile)
public: public:
TileProgress(const PIString & n = PIString()); TileProgress(const PIString & n = PIString());
virtual ~TileProgress() {} virtual ~TileProgress() {}
PIScreenTypes::CellFormat format; PIScreenTypes::CellFormat format;
PIString prefix; PIString prefix;
PIString suffix; PIString suffix;
double maximum; double maximum;
double value; double value;
protected: protected:
void sizeHint(int & w, int & h) const; void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d); void drawEvent(PIScreenDrawer * d);
}; };
class PIP_EXPORT TilePICout: public TileList { class PIP_EXPORT TilePICout: public TileList {
PIOBJECT_SUBCLASS(TilePICout, PIScreenTile) PIOBJECT_SUBCLASS(TilePICout, PIScreenTile)
public: public:
TilePICout(const PIString & n = PIString()); TilePICout(const PIString & n = PIString());
virtual ~TilePICout() {} virtual ~TilePICout() {}
PIScreenTypes::CellFormat format; PIScreenTypes::CellFormat format;
int max_lines; int max_lines;
protected: protected:
void drawEvent(PIScreenDrawer * d); void drawEvent(PIScreenDrawer * d);
bool keyEvent(PIKbdListener::KeyEvent key); bool keyEvent(PIKbdListener::KeyEvent key);
}; };
class PIP_EXPORT TileInput: public PIScreenTile { class PIP_EXPORT TileInput: public PIScreenTile {
PIOBJECT_SUBCLASS(TileInput, PIScreenTile) PIOBJECT_SUBCLASS(TileInput, PIScreenTile)
public: public:
TileInput(const PIString & n = PIString()); TileInput(const PIString & n = PIString());
virtual ~TileInput() {} virtual ~TileInput() {}
PIScreenTypes::CellFormat format; PIScreenTypes::CellFormat format;
PIString text; PIString text;
int max_length; int max_length;
protected: protected:
void sizeHint(int & w, int & h) const; void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d); void drawEvent(PIScreenDrawer * d);
bool keyEvent(PIKbdListener::KeyEvent key); bool keyEvent(PIKbdListener::KeyEvent key);
void reserCursor(); void reserCursor();
int cur, offset; int cur, offset;
bool inv; bool inv;
PITimeMeasurer tm_blink; PITimeMeasurer tm_blink;
}; };
#endif // PISCREENTILES_H #endif // PISCREENTILES_H

View File

@@ -1,146 +1,146 @@
/*! \file piscreentypes.h /*! \file piscreentypes.h
* \brief Types for PIScreen * \brief Types for PIScreen
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Types for PIScreen Types for PIScreen
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PISCREENTYPES_H #ifndef PISCREENTYPES_H
#define PISCREENTYPES_H #define PISCREENTYPES_H
#include "pivariant.h" #include "pivariant.h"
class PIScreenTile; class PIScreenTile;
namespace PIScreenTypes { namespace PIScreenTypes {
//! Color for chars or background //! Color for chars or background
enum PIP_EXPORT Color { enum PIP_EXPORT Color {
Default /** Default */, Default /** Default */,
Black /** Black */, Black /** Black */,
Red /** Red */, Red /** Red */,
Green /** Green */, Green /** Green */,
Blue /** Blue */, Blue /** Blue */,
Cyan /** Cyan */, Cyan /** Cyan */,
Magenta /** Magenta */, Magenta /** Magenta */,
Yellow /** Yellow */, Yellow /** Yellow */,
White /** White */, White /** White */,
Transparent /** Save previous color */ Transparent /** Save previous color */
}; };
//! Flags for chars //! Flags for chars
enum PIP_EXPORT CharFlag { enum PIP_EXPORT CharFlag {
Bold /** Bold or bright */ = 0x1, Bold /** Bold or bright */ = 0x1,
Blink /** Blink text */ = 0x2, Blink /** Blink text */ = 0x2,
Underline /** Underline text */ = 0x4, Underline /** Underline text */ = 0x4,
Inverse = 0x08 Inverse = 0x08
}; };
//! Alignment //! Alignment
enum PIP_EXPORT Alignment { enum PIP_EXPORT Alignment {
Left /** Left */ , Left /** Left */ ,
Center /** Center */ , Center /** Center */ ,
Right /** Right */ Right /** Right */
}; };
//! Size policy //! Size policy
enum PIP_EXPORT SizePolicy { enum PIP_EXPORT SizePolicy {
Fixed /** Fixed size */ , Fixed /** Fixed size */ ,
Preferred /** Preferred size */ , Preferred /** Preferred size */ ,
Expanding /** Maximum available size */ , Expanding /** Maximum available size */ ,
Ignore /** Ignore layout logic */ Ignore /** Ignore layout logic */
}; };
//! Direction //! Direction
enum PIP_EXPORT Direction { enum PIP_EXPORT Direction {
Horizontal /** Horizontal */ , Horizontal /** Horizontal */ ,
Vertical /** Vertical */ Vertical /** Vertical */
}; };
//! Focus flags //! Focus flags
enum PIP_EXPORT FocusFlag { enum PIP_EXPORT FocusFlag {
CanHasFocus /** Tile can has focus */ = 0x1, CanHasFocus /** Tile can has focus */ = 0x1,
NextByTab /** Focus passed to next tile by tab key */ = 0x2, NextByTab /** Focus passed to next tile by tab key */ = 0x2,
NextByArrowsHorizontal /** Focus passed to next tile by arrow keys left or right */ = 0x4, NextByArrowsHorizontal /** Focus passed to next tile by arrow keys left or right */ = 0x4,
NextByArrowsVertical /** Focus passed to next tile by arrow keys up or down */ = 0x8, NextByArrowsVertical /** Focus passed to next tile by arrow keys up or down */ = 0x8,
NextByArrowsAll /** Focus passed to next tile by any arrow key */ = NextByArrowsHorizontal | NextByArrowsVertical, NextByArrowsAll /** Focus passed to next tile by any arrow key */ = NextByArrowsHorizontal | NextByArrowsVertical,
FocusOnMouse /** Tile focused on mouse press */ = 0x10, FocusOnMouse /** Tile focused on mouse press */ = 0x10,
FocusOnWheel /** Tile focused on wheel */ = 0x20, FocusOnWheel /** Tile focused on wheel */ = 0x20,
FocusOnMouseOrWheel /** Tile focused on mouse press or wheel */ = FocusOnMouse | FocusOnWheel FocusOnMouseOrWheel /** Tile focused on mouse press or wheel */ = FocusOnMouse | FocusOnWheel
}; };
typedef PIFlags<CharFlag> CharFlags; typedef PIFlags<CharFlag> CharFlags;
typedef PIFlags<FocusFlag> FocusFlags; typedef PIFlags<FocusFlag> FocusFlags;
union PIP_EXPORT CellFormat { union PIP_EXPORT CellFormat {
CellFormat(ushort f = 0) {raw_format = f;} CellFormat(ushort f = 0) {raw_format = f;}
CellFormat(Color col_char, Color col_back = Default, CharFlags flags_ = 0) { CellFormat(Color col_char, Color col_back = Default, CharFlags flags_ = 0) {
color_char = col_char; color_char = col_char;
color_back = col_back; color_back = col_back;
flags = flags_; flags = flags_;
} }
ushort raw_format; ushort raw_format;
struct { struct {
ushort color_char : 4; ushort color_char : 4;
ushort color_back : 4; ushort color_back : 4;
ushort flags : 8; ushort flags : 8;
}; };
bool operator ==(const CellFormat & c) const {return raw_format == c.raw_format;} bool operator ==(const CellFormat & c) const {return raw_format == c.raw_format;}
bool operator !=(const CellFormat & c) const {return raw_format != c.raw_format;} bool operator !=(const CellFormat & c) const {return raw_format != c.raw_format;}
}; };
struct PIP_EXPORT Cell { struct PIP_EXPORT Cell {
Cell(PIChar c = PIChar(' '), CellFormat f = CellFormat()) {symbol = c; format = f;} Cell(PIChar c = PIChar(' '), CellFormat f = CellFormat()) {symbol = c; format = f;}
CellFormat format; CellFormat format;
PIChar symbol; PIChar symbol;
bool operator ==(const Cell & c) const {return format == c.format && symbol == c.symbol;} bool operator ==(const Cell & c) const {return format == c.format && symbol == c.symbol;}
bool operator !=(const Cell & c) const {return format != c.format || symbol != c.symbol;} bool operator !=(const Cell & c) const {return format != c.format || symbol != c.symbol;}
Cell & operator =(const Cell & c) { Cell & operator =(const Cell & c) {
symbol = c.symbol; symbol = c.symbol;
if (c.format.color_back == Transparent) { if (c.format.color_back == Transparent) {
format.color_char = c.format.color_char; format.color_char = c.format.color_char;
format.flags = c.format.flags; format.flags = c.format.flags;
} else format = c.format; } else format = c.format;
return *this; return *this;
} }
}; };
struct PIP_EXPORT TileEvent { struct PIP_EXPORT TileEvent {
TileEvent(int t = -1, const PIVariant & d = PIVariant()): type(t), data(d) {} TileEvent(int t = -1, const PIVariant & d = PIVariant()): type(t), data(d) {}
int type; int type;
PIVariant data; PIVariant data;
}; };
class PIScreenBase { class PIScreenBase {
public: public:
PIScreenBase() {} PIScreenBase() {}
virtual ~PIScreenBase() {} virtual ~PIScreenBase() {}
virtual void tileEventInternal(PIScreenTile * , TileEvent) {} virtual void tileEventInternal(PIScreenTile * , TileEvent) {}
virtual void tileRemovedInternal(PIScreenTile * ) {} virtual void tileRemovedInternal(PIScreenTile * ) {}
virtual void tileSetFocusInternal(PIScreenTile * ) {} virtual void tileSetFocusInternal(PIScreenTile * ) {}
}; };
} }
inline PIByteArray & operator <<(PIByteArray & s, const PIScreenTypes::Cell & v) {s << v.format.raw_format << v.symbol; return s;} inline PIByteArray & operator <<(PIByteArray & s, const PIScreenTypes::Cell & v) {s << v.format.raw_format << v.symbol; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIScreenTypes::Cell & v) {s >> v.format.raw_format >> v.symbol; return s;} inline PIByteArray & operator >>(PIByteArray & s, PIScreenTypes::Cell & v) {s >> v.format.raw_format >> v.symbol; return s;}
#endif // PISCREENTYPES_H #endif // PISCREENTYPES_H

View File

@@ -1,76 +1,76 @@
/*! \file piterminal.h /*! \file piterminal.h
* \brief Virtual terminal * \brief Virtual terminal
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Virtual terminal Virtual terminal
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PITERMINAL_H #ifndef PITERMINAL_H
#define PITERMINAL_H #define PITERMINAL_H
#include "pikbdlistener.h" #include "pikbdlistener.h"
#include "piscreentypes.h" #include "piscreentypes.h"
class PIP_EXPORT PITerminal: public PIThread class PIP_EXPORT PITerminal: public PIThread
{ {
PIOBJECT_SUBCLASS(PITerminal, PIThread) PIOBJECT_SUBCLASS(PITerminal, PIThread)
public: public:
//! Constructs %PITerminal //! Constructs %PITerminal
PITerminal(); PITerminal();
~PITerminal(); ~PITerminal();
int columns() const {return size_x;} int columns() const {return size_x;}
int rows() const {return size_y;} int rows() const {return size_y;}
bool resize(int cols, int rows); bool resize(int cols, int rows);
void write(const PIByteArray & d); void write(const PIByteArray & d);
void write(PIKbdListener::SpecialKey k, PIKbdListener::KeyModifiers m); void write(PIKbdListener::SpecialKey k, PIKbdListener::KeyModifiers m);
void write(PIKbdListener::KeyEvent ke); void write(PIKbdListener::KeyEvent ke);
PIVector<PIVector<PIScreenTypes::Cell> > content(); PIVector<PIVector<PIScreenTypes::Cell> > content();
static bool isSpecialKey(int k); static bool isSpecialKey(int k);
bool initialize(); bool initialize();
void destroy(); void destroy();
private: private:
void initPrivate(); void initPrivate();
void readConsole(); void readConsole();
void getCursor(int & x, int & y); void getCursor(int & x, int & y);
uchar invertColor(uchar c); uchar invertColor(uchar c);
void run(); void run();
#ifndef WINDOWS #ifndef WINDOWS
void parseInput(const PIString & s); void parseInput(const PIString & s);
bool isCompleteEscSeq(const PIString & es); bool isCompleteEscSeq(const PIString & es);
void applyEscSeq(PIString es); void applyEscSeq(PIString es);
void moveCursor(int dx, int dy); void moveCursor(int dx, int dy);
int termType(const PIString & t); int termType(const PIString & t);
#endif #endif
PRIVATE_DECLARATION PRIVATE_DECLARATION
int dsize_x, dsize_y; int dsize_x, dsize_y;
int size_x, size_y, cursor_x, cursor_y; int size_x, size_y, cursor_x, cursor_y;
bool cursor_blink, cursor_visible; bool cursor_blink, cursor_visible;
PITimeMeasurer cursor_tm; PITimeMeasurer cursor_tm;
PIVector<PIVector<PIScreenTypes::Cell> > cells; PIVector<PIVector<PIScreenTypes::Cell> > cells;
}; };
#endif // PITERMINAL_H #endif // PITERMINAL_H

View File

View File

@@ -1,55 +1,55 @@
/*! \file pipair.h /*! \file pipair.h
* \brief pair * \brief pair
* *
* This file declare PIPair * This file declare PIPair
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
pair pair
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PIPAIR_H #ifndef PIPAIR_H
#define PIPAIR_H #define PIPAIR_H
#include "pibase.h" #include "pibase.h"
class PICout; class PICout;
template<typename Type0, typename Type1> template<typename Type0, typename Type1>
class PIP_EXPORT PIPair { class PIP_EXPORT PIPair {
public: public:
PIPair() {first = Type0(); second = Type1();} PIPair() {first = Type0(); second = Type1();}
PIPair(const Type0 & value0, const Type1 & value1) {first = value0; second = value1;} PIPair(const Type0 & value0, const Type1 & value1) {first = value0; second = value1;}
Type0 first; Type0 first;
Type1 second; Type1 second;
}; };
template<typename Type0, typename Type1> template<typename Type0, typename Type1>
inline bool operator <(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {return value0.first < value1.first;} inline bool operator <(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {return value0.first < value1.first;}
template<typename Type0, typename Type1> template<typename Type0, typename Type1>
inline bool operator ==(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {return (value0.first == value1.first) && (value0.second == value1.second);} inline bool operator ==(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {return (value0.first == value1.first) && (value0.second == value1.second);}
template<typename Type0, typename Type1> template<typename Type0, typename Type1>
inline bool operator !=(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {return (value0.first != value1.first) || (value0.second != value1.second);} inline bool operator !=(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {return (value0.first != value1.first) || (value0.second != value1.second);}
#ifdef PIP_STD_IOSTREAM #ifdef PIP_STD_IOSTREAM
template<typename Type0, typename Type1> template<typename Type0, typename Type1>
inline std::ostream & operator <<(std::ostream & s, const PIPair<Type0, Type1> & v) {s << "(" << v.first << ", " << v.second << ")"; return s;} inline std::ostream & operator <<(std::ostream & s, const PIPair<Type0, Type1> & v) {s << "(" << v.first << ", " << v.second << ")"; return s;}
#endif #endif
template<typename Type0, typename Type1> template<typename Type0, typename Type1>
inline PICout operator <<(PICout s, const PIPair<Type0, Type1> & v) {s.space(); s.setControl(0, true); s << "(" << v.first << ", " << v.second << ")"; s.restoreControl(); return s;} inline PICout operator <<(PICout s, const PIPair<Type0, Type1> & v) {s.space(); s.setControl(0, true); s << "(" << v.first << ", " << v.second << ")"; s.restoreControl(); return s;}
#endif // PIPAIR_H #endif // PIPAIR_H

View File

View File

View File

View File

@@ -1,307 +1,307 @@
/*! \file pivecto2d.h /*! \file pivecto2d.h
* \brief 2D wrapper around PIVector * \brief 2D wrapper around PIVector
* *
* This file declares PIVector * This file declares PIVector
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
2D wrapper around PIVector 2D wrapper around PIVector
Andrey Bychkov work.a.b@yandex.ru Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PIVECTOR2D_H #ifndef PIVECTOR2D_H
#define PIVECTOR2D_H #define PIVECTOR2D_H
#include "pivector.h" #include "pivector.h"
/*! \brief 2D array, /*! \brief 2D array,
* \details This class used to store 2D array of any type elements as plain vector. * \details This class used to store 2D array of any type elements as plain vector.
* You can read/write any element via operators [][], first dimension - row, second - column. * You can read/write any element via operators [][], first dimension - row, second - column.
* The first dimension is Row, and you can operate with Row as PIVector<T>: modify any element, assign to another Row and etc. * The first dimension is Row, and you can operate with Row as PIVector<T>: modify any element, assign to another Row and etc.
* You can't add values to array, but you can modify any elements or create another PIVector2D. * You can't add values to array, but you can modify any elements or create another PIVector2D.
* PIVector2D has constructors from PIVector<T> and PIVector<PIVector<T> > * PIVector2D has constructors from PIVector<T> and PIVector<PIVector<T> >
*/ */
template <typename T> template <typename T>
class PIVector2D { class PIVector2D {
public: public:
inline PIVector2D() {rows_ = cols_ = 0;} inline PIVector2D() {rows_ = cols_ = 0;}
inline PIVector2D(size_t rows, size_t cols, const T & f = T()) { inline PIVector2D(size_t rows, size_t cols, const T & f = T()) {
rows_ = rows; rows_ = rows;
cols_ = cols; cols_ = cols;
mat.resize(rows*cols, f); mat.resize(rows*cols, f);
} }
inline PIVector2D(size_t rows, size_t cols, const PIVector<T> & v) { inline PIVector2D(size_t rows, size_t cols, const PIVector<T> & v) {
mat = v; mat = v;
rows_ = rows; rows_ = rows;
cols_ = cols; cols_ = cols;
mat.resize(rows*cols); mat.resize(rows*cols);
} }
inline PIVector2D(const PIVector<PIVector<T> > & v) { inline PIVector2D(const PIVector<PIVector<T> > & v) {
rows_ = v.size(); rows_ = v.size();
if (rows_) { if (rows_) {
cols_ = v[0].size(); cols_ = v[0].size();
for (size_t i = 0; i < rows_; i++) { for (size_t i = 0; i < rows_; i++) {
mat.append(v[i]); mat.append(v[i]);
} }
mat.resize(rows_*cols_); mat.resize(rows_*cols_);
} }
if (mat.isEmpty()) rows_ = cols_ = 0; if (mat.isEmpty()) rows_ = cols_ = 0;
} }
inline size_t rows() const {return rows_;} inline size_t rows() const {return rows_;}
inline size_t cols() const {return cols_;} inline size_t cols() const {return cols_;}
inline size_t size() const {return mat.size();} inline size_t size() const {return mat.size();}
inline ssize_t size_s() const {return mat.size_s();} inline ssize_t size_s() const {return mat.size_s();}
inline size_t length() const {return mat.length();} inline size_t length() const {return mat.length();}
inline size_t capacity() const {return mat.capacity();} inline size_t capacity() const {return mat.capacity();}
inline bool isEmpty() const {return mat.isEmpty();} inline bool isEmpty() const {return mat.isEmpty();}
class Row { class Row {
friend class PIVector2D<T>; friend class PIVector2D<T>;
private: private:
inline Row(PIVector2D<T> * p, size_t row) : p_(&(p->mat)) {st_ = p->cols_ * row; sz_ = p->cols_;} inline Row(PIVector2D<T> * p, size_t row) : p_(&(p->mat)) {st_ = p->cols_ * row; sz_ = p->cols_;}
PIVector<T> * p_; PIVector<T> * p_;
size_t st_, sz_; size_t st_, sz_;
public: public:
inline size_t size() const {return sz_;} inline size_t size() const {return sz_;}
inline T & operator [](size_t index) {return (*p_)[st_ + index];} inline T & operator [](size_t index) {return (*p_)[st_ + index];}
inline const T & operator [](size_t index) const {return (*p_)[st_ + index];} inline const T & operator [](size_t index) const {return (*p_)[st_ + index];}
inline T * data(size_t index = 0) {return p_->data(st_ + index);} inline T * data(size_t index = 0) {return p_->data(st_ + index);}
inline const T * data(size_t index = 0) const {return p_->data(st_ + index);} inline const T * data(size_t index = 0) const {return p_->data(st_ + index);}
inline Row & operator =(const Row & other) { inline Row & operator =(const Row & other) {
if (p_ == other.p_ && st_ == other.st_) return *this; if (p_ == other.p_ && st_ == other.st_) return *this;
size_t sz = piMin<size_t>(sz_, other.sz_); size_t sz = piMin<size_t>(sz_, other.sz_);
p_->_copyRaw(p_->data(st_), other.data(), sz); p_->_copyRaw(p_->data(st_), other.data(), sz);
return *this; return *this;
} }
inline Row & operator =(const PIVector<T> & other) { inline Row & operator =(const PIVector<T> & other) {
size_t sz = piMin<size_t>(sz, other.size()); size_t sz = piMin<size_t>(sz, other.size());
p_->_copyRaw(p_->data(st_), other.data(), sz); p_->_copyRaw(p_->data(st_), other.data(), sz);
return *this; return *this;
} }
inline PIVector<T> toVector() const {return PIVector<T>(p_->data(st_), sz_);} inline PIVector<T> toVector() const {return PIVector<T>(p_->data(st_), sz_);}
}; };
class Col { class Col {
friend class PIVector2D<T>; friend class PIVector2D<T>;
private: private:
inline Col(PIVector2D<T> * p, size_t row) : p_(&(p->mat)) {step_ = p->cols_; row_ = row; sz_ = p->rows_;} inline Col(PIVector2D<T> * p, size_t row) : p_(&(p->mat)) {step_ = p->cols_; row_ = row; sz_ = p->rows_;}
PIVector<T> * p_; PIVector<T> * p_;
size_t step_, row_, sz_; size_t step_, row_, sz_;
public: public:
inline size_t size() const {return sz_;} inline size_t size() const {return sz_;}
inline T & operator [](size_t index) {return (*p_)[index * step_ + row_];} inline T & operator [](size_t index) {return (*p_)[index * step_ + row_];}
inline const T & operator [](size_t index) const {return (*p_)[index * step_ + row_];} inline const T & operator [](size_t index) const {return (*p_)[index * step_ + row_];}
inline T * data(size_t index = 0) {return p_->data(index * step_ + row_);} inline T * data(size_t index = 0) {return p_->data(index * step_ + row_);}
inline const T * data(size_t index = 0) const {return p_->data(index * step_ + row_);} inline const T * data(size_t index = 0) const {return p_->data(index * step_ + row_);}
inline Col & operator =(const Col & other) { inline Col & operator =(const Col & other) {
if (p_ == other.p_ && row_ == other.row_) return *this; if (p_ == other.p_ && row_ == other.row_) return *this;
size_t sz = piMin<size_t>(sz_, other.sz_); size_t sz = piMin<size_t>(sz_, other.sz_);
for (int i=0; i<sz; ++i) (*p_)[i * step_ + row_] = other[i]; for (int i=0; i<sz; ++i) (*p_)[i * step_ + row_] = other[i];
return *this; return *this;
} }
inline Row & operator =(const PIVector<T> & other) { inline Row & operator =(const PIVector<T> & other) {
size_t sz = piMin<size_t>(sz_, other.size()); size_t sz = piMin<size_t>(sz_, other.size());
for (int i=0; i<sz; ++i) (*p_)[i * step_ + row_] = other[i]; for (int i=0; i<sz; ++i) (*p_)[i * step_ + row_] = other[i];
return *this; return *this;
} }
inline PIVector<T> toVector() const { inline PIVector<T> toVector() const {
PIVector<T> ret; PIVector<T> ret;
ret.reserve(sz_); ret.reserve(sz_);
for (size_t i=0; i<sz_; i++) ret << (*p_)[i * step_ + row_]; for (size_t i=0; i<sz_; i++) ret << (*p_)[i * step_ + row_];
return ret; return ret;
} }
}; };
class RowConst { class RowConst {
friend class PIVector2D<T>; friend class PIVector2D<T>;
private: private:
inline RowConst(const PIVector2D<T> * p, size_t row) : p_(&(p->mat)) {st_ = p->cols_ * row; sz_ = p->cols_;} inline RowConst(const PIVector2D<T> * p, size_t row) : p_(&(p->mat)) {st_ = p->cols_ * row; sz_ = p->cols_;}
const PIVector<T> * p_; const PIVector<T> * p_;
size_t st_, sz_; size_t st_, sz_;
public: public:
inline size_t size() const {return sz_;} inline size_t size() const {return sz_;}
inline const T & operator [](size_t index) const {return (*p_)[st_ + index];} inline const T & operator [](size_t index) const {return (*p_)[st_ + index];}
inline const T * data(size_t index = 0) const {return p_->data(st_ + index);} inline const T * data(size_t index = 0) const {return p_->data(st_ + index);}
inline PIVector<T> toVector() const {return PIVector<T>(p_->data(st_), sz_);} inline PIVector<T> toVector() const {return PIVector<T>(p_->data(st_), sz_);}
}; };
class ColConst { class ColConst {
friend class PIVector2D<T>; friend class PIVector2D<T>;
private: private:
inline ColConst(const PIVector2D<T> * p, size_t row) : p_(&(p->mat)) {step_ = p->cols_; row_ = row; sz_ = p->rows_;} inline ColConst(const PIVector2D<T> * p, size_t row) : p_(&(p->mat)) {step_ = p->cols_; row_ = row; sz_ = p->rows_;}
const PIVector<T> * p_; const PIVector<T> * p_;
size_t step_, row_, sz_; size_t step_, row_, sz_;
public: public:
inline size_t size() const {return p_->rows_;} inline size_t size() const {return p_->rows_;}
inline const T & operator [](size_t index) const {return (*p_)[index * step_ + row_];} inline const T & operator [](size_t index) const {return (*p_)[index * step_ + row_];}
inline const T * data(size_t index = 0) const {return p_->data(index * step_ + row_);} inline const T * data(size_t index = 0) const {return p_->data(index * step_ + row_);}
inline PIVector<T> toVector() const { inline PIVector<T> toVector() const {
PIVector<T> ret; PIVector<T> ret;
ret.reserve(sz_); ret.reserve(sz_);
for (int i=0; i<size(); i++) ret << (*p_)[i * step_ + row_]; for (int i=0; i<size(); i++) ret << (*p_)[i * step_ + row_];
return ret; return ret;
} }
}; };
inline T & element(size_t row, size_t col) {return mat[row * cols_ + col];} inline T & element(size_t row, size_t col) {return mat[row * cols_ + col];}
inline const T & element(size_t row, size_t col) const {return mat[row * cols_ + col];} inline const T & element(size_t row, size_t col) const {return mat[row * cols_ + col];}
inline Row operator[](size_t index) {return Row(this, index);} inline Row operator[](size_t index) {return Row(this, index);}
inline RowConst operator[](size_t index) const {return RowConst(this, index);} inline RowConst operator[](size_t index) const {return RowConst(this, index);}
inline T * data(size_t index = 0) {return mat.data(index);} inline T * data(size_t index = 0) {return mat.data(index);}
inline const T * data(size_t index = 0) const {return mat.data(index);} inline const T * data(size_t index = 0) const {return mat.data(index);}
inline Row row(size_t index) {return Row(this, index);} inline Row row(size_t index) {return Row(this, index);}
inline RowConst row(size_t index) const {return RowConst(this, index);} inline RowConst row(size_t index) const {return RowConst(this, index);}
inline Col col(size_t index) {return Col(this, index);} inline Col col(size_t index) {return Col(this, index);}
inline ColConst col(size_t index) const {return ColConst(this, index);} inline ColConst col(size_t index) const {return ColConst(this, index);}
inline PIVector2D<T> & setRow(size_t row, const Row & other) { inline PIVector2D<T> & setRow(size_t row, const Row & other) {
size_t sz = piMin<size_t>(cols_, other.sz_); size_t sz = piMin<size_t>(cols_, other.sz_);
mat._copyRaw(mat.data(cols_ * row), other.data(), sz); mat._copyRaw(mat.data(cols_ * row), other.data(), sz);
return *this; return *this;
} }
inline PIVector2D<T> & setRow(size_t row, const RowConst & other) { inline PIVector2D<T> & setRow(size_t row, const RowConst & other) {
size_t sz = piMin<size_t>(cols_, other.sz_); size_t sz = piMin<size_t>(cols_, other.sz_);
mat._copyRaw(mat.data(cols_ * row), other.data(), sz); mat._copyRaw(mat.data(cols_ * row), other.data(), sz);
return *this; return *this;
} }
inline PIVector2D<T> & setRow(size_t row, const PIVector<T> & other) { inline PIVector2D<T> & setRow(size_t row, const PIVector<T> & other) {
size_t sz = piMin<size_t>(cols_, other.size()); size_t sz = piMin<size_t>(cols_, other.size());
mat._copyRaw(mat.data(cols_ * row), other.data(), sz); mat._copyRaw(mat.data(cols_ * row), other.data(), sz);
return *this; return *this;
} }
inline PIVector2D<T> & addRow(const Row & other) { inline PIVector2D<T> & addRow(const Row & other) {
if (cols_ == 0) cols_ = other.sz_; if (cols_ == 0) cols_ = other.sz_;
size_t sz = piMin<size_t>(cols_, other.sz_); size_t sz = piMin<size_t>(cols_, other.sz_);
size_t ps = mat.size(); size_t ps = mat.size();
mat.resize(mat.size() + cols_); mat.resize(mat.size() + cols_);
mat._copyRaw(mat.data(ps), other.data(), sz); mat._copyRaw(mat.data(ps), other.data(), sz);
rows_++; rows_++;
return *this; return *this;
} }
inline PIVector2D<T> & addRow(const RowConst & other) { inline PIVector2D<T> & addRow(const RowConst & other) {
if (cols_ == 0) cols_ = other.sz_; if (cols_ == 0) cols_ = other.sz_;
size_t sz = piMin<size_t>(cols_, other.sz_); size_t sz = piMin<size_t>(cols_, other.sz_);
size_t ps = mat.size(); size_t ps = mat.size();
mat.resize(mat.size() + cols_); mat.resize(mat.size() + cols_);
mat._copyRaw(mat.data(ps), other.data(), sz); mat._copyRaw(mat.data(ps), other.data(), sz);
rows_++; rows_++;
return *this; return *this;
} }
inline PIVector2D<T> & addRow(const PIVector<T> & other) { inline PIVector2D<T> & addRow(const PIVector<T> & other) {
if (cols_ == 0) cols_ = other.size(); if (cols_ == 0) cols_ = other.size();
size_t sz = piMin<size_t>(cols_, other.size()); size_t sz = piMin<size_t>(cols_, other.size());
size_t ps = mat.size(); size_t ps = mat.size();
mat.resize(mat.size() + cols_); mat.resize(mat.size() + cols_);
mat._copyRaw(mat.data(ps), other.data(), sz); mat._copyRaw(mat.data(ps), other.data(), sz);
rows_++; rows_++;
return *this; return *this;
} }
inline PIVector2D<T> & resize(size_t rows, size_t cols, const T & f = T()) { inline PIVector2D<T> & resize(size_t rows, size_t cols, const T & f = T()) {
mat.resize(rows*cols_, f); mat.resize(rows*cols_, f);
rows_ = rows; rows_ = rows;
int cs = (cols - cols_); int cs = (cols - cols_);
if (cs < 0) { if (cs < 0) {
for (size_t r=0; r<rows; ++r) { for (size_t r=0; r<rows; ++r) {
mat.remove(r*cols_ + cols_, -cs); mat.remove(r*cols_ + cols_, -cs);
} }
} }
mat.resize(rows*cols, f); mat.resize(rows*cols, f);
if (!mat.isEmpty()) { if (!mat.isEmpty()) {
if (cs > 0) { if (cs > 0) {
for (size_t r=0; r<rows_; ++r) { for (size_t r=0; r<rows_; ++r) {
for (int i=0; i<cs; ++i) for (int i=0; i<cs; ++i)
mat.insert(r*cols + cols_, mat.take_back()); mat.insert(r*cols + cols_, mat.take_back());
} }
} }
} }
cols_ = cols; cols_ = cols;
return *this; return *this;
} }
PIVector<PIVector<T> > toVectors() const { PIVector<PIVector<T> > toVectors() const {
PIVector<PIVector<T> > ret; PIVector<PIVector<T> > ret;
for(size_t i = 0; i < rows_; ++i) for(size_t i = 0; i < rows_; ++i)
ret << PIVector<T>(mat.data(i*cols_), cols_); ret << PIVector<T>(mat.data(i*cols_), cols_);
return ret; return ret;
} }
PIVector<T> toPlainVector() const {return mat;} PIVector<T> toPlainVector() const {return mat;}
PIVector<T> & plainVector() {return mat;} PIVector<T> & plainVector() {return mat;}
const PIVector<T> & plainVector() const {return mat;} const PIVector<T> & plainVector() const {return mat;}
inline void swap(PIVector2D<T> & other) { inline void swap(PIVector2D<T> & other) {
mat.swap(other.mat); mat.swap(other.mat);
piSwap<size_t>(rows_, other.rows_); piSwap<size_t>(rows_, other.rows_);
piSwap<size_t>(cols_, other.cols_); piSwap<size_t>(cols_, other.cols_);
} }
inline PIVector2D<T> & _resizeRaw(size_t r, size_t c) { inline PIVector2D<T> & _resizeRaw(size_t r, size_t c) {
piCout << "Error, \"resizeRaw()\" only allowed for simple type declared with __PIVECTOR_SIMPLE_TYPE__ macro!"; piCout << "Error, \"resizeRaw()\" only allowed for simple type declared with __PIVECTOR_SIMPLE_TYPE__ macro!";
assert(0); assert(0);
return *this; return *this;
} }
inline void clear() { inline void clear() {
rows_ = cols_ = 0; rows_ = cols_ = 0;
mat.clear(); mat.clear();
} }
protected: protected:
size_t rows_, cols_; size_t rows_, cols_;
PIVector<T> mat; PIVector<T> mat;
}; };
template<typename T> template<typename T>
inline PICout operator <<(PICout s, const PIVector2D<T> & v) { inline PICout operator <<(PICout s, const PIVector2D<T> & v) {
s.setControl(0, true); s.setControl(0, true);
s << "{"; s << "{";
for (size_t i = 0; i < v.rows(); ++i) { for (size_t i = 0; i < v.rows(); ++i) {
s << "{ "; s << "{ ";
for (size_t j = 0; j < v.cols(); ++j) { for (size_t j = 0; j < v.cols(); ++j) {
s << v[i][j]; s << v[i][j];
if (j < v.cols() - 1) s << ", "; if (j < v.cols() - 1) s << ", ";
} }
s << " }"; s << " }";
if (i < v.rows() - 1) s << PICoutManipulators::NewLine ; if (i < v.rows() - 1) s << PICoutManipulators::NewLine ;
} }
if (v.isEmpty()) s << "{ }"; if (v.isEmpty()) s << "{ }";
s << "}"; s << "}";
s.restoreControl(); s.restoreControl();
return s; return s;
} }
#define __PIVECTOR2D_SIMPLE_TYPE__(T) \ #define __PIVECTOR2D_SIMPLE_TYPE__(T) \
template<> inline PIVector2D<T> & PIVector2D<T>::_resizeRaw(size_t r, size_t c) {rows_ = r; cols_ = c; mat._resizeRaw(r*c); return *this;} template<> inline PIVector2D<T> & PIVector2D<T>::_resizeRaw(size_t r, size_t c) {rows_ = r; cols_ = c; mat._resizeRaw(r*c); return *this;}
__PIVECTOR2D_SIMPLE_TYPE__(bool) __PIVECTOR2D_SIMPLE_TYPE__(bool)
__PIVECTOR2D_SIMPLE_TYPE__(char) __PIVECTOR2D_SIMPLE_TYPE__(char)
__PIVECTOR2D_SIMPLE_TYPE__(uchar) __PIVECTOR2D_SIMPLE_TYPE__(uchar)
__PIVECTOR2D_SIMPLE_TYPE__(short) __PIVECTOR2D_SIMPLE_TYPE__(short)
__PIVECTOR2D_SIMPLE_TYPE__(ushort) __PIVECTOR2D_SIMPLE_TYPE__(ushort)
__PIVECTOR2D_SIMPLE_TYPE__(int) __PIVECTOR2D_SIMPLE_TYPE__(int)
__PIVECTOR2D_SIMPLE_TYPE__(uint) __PIVECTOR2D_SIMPLE_TYPE__(uint)
__PIVECTOR2D_SIMPLE_TYPE__(long) __PIVECTOR2D_SIMPLE_TYPE__(long)
__PIVECTOR2D_SIMPLE_TYPE__(ulong) __PIVECTOR2D_SIMPLE_TYPE__(ulong)
__PIVECTOR2D_SIMPLE_TYPE__(llong) __PIVECTOR2D_SIMPLE_TYPE__(llong)
__PIVECTOR2D_SIMPLE_TYPE__(ullong) __PIVECTOR2D_SIMPLE_TYPE__(ullong)
__PIVECTOR2D_SIMPLE_TYPE__(float) __PIVECTOR2D_SIMPLE_TYPE__(float)
__PIVECTOR2D_SIMPLE_TYPE__(double) __PIVECTOR2D_SIMPLE_TYPE__(double)
__PIVECTOR2D_SIMPLE_TYPE__(ldouble) __PIVECTOR2D_SIMPLE_TYPE__(ldouble)
#endif // PIVECTOR2D_H #endif // PIVECTOR2D_H

View File

@@ -1,557 +1,557 @@
/*! \file pibase.h /*! \file pibase.h
* \brief Base types and functions * \brief Base types and functions
* *
* This file implements first layer above the system and * This file implements first layer above the system and
* declares some basic useful functions * declares some basic useful functions
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Base types and functions Base types and functions
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PIBASE_H #ifndef PIBASE_H
#define PIBASE_H #define PIBASE_H
#include "piversion.h" #include "piversion.h"
#include "piplatform.h" #include "piplatform.h"
#include "pip_export.h" #include "pip_export.h"
#include "pip_defs.h" #include "pip_defs.h"
#include "string.h" #include "string.h"
//! Meta-information section for any entity. //! Meta-information section for any entity.
//! Parsing by \a pip_cmg and can be accessed by \a PICodeInfo. //! Parsing by \a pip_cmg and can be accessed by \a PICodeInfo.
//! Contains sequence of key=value pairs, e.g. //! Contains sequence of key=value pairs, e.g.
//! PIMETA(id=12345,tag="my string") //! PIMETA(id=12345,tag="my string")
#define PIMETA(...) #define PIMETA(...)
#ifdef DOXYGEN #ifdef DOXYGEN
//! Major value of PIP version //! Major value of PIP version
# define PIP_VERSION_MAJOR # define PIP_VERSION_MAJOR
//! Minor value of PIP version //! Minor value of PIP version
# define PIP_VERSION_MINOR # define PIP_VERSION_MINOR
//! Revision value of PIP version //! Revision value of PIP version
# define PIP_VERSION_REVISION # define PIP_VERSION_REVISION
//! Suffix of PIP version //! Suffix of PIP version
# define PIP_VERSION_SUFFIX # define PIP_VERSION_SUFFIX
//! Version of PIP in hex - 0x##(Major)##(Minor)##(Revision) //! Version of PIP in hex - 0x##(Major)##(Minor)##(Revision)
# define PIP_VERSION # define PIP_VERSION
//! Macro is defined when compile-time debug is enabled //! Macro is defined when compile-time debug is enabled
# define PIP_DEBUG # define PIP_DEBUG
//! Macro is defined when host is any Windows //! Macro is defined when host is any Windows
# define WINDOWS # define WINDOWS
//! Macro is defined when host is QNX or Blackberry //! Macro is defined when host is QNX or Blackberry
# define QNX # define QNX
//! Macro is defined when host is Blackberry //! Macro is defined when host is Blackberry
# define BLACKBERRY # define BLACKBERRY
//! Macro is defined when host is FreeBSD //! Macro is defined when host is FreeBSD
# define FREE_BSD # define FREE_BSD
//! Macro is defined when host is Mac OS //! Macro is defined when host is Mac OS
# define MAC_OS # define MAC_OS
//! Macro is defined when host is Android //! Macro is defined when host is Android
# define ANDROID # define ANDROID
//! Macro is defined when host is any Linux //! Macro is defined when host is any Linux
# define LINUX # define LINUX
//! Macro is defined when compiler is GCC or MinGW //! Macro is defined when compiler is GCC or MinGW
# define CC_GCC # define CC_GCC
//! Macro is defined when PIP is decided that host is support language //! Macro is defined when PIP is decided that host is support language
# define HAS_LOCALE # define HAS_LOCALE
//! Macro is defined when compiler is Visual Studio //! Macro is defined when compiler is Visual Studio
# define CC_VC # define CC_VC
//! Macro is defined when compiler is unknown //! Macro is defined when compiler is unknown
# define CC_OTHER # define CC_OTHER
//! Macro is defined when PIP can use "rt" library for "PITimer::ThreadRT" timers implementation //! Macro is defined when PIP can use "rt" library for "PITimer::ThreadRT" timers implementation
# define PIP_TIMER_RT # define PIP_TIMER_RT
#endif #endif
#ifdef PIP_CXX11_SUPPORT #ifdef PIP_CXX11_SUPPORT
# include <functional> # include <functional>
#endif #endif
#include <cstddef> #include <cstddef>
#ifdef WINDOWS #ifdef WINDOWS
# ifdef CC_VC # ifdef CC_VC
# define SHUT_RDWR 2 # define SHUT_RDWR 2
# pragma comment(lib, "Ws2_32.lib") # pragma comment(lib, "Ws2_32.lib")
# pragma comment(lib, "Iphlpapi.lib") # pragma comment(lib, "Iphlpapi.lib")
# pragma comment(lib, "Psapi.lib") # pragma comment(lib, "Psapi.lib")
# ifdef ARCH_BITS_32 # ifdef ARCH_BITS_32
# define _X86_ # define _X86_
# else # else
# define _IA64_ # define _IA64_
# endif # endif
# else # else
# define SHUT_RDWR SD_BOTH # define SHUT_RDWR SD_BOTH
# endif # endif
typedef int socklen_t; typedef int socklen_t;
extern long long __pi_perf_freq; extern long long __pi_perf_freq;
#endif #endif
#ifdef ANDROID #ifdef ANDROID
///# define tcdrain(fd) ioctl(fd, TCSBRK, 1) ///# define tcdrain(fd) ioctl(fd, TCSBRK, 1)
//inline int wctomb(char * c, wchar_t w) {*c = ((char * )&w)[0]; return 1;} //inline int wctomb(char * c, wchar_t w) {*c = ((char * )&w)[0]; return 1;}
//inline int mbtowc(wchar_t * w, const char * c, size_t) {*w = ((wchar_t * )&c)[0]; return 1;} //inline int mbtowc(wchar_t * w, const char * c, size_t) {*w = ((wchar_t * )&c)[0]; return 1;}
#endif #endif
#ifdef MAC_OS #ifdef MAC_OS
# define environ (*_NSGetEnviron()) # define environ (*_NSGetEnviron())
typedef long time_t; typedef long time_t;
#endif #endif
#ifdef LINUX #ifdef LINUX
# define environ __environ # define environ __environ
#endif #endif
#ifdef FREE_BSD #ifdef FREE_BSD
extern char ** environ; extern char ** environ;
#endif #endif
#ifdef CC_GCC #ifdef CC_GCC
# undef DEPRECATED # undef DEPRECATED
# define DEPRECATED __attribute__((deprecated)) # define DEPRECATED __attribute__((deprecated))
# if CC_GCC_VERSION > 0x025F // > 2.95 # if CC_GCC_VERSION > 0x025F // > 2.95
# ifdef LINUX # ifdef LINUX
# define HAS_LOCALE # define HAS_LOCALE
# endif # endif
# ifdef MAC_OS # ifdef MAC_OS
# pragma GCC diagnostic ignored "-Wdeprecated-declarations" # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
# pragma GCC diagnostic ignored "-Wundefined-bool-conversion" # pragma GCC diagnostic ignored "-Wundefined-bool-conversion"
# pragma GCC diagnostic ignored "-Wc++11-extensions" # pragma GCC diagnostic ignored "-Wc++11-extensions"
# endif # endif
# endif # endif
# ifdef ANDROID # ifdef ANDROID
# pragma GCC diagnostic ignored "-Wunused-parameter" # pragma GCC diagnostic ignored "-Wunused-parameter"
# pragma GCC diagnostic ignored "-Wextra" # pragma GCC diagnostic ignored "-Wextra"
# pragma GCC diagnostic ignored "-Wc++11-extensions" # pragma GCC diagnostic ignored "-Wc++11-extensions"
# pragma GCC diagnostic ignored "-Wundefined-bool-conversion" # pragma GCC diagnostic ignored "-Wundefined-bool-conversion"
//# pragma GCC diagnostic ignored "-Wliteral-suffix" //# pragma GCC diagnostic ignored "-Wliteral-suffix"
# endif # endif
#endif #endif
#ifdef CC_VC #ifdef CC_VC
# undef DEPRECATED # undef DEPRECATED
# define DEPRECATED # define DEPRECATED
# pragma warning(disable: 4018) # pragma warning(disable: 4018)
# pragma warning(disable: 4061) # pragma warning(disable: 4061)
# pragma warning(disable: 4100) # pragma warning(disable: 4100)
# pragma warning(disable: 4239) # pragma warning(disable: 4239)
# pragma warning(disable: 4242) # pragma warning(disable: 4242)
# pragma warning(disable: 4244) # pragma warning(disable: 4244)
# pragma warning(disable: 4251) # pragma warning(disable: 4251)
# pragma warning(disable: 4365) # pragma warning(disable: 4365)
# pragma warning(disable: 4512) # pragma warning(disable: 4512)
# pragma warning(disable: 4668) # pragma warning(disable: 4668)
# pragma warning(disable: 4710) # pragma warning(disable: 4710)
# pragma warning(disable: 4800) # pragma warning(disable: 4800)
# pragma warning(disable: 4820) # pragma warning(disable: 4820)
# pragma warning(disable: 4986) # pragma warning(disable: 4986)
# pragma warning(disable: 4996) # pragma warning(disable: 4996)
# ifdef ARCH_BITS_32 # ifdef ARCH_BITS_32
typedef long ssize_t; typedef long ssize_t;
# else # else
typedef long long ssize_t; typedef long long ssize_t;
# endif # endif
#endif #endif
#ifdef CC_OTHER #ifdef CC_OTHER
# undef DEPRECATED # undef DEPRECATED
# define DEPRECATED # define DEPRECATED
#endif #endif
// Private data macros // Private data macros
#define PRIVATE_DECLARATION \ #define PRIVATE_DECLARATION \
struct __Private__; \ struct __Private__; \
friend struct __Private__; \ friend struct __Private__; \
struct __PrivateInitializer__ { \ struct __PrivateInitializer__ { \
__PrivateInitializer__(); \ __PrivateInitializer__(); \
__PrivateInitializer__(const __PrivateInitializer__ & o); \ __PrivateInitializer__(const __PrivateInitializer__ & o); \
~__PrivateInitializer__(); \ ~__PrivateInitializer__(); \
__PrivateInitializer__ & operator =(const __PrivateInitializer__ & o); \ __PrivateInitializer__ & operator =(const __PrivateInitializer__ & o); \
__Private__ * p; \ __Private__ * p; \
}; \ }; \
__PrivateInitializer__ __privateinitializer__; __PrivateInitializer__ __privateinitializer__;
#define PRIVATE_DEFINITION_START(c) \ #define PRIVATE_DEFINITION_START(c) \
struct c::__Private__ { struct c::__Private__ {
#define PRIVATE_DEFINITION_END(c) \ #define PRIVATE_DEFINITION_END(c) \
}; \ }; \
c::__PrivateInitializer__::__PrivateInitializer__() {p = new c::__Private__();} \ c::__PrivateInitializer__::__PrivateInitializer__() {p = new c::__Private__();} \
c::__PrivateInitializer__::__PrivateInitializer__(const c::__PrivateInitializer__ & ) {/*if (p) delete p;*/ p = new c::__Private__();} \ c::__PrivateInitializer__::__PrivateInitializer__(const c::__PrivateInitializer__ & ) {/*if (p) delete p;*/ p = new c::__Private__();} \
c::__PrivateInitializer__::~__PrivateInitializer__() {delete p; p = 0;} \ c::__PrivateInitializer__::~__PrivateInitializer__() {delete p; p = 0;} \
c::__PrivateInitializer__ & c::__PrivateInitializer__::operator =(const c::__PrivateInitializer__ & ) {if (p) delete p; p = new c::__Private__(); return *this;} c::__PrivateInitializer__ & c::__PrivateInitializer__::operator =(const c::__PrivateInitializer__ & ) {if (p) delete p; p = new c::__Private__(); return *this;}
#define PRIVATE (__privateinitializer__.p) #define PRIVATE (__privateinitializer__.p)
#define PRIVATEWB __privateinitializer__.p #define PRIVATEWB __privateinitializer__.p
#define NO_COPY_CLASS(name) \ #define NO_COPY_CLASS(name) \
explicit name(const name & ); \ explicit name(const name & ); \
void operator =(const name & ); void operator =(const name & );
#ifdef FREERTOS #ifdef FREERTOS
# define PIP_MIN_MSLEEP 10. # define PIP_MIN_MSLEEP 10.
#else #else
# define PIP_MIN_MSLEEP 1. # define PIP_MIN_MSLEEP 1.
#endif #endif
//! Macro used for infinite loop //! Macro used for infinite loop
#define FOREVER for (;;) #define FOREVER for (;;)
//! Macro used for infinite wait //! Macro used for infinite wait
#define FOREVER_WAIT FOREVER msleep(PIP_MIN_MSLEEP); #define FOREVER_WAIT FOREVER msleep(PIP_MIN_MSLEEP);
//! Macro used for infinite wait //! Macro used for infinite wait
#define WAIT_FOREVER FOREVER msleep(PIP_MIN_MSLEEP); #define WAIT_FOREVER FOREVER msleep(PIP_MIN_MSLEEP);
//! global variable enabling output to piCout, default is true //! global variable enabling output to piCout, default is true
extern PIP_EXPORT bool piDebug; extern PIP_EXPORT bool piDebug;
//! global variable that set minimum real update interval //! global variable that set minimum real update interval
//! for function PIInit::mountInfo(), default is 10000 ms //! for function PIInit::mountInfo(), default is 10000 ms
extern PIP_EXPORT double piMountInfoRefreshIntervalMs; extern PIP_EXPORT double piMountInfoRefreshIntervalMs;
typedef unsigned char uchar; typedef unsigned char uchar;
typedef unsigned short ushort; typedef unsigned short ushort;
typedef unsigned int uint; typedef unsigned int uint;
typedef unsigned long ulong; typedef unsigned long ulong;
typedef unsigned long long ullong; typedef unsigned long long ullong;
typedef long long llong; typedef long long llong;
typedef long double ldouble; typedef long double ldouble;
/*! \brief Templated function for swap two values /*! \brief Templated function for swap two values
* \details Example:\n \snippet piincludes.cpp swap */ * \details Example:\n \snippet piincludes.cpp swap */
template<typename T> inline void piSwap(T & f, T & s) {T t = f; f = s; s = t;} template<typename T> inline void piSwap(T & f, T & s) {T t = f; f = s; s = t;}
/*! \brief Templated function for swap two values without "=" /*! \brief Templated function for swap two values without "="
* \details Example:\n \snippet piincludes.cpp swapBinary */ * \details Example:\n \snippet piincludes.cpp swapBinary */
template<typename T> inline void piSwapBinary(T & f, T & s) { template<typename T> inline void piSwapBinary(T & f, T & s) {
if ((size_t*)&f == (size_t*)&s) return; if ((size_t*)&f == (size_t*)&s) return;
size_t j = (sizeof(T) / sizeof(size_t)), bs = j * sizeof(size_t), bf = sizeof(T); size_t j = (sizeof(T) / sizeof(size_t)), bs = j * sizeof(size_t), bf = sizeof(T);
size_t i = 0; size_t i = 0;
for (i = 0; i < j; ++i) { for (i = 0; i < j; ++i) {
((size_t*)(&f))[i] ^= ((size_t*)(&s))[i]; ((size_t*)(&f))[i] ^= ((size_t*)(&s))[i];
((size_t*)(&s))[i] ^= ((size_t*)(&f))[i]; ((size_t*)(&s))[i] ^= ((size_t*)(&f))[i];
((size_t*)(&f))[i] ^= ((size_t*)(&s))[i]; ((size_t*)(&f))[i] ^= ((size_t*)(&s))[i];
} }
for (i = bs; i < bf; ++i) { for (i = bs; i < bf; ++i) {
((uchar*)(&f))[i] ^= ((uchar*)(&s))[i]; ((uchar*)(&f))[i] ^= ((uchar*)(&s))[i];
((uchar*)(&s))[i] ^= ((uchar*)(&f))[i]; ((uchar*)(&s))[i] ^= ((uchar*)(&f))[i];
((uchar*)(&f))[i] ^= ((uchar*)(&s))[i]; ((uchar*)(&f))[i] ^= ((uchar*)(&s))[i];
} }
} }
template<> inline void piSwapBinary(const void *& f, const void *& s) { template<> inline void piSwapBinary(const void *& f, const void *& s) {
if ((size_t*)f == (size_t*)s) return; if ((size_t*)f == (size_t*)s) return;
size_t j = (sizeof(void *) / sizeof(size_t)), bs = j * sizeof(size_t), bf = sizeof(void *); size_t j = (sizeof(void *) / sizeof(size_t)), bs = j * sizeof(size_t), bf = sizeof(void *);
size_t i = 0; size_t i = 0;
void * pf = const_cast<void*>(f), * ps = const_cast<void*>(s); void * pf = const_cast<void*>(f), * ps = const_cast<void*>(s);
for (i = 0; i < j; ++i) { for (i = 0; i < j; ++i) {
((size_t*)(&pf))[i] ^= ((size_t*)(&ps))[i]; ((size_t*)(&pf))[i] ^= ((size_t*)(&ps))[i];
((size_t*)(&ps))[i] ^= ((size_t*)(&pf))[i]; ((size_t*)(&ps))[i] ^= ((size_t*)(&pf))[i];
((size_t*)(&pf))[i] ^= ((size_t*)(&ps))[i]; ((size_t*)(&pf))[i] ^= ((size_t*)(&ps))[i];
} }
for (i = bs; i < bf; ++i) { for (i = bs; i < bf; ++i) {
((uchar*)(&pf))[i] ^= ((uchar*)(&ps))[i]; ((uchar*)(&pf))[i] ^= ((uchar*)(&ps))[i];
((uchar*)(&ps))[i] ^= ((uchar*)(&pf))[i]; ((uchar*)(&ps))[i] ^= ((uchar*)(&pf))[i];
((uchar*)(&pf))[i] ^= ((uchar*)(&ps))[i]; ((uchar*)(&pf))[i] ^= ((uchar*)(&ps))[i];
} }
} }
/*! \brief Function for compare two values without "=" by raw content /*! \brief Function for compare two values without "=" by raw content
* \details Example:\n \snippet piincludes.cpp compareBinary */ * \details Example:\n \snippet piincludes.cpp compareBinary */
inline bool piCompareBinary(const void * f, const void * s, size_t size) { inline bool piCompareBinary(const void * f, const void * s, size_t size) {
for (size_t i = 0; i < size; ++i) for (size_t i = 0; i < size; ++i)
if (((const uchar*)f)[i] != ((const uchar*)s)[i]) if (((const uchar*)f)[i] != ((const uchar*)s)[i])
return false; return false;
return true; return true;
} }
/*! \brief Templated function return round of float falue /*! \brief Templated function return round of float falue
* \details Round is the nearest integer value \n * \details Round is the nearest integer value \n
* There are some macros: * There are some macros:
* - \c piRoundf for "float" * - \c piRoundf for "float"
* - \c piRoundd for "double" * - \c piRoundd for "double"
* *
* Example: * Example:
* \snippet piincludes.cpp round */ * \snippet piincludes.cpp round */
template<typename T> inline int piRound(const T & v) {return int(v >= T(0.) ? v + T(0.5) : v - T(0.5));} template<typename T> inline int piRound(const T & v) {return int(v >= T(0.) ? v + T(0.5) : v - T(0.5));}
/*! \brief Templated function return floor of float falue /*! \brief Templated function return floor of float falue
* \details Floor is the largest integer that is not greater than value \n * \details Floor is the largest integer that is not greater than value \n
* There are some macros: * There are some macros:
* - \c piFloorf for "float" * - \c piFloorf for "float"
* - \c piFloord for "double" * - \c piFloord for "double"
* *
* Example: * Example:
* \snippet piincludes.cpp floor */ * \snippet piincludes.cpp floor */
template<typename T> inline int piFloor(const T & v) {return v < T(0) ? int(v) - 1 : int(v);} template<typename T> inline int piFloor(const T & v) {return v < T(0) ? int(v) - 1 : int(v);}
/*! \brief Templated function return ceil of float falue /*! \brief Templated function return ceil of float falue
* \details Ceil is the smallest integer that is not less than value \n * \details Ceil is the smallest integer that is not less than value \n
* There are some macros: * There are some macros:
* - \c piCeilf for "float" * - \c piCeilf for "float"
* - \c piCeild for "double" * - \c piCeild for "double"
* *
* Example: * Example:
* \snippet piincludes.cpp ceil */ * \snippet piincludes.cpp ceil */
template<typename T> inline int piCeil(const T & v) {return v < T(0) ? int(v) : int(v) + 1;} template<typename T> inline int piCeil(const T & v) {return v < T(0) ? int(v) : int(v) + 1;}
/*! \brief Templated function return absolute of numeric falue /*! \brief Templated function return absolute of numeric falue
* \details Absolute is the positive or equal 0 value \n * \details Absolute is the positive or equal 0 value \n
* There are some macros: * There are some macros:
* - \c piAbss for "short" * - \c piAbss for "short"
* - \c piAbsi for "int" * - \c piAbsi for "int"
* - \c piAbsl for "long" * - \c piAbsl for "long"
* - \c piAbsll for "llong" * - \c piAbsll for "llong"
* - \c piAbsf for "float" * - \c piAbsf for "float"
* - \c piAbsd for "double" * - \c piAbsd for "double"
* *
* Example: * Example:
* \snippet piincludes.cpp abs */ * \snippet piincludes.cpp abs */
template<typename T> inline T piAbs(const T & v) {return (v >= T(0) ? v : -v);} template<typename T> inline T piAbs(const T & v) {return (v >= T(0) ? v : -v);}
/*! \brief Templated function return minimum of two values /*! \brief Templated function return minimum of two values
* \details There are some macros: * \details There are some macros:
* - \c piMins for "short" * - \c piMins for "short"
* - \c piMini for "int" * - \c piMini for "int"
* - \c piMinl for "long" * - \c piMinl for "long"
* - \c piMinll for "llong" * - \c piMinll for "llong"
* - \c piMinf for "float" * - \c piMinf for "float"
* - \c piMind for "double" * - \c piMind for "double"
* *
* Example: * Example:
* \snippet piincludes.cpp min2 */ * \snippet piincludes.cpp min2 */
template<typename T> inline T piMin(const T & f, const T & s) {return ((f > s) ? s : f);} template<typename T> inline T piMin(const T & f, const T & s) {return ((f > s) ? s : f);}
/*! \brief Templated function return minimum of tree values /*! \brief Templated function return minimum of tree values
* \details There are some macros: * \details There are some macros:
* - \c piMins for "short" * - \c piMins for "short"
* - \c piMini for "int" * - \c piMini for "int"
* - \c piMinl for "long" * - \c piMinl for "long"
* - \c piMinll for "llong" * - \c piMinll for "llong"
* - \c piMinf for "float" * - \c piMinf for "float"
* - \c piMind for "double" * - \c piMind for "double"
* *
* Example: * Example:
* \snippet piincludes.cpp min3 */ * \snippet piincludes.cpp min3 */
template<typename T> inline T piMin(const T & f, const T & s, const T & t) {return ((f < s && f < t) ? f : ((s < t) ? s : t));} template<typename T> inline T piMin(const T & f, const T & s, const T & t) {return ((f < s && f < t) ? f : ((s < t) ? s : t));}
/*! \brief Templated function return maximum of two values /*! \brief Templated function return maximum of two values
* \details There are some macros: * \details There are some macros:
* - \c piMaxs for "short" * - \c piMaxs for "short"
* - \c piMaxi for "int" * - \c piMaxi for "int"
* - \c piMaxl for "long" * - \c piMaxl for "long"
* - \c piMaxll for "llong" * - \c piMaxll for "llong"
* - \c piMaxf for "float" * - \c piMaxf for "float"
* - \c piMaxd for "double" * - \c piMaxd for "double"
* *
* Example: * Example:
* \snippet piincludes.cpp max2 */ * \snippet piincludes.cpp max2 */
template<typename T> inline T piMax(const T & f, const T & s) {return ((f < s) ? s : f);} template<typename T> inline T piMax(const T & f, const T & s) {return ((f < s) ? s : f);}
/*! \brief Templated function return maximum of tree values /*! \brief Templated function return maximum of tree values
* \details There are some macros: * \details There are some macros:
* - \c piMaxs for "short" * - \c piMaxs for "short"
* - \c piMaxi for "int" * - \c piMaxi for "int"
* - \c piMaxl for "long" * - \c piMaxl for "long"
* - \c piMaxll for "llong" * - \c piMaxll for "llong"
* - \c piMaxf for "float" * - \c piMaxf for "float"
* - \c piMaxd for "double" * - \c piMaxd for "double"
* *
* Example: * Example:
* \snippet piincludes.cpp max3 */ * \snippet piincludes.cpp max3 */
template<typename T> inline T piMax(const T & f, const T & s, const T & t) {return ((f > s && f > t) ? f : ((s > t) ? s : t));} template<typename T> inline T piMax(const T & f, const T & s, const T & t) {return ((f > s && f > t) ? f : ((s > t) ? s : t));}
/*! \brief Templated function return clamped value /*! \brief Templated function return clamped value
* \details Clamped is the not greater than "max" and not lesser than "min" value \n * \details Clamped is the not greater than "max" and not lesser than "min" value \n
* There are some macros: * There are some macros:
* - \c piClamps for "short" * - \c piClamps for "short"
* - \c piClampi for "int" * - \c piClampi for "int"
* - \c piClampl for "long" * - \c piClampl for "long"
* - \c piClampll for "llong" * - \c piClampll for "llong"
* - \c piClampf for "float" * - \c piClampf for "float"
* - \c piClampd for "double" * - \c piClampd for "double"
* *
* Example: * Example:
* \snippet piincludes.cpp clamp */ * \snippet piincludes.cpp clamp */
template<typename T> inline T piClamp(const T & v, const T & min, const T & max) {return (v > max ? max : (v < min ? min : v));} template<typename T> inline T piClamp(const T & v, const T & min, const T & max) {return (v > max ? max : (v < min ? min : v));}
/// Function inverse byte order in memory block /// Function inverse byte order in memory block
inline void piLetobe(void * data, int size) { inline void piLetobe(void * data, int size) {
for (int i = 0; i < size / 2; i++) for (int i = 0; i < size / 2; i++)
piSwap<uchar>(((uchar*)data)[size - i - 1], ((uchar*)data)[i]); piSwap<uchar>(((uchar*)data)[size - i - 1], ((uchar*)data)[i]);
} }
/// \brief Templated function that inverse byte order of value "v" /// \brief Templated function that inverse byte order of value "v"
template<typename T> inline void piLetobe(T * v) {piLetobe(v, sizeof(T));} template<typename T> inline void piLetobe(T * v) {piLetobe(v, sizeof(T));}
/*! \brief Templated function that returns "v" with inversed byte order /*! \brief Templated function that returns "v" with inversed byte order
* \details This function used to convert values between little and big endian \n * \details This function used to convert values between little and big endian \n
* There are some macros: * There are some macros:
* - \c piLetobes for "ushort" * - \c piLetobes for "ushort"
* - \c piLetobei for "uint" * - \c piLetobei for "uint"
* - \c piLetobel for "ulong" * - \c piLetobel for "ulong"
* - \c piLetobell for "ullong" * - \c piLetobell for "ullong"
* *
* Example: * Example:
* \snippet piincludes.cpp letobe */ * \snippet piincludes.cpp letobe */
template<typename T> inline T piLetobe(const T & v) {T tv(v); piLetobe(&tv, sizeof(T)); return tv;} template<typename T> inline T piLetobe(const T & v) {T tv(v); piLetobe(&tv, sizeof(T)); return tv;}
// specialization // specialization
template<> inline ushort piLetobe(const ushort & v) {return (v << 8) | (v >> 8);} template<> inline ushort piLetobe(const ushort & v) {return (v << 8) | (v >> 8);}
template<> inline uint piLetobe(const uint & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);} template<> inline uint piLetobe(const uint & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);}
template<> inline float piLetobe(const float & v) { template<> inline float piLetobe(const float & v) {
union _pletobe_f { union _pletobe_f {
_pletobe_f(const float &f_) {f = f_;} _pletobe_f(const float &f_) {f = f_;}
float f; float f;
uint v; uint v;
}; };
_pletobe_f a(v); _pletobe_f a(v);
a.v = (a.v >> 24) | ((a.v >> 8) & 0xFF00) | ((a.v << 8) & 0xFF0000) | ((a.v << 24) & 0xFF000000); a.v = (a.v >> 24) | ((a.v >> 8) & 0xFF00) | ((a.v << 8) & 0xFF0000) | ((a.v << 24) & 0xFF000000);
return a.f; return a.f;
} }
DEPRECATED inline ushort letobe_s(const ushort & v) {return (v << 8) | (v >> 8);} DEPRECATED inline ushort letobe_s(const ushort & v) {return (v << 8) | (v >> 8);}
DEPRECATED inline uint letobe_i(const uint & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);} DEPRECATED inline uint letobe_i(const uint & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);}
#ifdef DOXYGEN #ifdef DOXYGEN
/// \deprecated \brief Use \a piLetobe() instead of this function /// \deprecated \brief Use \a piLetobe() instead of this function
ushort letobe_s(ushort v) {return (v << 8) | (v >> 8);} ushort letobe_s(ushort v) {return (v << 8) | (v >> 8);}
/// \deprecated \brief Use \a piLetobe() instead of this function /// \deprecated \brief Use \a piLetobe() instead of this function
uint letobe_i(uint v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);} uint letobe_i(uint v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);}
#endif #endif
/// \brief Generic hash function, impements murmur3/32 algorithm /// \brief Generic hash function, impements murmur3/32 algorithm
inline uint piHashData(const uchar * data, uint len, uint seed = 0) { inline uint piHashData(const uchar * data, uint len, uint seed = 0) {
if (!data || len <= 0) return 0u; if (!data || len <= 0) return 0u;
uint h = seed; uint h = seed;
if (len > 3) { if (len > 3) {
uint i = len >> 2; uint i = len >> 2;
do { do {
uint k; uint k;
memcpy(&k, data, sizeof(uint)); memcpy(&k, data, sizeof(uint));
data += sizeof(uint); data += sizeof(uint);
k *= 0xcc9e2d51; k *= 0xcc9e2d51;
k = (k << 15) | (k >> 17); k = (k << 15) | (k >> 17);
k *= 0x1b873593; k *= 0x1b873593;
h ^= k; h ^= k;
h = (h << 13) | (h >> 19); h = (h << 13) | (h >> 19);
h = h * 5 + 0xe6546b64; h = h * 5 + 0xe6546b64;
} while (--i); } while (--i);
} }
if (len & 3) { if (len & 3) {
uint i = len & 3; uint i = len & 3;
uint k = 0; uint k = 0;
do { do {
k <<= 8; k <<= 8;
k |= data[i - 1]; k |= data[i - 1];
} while (--i); } while (--i);
k *= 0xcc9e2d51; k *= 0xcc9e2d51;
k = (k << 15) | (k >> 17); k = (k << 15) | (k >> 17);
k *= 0x1b873593; k *= 0x1b873593;
h ^= k; h ^= k;
} }
h ^= len; h ^= len;
h ^= h >> 16; h ^= h >> 16;
h *= 0x85ebca6b; h *= 0x85ebca6b;
h ^= h >> 13; h ^= h >> 13;
h *= 0xc2b2ae35; h *= 0xc2b2ae35;
h ^= h >> 16; h ^= h >> 16;
return h; return h;
} }
template<typename T> inline uint piHash(const T & v) { template<typename T> inline uint piHash(const T & v) {
return 0; return 0;
} }
template<> inline uint piHash(const char & v) {return (uint)v;} template<> inline uint piHash(const char & v) {return (uint)v;}
template<> inline uint piHash(const uchar & v) {return (uint)v;} template<> inline uint piHash(const uchar & v) {return (uint)v;}
template<> inline uint piHash(const short & v) {return (uint)v;} template<> inline uint piHash(const short & v) {return (uint)v;}
template<> inline uint piHash(const ushort & v) {return (uint)v;} template<> inline uint piHash(const ushort & v) {return (uint)v;}
template<> inline uint piHash(const int & v) {return (uint)v;} template<> inline uint piHash(const int & v) {return (uint)v;}
template<> inline uint piHash(const uint & v) {return (uint)v;} template<> inline uint piHash(const uint & v) {return (uint)v;}
template<> inline uint piHash(const llong & v) {return piHashData((const uchar *)&v, sizeof(v));} template<> inline uint piHash(const llong & v) {return piHashData((const uchar *)&v, sizeof(v));}
template<> inline uint piHash(const ullong & v) {return piHashData((const uchar *)&v, sizeof(v));} template<> inline uint piHash(const ullong & v) {return piHashData((const uchar *)&v, sizeof(v));}
template<> inline uint piHash(const float & v) {return (uint)v;} template<> inline uint piHash(const float & v) {return (uint)v;}
template<> inline uint piHash(const double & v) {return piHashData((const uchar *)&v, sizeof(v));} template<> inline uint piHash(const double & v) {return piHashData((const uchar *)&v, sizeof(v));}
template<> inline uint piHash(const ldouble & v) {return piHashData((const uchar *)&v, sizeof(v));} template<> inline uint piHash(const ldouble & v) {return piHashData((const uchar *)&v, sizeof(v));}
#define piRoundf piRound<float> #define piRoundf piRound<float>
#define piRoundd piRound<double> #define piRoundd piRound<double>
#define piFloorf piFloor<float> #define piFloorf piFloor<float>
#define piFloord piFloor<double> #define piFloord piFloor<double>
#define piCeilf piCeil<float> #define piCeilf piCeil<float>
#define piCeild piCeil<double> #define piCeild piCeil<double>
#define piAbss piAbs<short> #define piAbss piAbs<short>
#define piAbsi piAbs<int> #define piAbsi piAbs<int>
#define piAbsl piAbs<long> #define piAbsl piAbs<long>
#define piAbsll piAbs<llong> #define piAbsll piAbs<llong>
#define piAbsf piAbs<float> #define piAbsf piAbs<float>
#define piAbsd piAbs<double> #define piAbsd piAbs<double>
#define piMins piMin<short> #define piMins piMin<short>
#define piMini piMin<int> #define piMini piMin<int>
#define piMinl piMin<long> #define piMinl piMin<long>
#define piMinll piMin<llong> #define piMinll piMin<llong>
#define piMinf piMin<float> #define piMinf piMin<float>
#define piMind piMin<double> #define piMind piMin<double>
#define piMaxs piMax<short> #define piMaxs piMax<short>
#define piMaxi piMax<int> #define piMaxi piMax<int>
#define piMaxl piMax<long> #define piMaxl piMax<long>
#define piMaxll piMax<llong> #define piMaxll piMax<llong>
#define piMaxf piMax<float> #define piMaxf piMax<float>
#define piMaxd piMax<double> #define piMaxd piMax<double>
#define piClamps piClamp<short> #define piClamps piClamp<short>
#define piClampi piClamp<int> #define piClampi piClamp<int>
#define piClampl piClamp<long> #define piClampl piClamp<long>
#define piClampll piClamp<llong> #define piClampll piClamp<llong>
#define piClampf piClamp<float> #define piClampf piClamp<float>
#define piClampd piClamp<double> #define piClampd piClamp<double>
#define piLetobes piLetobe<ushort> #define piLetobes piLetobe<ushort>
#define piLetobei piLetobe<uint> #define piLetobei piLetobe<uint>
#define piLetobel piLetobe<ulong> #define piLetobel piLetobe<ulong>
#define piLetobell piLetobe<ullong> #define piLetobell piLetobe<ullong>
#define piLetobef piLetobe<float> #define piLetobef piLetobe<float>
#endif // PIBASE_H #endif // PIBASE_H

View File

@@ -1,44 +1,44 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Bit array Bit array
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "pibitarray.h" #include "pibitarray.h"
#include "picout.h" #include "picout.h"
PICout operator <<(PICout s, const PIBitArray & ba) { PICout operator <<(PICout s, const PIBitArray & ba) {
s.space(); s.space();
s.setControl(0, true); s.setControl(0, true);
for (uint i = 0; i < ba.bitSize(); ++i) { for (uint i = 0; i < ba.bitSize(); ++i) {
s << int(ba[i]); s << int(ba[i]);
if (i % 8 == 7) s << ' '; if (i % 8 == 7) s << ' ';
} }
s.restoreControl(); s.restoreControl();
return s; return s;
} }
#ifdef PIP_STD_IOSTREAM #ifdef PIP_STD_IOSTREAM
std::ostream &operator <<(std::ostream & s, const PIBitArray & ba) { std::ostream &operator <<(std::ostream & s, const PIBitArray & ba) {
for (uint i = 0; i < ba.bitSize(); ++i) { for (uint i = 0; i < ba.bitSize(); ++i) {
s << ba[i]; s << ba[i];
if (i % 8 == 7) s << ' '; if (i % 8 == 7) s << ' ';
} }
return s; return s;
} }
#endif #endif

View File

View File

View File

0
src_main/core/pichar.h → lib/main/core/pichar.h Executable file → Normal file
View File

0
src_main/core/picli.cpp → lib/main/core/picli.cpp Executable file → Normal file
View File

0
src_main/core/picli.h → lib/main/core/picli.h Executable file → Normal file
View File

View File

View File

View File

@@ -1,301 +1,301 @@
/*! \file picout.h /*! \file picout.h
* \brief Universal output to console class * \brief Universal output to console class
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Universal output to console class Universal output to console class
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PICOUT_H #ifndef PICOUT_H
#define PICOUT_H #define PICOUT_H
#include "piincludes.h" #include "piincludes.h"
#ifdef DOXYGEN #ifdef DOXYGEN
//! \brief Macro used for conditional (piDebug) output to PICout //! \brief Macro used for conditional (piDebug) output to PICout
# define piCout # define piCout
//! \relatesalso PIObject \brief Macro used for conditional (piDebug and PIObject::debug()) output to PICout for subclasses of PIObject //! \relatesalso PIObject \brief Macro used for conditional (piDebug and PIObject::debug()) output to PICout for subclasses of PIObject
# define piCoutObj # define piCoutObj
#else #else
# define piCout PICout(piDebug) # define piCout PICout(piDebug)
# define piCoutObj PICout(piDebug && debug()) << (PIStringAscii("[") + className() + PIStringAscii(" \"") + name() + PIStringAscii("\"]")) # define piCoutObj PICout(piDebug && debug()) << (PIStringAscii("[") + className() + PIStringAscii(" \"") + name() + PIStringAscii("\"]"))
#endif #endif
class PIObject; class PIObject;
//! \brief Namespace contains enums controlled PICout //! \brief Namespace contains enums controlled PICout
namespace PICoutManipulators { namespace PICoutManipulators {
//! \brief Enum contains special characters //! \brief Enum contains special characters
enum PIP_EXPORT PICoutSpecialChar { enum PIP_EXPORT PICoutSpecialChar {
Null /*! Null-character, '\\0' */, Null /*! Null-character, '\\0' */,
NewLine /*! New line character, '\\n' */, NewLine /*! New line character, '\\n' */,
Tab /*! Tab character, '\\t' */, Tab /*! Tab character, '\\t' */,
Esc /*! Escape character, '\\e' */, Esc /*! Escape character, '\\e' */,
Quote /*! Quote character, '"' */ Quote /*! Quote character, '"' */
}; };
//! \brief Enum contains immediate action //! \brief Enum contains immediate action
enum PIP_EXPORT PICoutAction { enum PIP_EXPORT PICoutAction {
Flush /*! Flush the output */, Flush /*! Flush the output */,
Backspace /*! Remove last symbol */, Backspace /*! Remove last symbol */,
ShowCursor /*! Show cursor */, ShowCursor /*! Show cursor */,
HideCursor /*! Hide cursor */, HideCursor /*! Hide cursor */,
ClearLine /*! Clear current line */, ClearLine /*! Clear current line */,
ClearScreen /*! Clear the screen */, ClearScreen /*! Clear the screen */,
SaveContol /*! Save control flags, equivalent to \a saveControl() */, SaveContol /*! Save control flags, equivalent to \a saveControl() */,
RestoreControl /*! Restore control flags, equivalent to \a restoreControl() */ RestoreControl /*! Restore control flags, equivalent to \a restoreControl() */
}; };
//! \brief Enum contains control of PICout //! \brief Enum contains control of PICout
enum PIP_EXPORT PICoutControl { enum PIP_EXPORT PICoutControl {
AddNone /*! No controls */ = 0x0, AddNone /*! No controls */ = 0x0,
AddSpaces /*! Spaces will be appear after each output */ = 0x1, AddSpaces /*! Spaces will be appear after each output */ = 0x1,
AddNewLine /*! New line will be appear after all output */ = 0x2, AddNewLine /*! New line will be appear after all output */ = 0x2,
AddQuotes /*! Each string will be quoted */ = 0x4, AddQuotes /*! Each string will be quoted */ = 0x4,
DefaultControls /*! Default controls */ = AddSpaces | AddNewLine, DefaultControls /*! Default controls */ = AddSpaces | AddNewLine,
AddAll /*! All controls */ = 0xFF, AddAll /*! All controls */ = 0xFF,
NoLock /*! Don`t use mutex for output */ = 0x100, NoLock /*! Don`t use mutex for output */ = 0x100,
}; };
//! \brief Enum contains output format //! \brief Enum contains output format
enum PIP_EXPORT PICoutFormat { enum PIP_EXPORT PICoutFormat {
Bin /*! Binary representation of integers */ = 0x01, Bin /*! Binary representation of integers */ = 0x01,
Oct /*! Octal representation of integers */ = 0x02, Oct /*! Octal representation of integers */ = 0x02,
Dec /*! Decimal representation of integers */ = 0x04, Dec /*! Decimal representation of integers */ = 0x04,
Hex /*! Hexadecimal representation of integers */ = 0x08, Hex /*! Hexadecimal representation of integers */ = 0x08,
Bold /*! Bold */ = 0x10, Bold /*! Bold */ = 0x10,
Faint /*! */ = 0x20, Faint /*! */ = 0x20,
Italic /*! */ = 0x40, Italic /*! */ = 0x40,
Underline /*! Underline */ = 0x80, Underline /*! Underline */ = 0x80,
Blink /*! Blink */ = 0x100, Blink /*! Blink */ = 0x100,
Black /*! Black font */ = 0x400, Black /*! Black font */ = 0x400,
Red /*! Red font */ = 0x800, Red /*! Red font */ = 0x800,
Green /*! Green font */ = 0x1000, Green /*! Green font */ = 0x1000,
Blue /*! Blue font */ = 0x2000, Blue /*! Blue font */ = 0x2000,
Yellow /*! Yellow font */ = 0x4000, Yellow /*! Yellow font */ = 0x4000,
Magenta /*! Magenta font */ = 0x8000, Magenta /*! Magenta font */ = 0x8000,
Cyan /*! Cyan font */ = 0x10000, Cyan /*! Cyan font */ = 0x10000,
White /*! White font */ = 0x20000, White /*! White font */ = 0x20000,
BackBlack /*! Black background */ = 0x40000, BackBlack /*! Black background */ = 0x40000,
BackRed /*! Red background */ = 0x80000, BackRed /*! Red background */ = 0x80000,
BackGreen /*! Green background */ = 0x100000, BackGreen /*! Green background */ = 0x100000,
BackBlue /*! Blue background */ = 0x200000, BackBlue /*! Blue background */ = 0x200000,
BackYellow /*! Yellow background */ = 0x400000, BackYellow /*! Yellow background */ = 0x400000,
BackMagenta /*! Magenta background */ = 0x800000, BackMagenta /*! Magenta background */ = 0x800000,
BackCyan /*! Cyan background */ = 0x1000000, BackCyan /*! Cyan background */ = 0x1000000,
BackWhite /*! White background */ = 0x2000000, BackWhite /*! White background */ = 0x2000000,
Default /*! Default format */ = 0x4000000 Default /*! Default format */ = 0x4000000
}; };
typedef PIFlags<PICoutControl> PICoutControls; typedef PIFlags<PICoutControl> PICoutControls;
} }
class PIP_EXPORT PICout { class PIP_EXPORT PICout {
public: public:
//! Default constructor with default features (AddSpaces and AddNewLine) //! Default constructor with default features (AddSpaces and AddNewLine)
PICout(PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::DefaultControls); PICout(PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::DefaultControls);
PICout(PICoutManipulators::PICoutControl control = PICoutManipulators::DefaultControls); PICout(PICoutManipulators::PICoutControl control = PICoutManipulators::DefaultControls);
//! Construct with default features (AddSpaces and AddNewLine), but if \"active\" is false does nothing //! Construct with default features (AddSpaces and AddNewLine), but if \"active\" is false does nothing
PICout(bool active); PICout(bool active);
//! Construct with external buffer and id "id". See \a Notifier for details //! Construct with external buffer and id "id". See \a Notifier for details
PICout(PIString * buffer, int id = 0, PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::AddSpaces | PICoutManipulators::AddNewLine); PICout(PIString * buffer, int id = 0, PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::AddSpaces | PICoutManipulators::AddNewLine);
PICout(const PICout & other); PICout(const PICout & other);
~PICout(); ~PICout();
class Notifier { class Notifier {
public: public:
static Notifier * instance(); static Notifier * instance();
static PIObject * object(); static PIObject * object();
private: private:
Notifier(); Notifier();
PIObject * o; PIObject * o;
}; };
//! \brief Enum contains output devices of PICout //! \brief Enum contains output devices of PICout
enum OutputDevice { enum OutputDevice {
NoDevices /** PICout is disabled */ = 0x0, NoDevices /** PICout is disabled */ = 0x0,
StdOut /** Standard console output */ = 0x1, StdOut /** Standard console output */ = 0x1,
Buffer /** Internal buffer */ = 0x2, Buffer /** Internal buffer */ = 0x2,
AllDevices /** All */ = 0xFFFF, AllDevices /** All */ = 0xFFFF,
}; };
typedef PIFlags<OutputDevice> OutputDevices; typedef PIFlags<OutputDevice> OutputDevices;
//! Output operator for strings with <tt>"const char * "</tt> type //! Output operator for strings with <tt>"const char * "</tt> type
PICout operator <<(const char * v); PICout operator <<(const char * v);
//! Output operator for strings with <tt>"std::string"</tt> type //! Output operator for strings with <tt>"std::string"</tt> type
//PICout operator <<(const std::string & v); //PICout operator <<(const std::string & v);
//! Output operator for boolean values //! Output operator for boolean values
PICout operator <<(const bool v); PICout operator <<(const bool v);
//! Output operator for <tt>"char"</tt> values //! Output operator for <tt>"char"</tt> values
PICout operator <<(const char v); PICout operator <<(const char v);
//! Output operator for <tt>"unsigned char"</tt> values //! Output operator for <tt>"unsigned char"</tt> values
PICout operator <<(const uchar v); PICout operator <<(const uchar v);
//! Output operator for <tt>"short"</tt> values //! Output operator for <tt>"short"</tt> values
PICout operator <<(const short v); PICout operator <<(const short v);
//! Output operator for <tt>"unsigned short"</tt> values //! Output operator for <tt>"unsigned short"</tt> values
PICout operator <<(const ushort v); PICout operator <<(const ushort v);
//! Output operator for <tt>"int"</tt> values //! Output operator for <tt>"int"</tt> values
PICout operator <<(const int v); PICout operator <<(const int v);
//! Output operator for <tt>"unsigned int"</tt> values //! Output operator for <tt>"unsigned int"</tt> values
PICout operator <<(const uint v); PICout operator <<(const uint v);
//! Output operator for <tt>"long"</tt> values //! Output operator for <tt>"long"</tt> values
PICout operator <<(const long v); PICout operator <<(const long v);
//! Output operator for <tt>"unsigned long"</tt> values //! Output operator for <tt>"unsigned long"</tt> values
PICout operator <<(const ulong v); PICout operator <<(const ulong v);
//! Output operator for <tt>"long long"</tt> values //! Output operator for <tt>"long long"</tt> values
PICout operator <<(const llong v); PICout operator <<(const llong v);
//! Output operator for <tt>"unsigned long long"</tt> values //! Output operator for <tt>"unsigned long long"</tt> values
PICout operator <<(const ullong v); PICout operator <<(const ullong v);
//! Output operator for <tt>"float"</tt> values //! Output operator for <tt>"float"</tt> values
PICout operator <<(const float v); PICout operator <<(const float v);
//! Output operator for <tt>"double"</tt> values //! Output operator for <tt>"double"</tt> values
PICout operator <<(const double v); PICout operator <<(const double v);
//! Output operator for pointers //! Output operator for pointers
PICout operator <<(const void * v); PICout operator <<(const void * v);
//! Output operator for PIObject and ancestors //! Output operator for PIObject and ancestors
PICout operator <<(const PIObject * v); PICout operator <<(const PIObject * v);
//! Output operator for \a PICoutSpecialChar values //! Output operator for \a PICoutSpecialChar values
PICout operator <<(const PICoutManipulators::PICoutSpecialChar v); PICout operator <<(const PICoutManipulators::PICoutSpecialChar v);
//! Output operator for \a PIFlags<PICoutFormat> values //! Output operator for \a PIFlags<PICoutFormat> values
PICout operator <<(const PIFlags<PICoutManipulators::PICoutFormat> & v) { PICout operator <<(const PIFlags<PICoutManipulators::PICoutFormat> & v) {
if (v[PICoutManipulators::Bin]) cnb_ = 2; if (v[PICoutManipulators::Bin]) cnb_ = 2;
if (v[PICoutManipulators::Oct]) cnb_ = 8; if (v[PICoutManipulators::Oct]) cnb_ = 8;
if (v[PICoutManipulators::Dec]) cnb_ = 10; if (v[PICoutManipulators::Dec]) cnb_ = 10;
if (v[PICoutManipulators::Hex]) cnb_ = 16; if (v[PICoutManipulators::Hex]) cnb_ = 16;
if (v[PICoutManipulators::Bold]) applyFormat(PICoutManipulators::Bold); if (v[PICoutManipulators::Bold]) applyFormat(PICoutManipulators::Bold);
if (v[PICoutManipulators::Faint]) applyFormat(PICoutManipulators::Faint); if (v[PICoutManipulators::Faint]) applyFormat(PICoutManipulators::Faint);
if (v[PICoutManipulators::Italic]) applyFormat(PICoutManipulators::Italic); if (v[PICoutManipulators::Italic]) applyFormat(PICoutManipulators::Italic);
if (v[PICoutManipulators::Underline]) applyFormat(PICoutManipulators::Underline); if (v[PICoutManipulators::Underline]) applyFormat(PICoutManipulators::Underline);
if (v[PICoutManipulators::Blink]) applyFormat(PICoutManipulators::Blink); if (v[PICoutManipulators::Blink]) applyFormat(PICoutManipulators::Blink);
if (v[PICoutManipulators::Black]) applyFormat(PICoutManipulators::Black); if (v[PICoutManipulators::Black]) applyFormat(PICoutManipulators::Black);
if (v[PICoutManipulators::Red]) applyFormat(PICoutManipulators::Red); if (v[PICoutManipulators::Red]) applyFormat(PICoutManipulators::Red);
if (v[PICoutManipulators::Green]) applyFormat(PICoutManipulators::Green); if (v[PICoutManipulators::Green]) applyFormat(PICoutManipulators::Green);
if (v[PICoutManipulators::Blue]) applyFormat(PICoutManipulators::Blue); if (v[PICoutManipulators::Blue]) applyFormat(PICoutManipulators::Blue);
if (v[PICoutManipulators::Yellow]) applyFormat(PICoutManipulators::Yellow); if (v[PICoutManipulators::Yellow]) applyFormat(PICoutManipulators::Yellow);
if (v[PICoutManipulators::Magenta]) applyFormat(PICoutManipulators::Magenta); if (v[PICoutManipulators::Magenta]) applyFormat(PICoutManipulators::Magenta);
if (v[PICoutManipulators::Cyan]) applyFormat(PICoutManipulators::Cyan); if (v[PICoutManipulators::Cyan]) applyFormat(PICoutManipulators::Cyan);
if (v[PICoutManipulators::White]) applyFormat(PICoutManipulators::White); if (v[PICoutManipulators::White]) applyFormat(PICoutManipulators::White);
if (v[PICoutManipulators::BackBlack]) applyFormat(PICoutManipulators::BackBlack); if (v[PICoutManipulators::BackBlack]) applyFormat(PICoutManipulators::BackBlack);
if (v[PICoutManipulators::BackRed]) applyFormat(PICoutManipulators::BackRed); if (v[PICoutManipulators::BackRed]) applyFormat(PICoutManipulators::BackRed);
if (v[PICoutManipulators::BackGreen]) applyFormat(PICoutManipulators::BackGreen); if (v[PICoutManipulators::BackGreen]) applyFormat(PICoutManipulators::BackGreen);
if (v[PICoutManipulators::BackBlue]) applyFormat(PICoutManipulators::BackBlue); if (v[PICoutManipulators::BackBlue]) applyFormat(PICoutManipulators::BackBlue);
if (v[PICoutManipulators::BackYellow]) applyFormat(PICoutManipulators::BackYellow); if (v[PICoutManipulators::BackYellow]) applyFormat(PICoutManipulators::BackYellow);
if (v[PICoutManipulators::BackMagenta]) applyFormat(PICoutManipulators::BackMagenta); if (v[PICoutManipulators::BackMagenta]) applyFormat(PICoutManipulators::BackMagenta);
if (v[PICoutManipulators::BackCyan]) applyFormat(PICoutManipulators::BackCyan); if (v[PICoutManipulators::BackCyan]) applyFormat(PICoutManipulators::BackCyan);
if (v[PICoutManipulators::BackWhite]) applyFormat(PICoutManipulators::BackWhite); if (v[PICoutManipulators::BackWhite]) applyFormat(PICoutManipulators::BackWhite);
if (v[PICoutManipulators::Default]) applyFormat(PICoutManipulators::Default); if (v[PICoutManipulators::Default]) applyFormat(PICoutManipulators::Default);
return *this; return *this;
} }
//! Output operator for \a PICoutFormat values //! Output operator for \a PICoutFormat values
PICout operator <<(const PICoutManipulators::PICoutFormat v) { PICout operator <<(const PICoutManipulators::PICoutFormat v) {
switch (v) { switch (v) {
case PICoutManipulators::Bin: cnb_ = 2; break; case PICoutManipulators::Bin: cnb_ = 2; break;
case PICoutManipulators::Oct: cnb_ = 8; break; case PICoutManipulators::Oct: cnb_ = 8; break;
case PICoutManipulators::Dec: cnb_ = 10; break; case PICoutManipulators::Dec: cnb_ = 10; break;
case PICoutManipulators::Hex: cnb_ = 16; break; case PICoutManipulators::Hex: cnb_ = 16; break;
default: applyFormat(v); default: applyFormat(v);
}; };
return *this; return *this;
} }
//! Do some action //! Do some action
PICout operator <<(const PICoutManipulators::PICoutAction v); PICout operator <<(const PICoutManipulators::PICoutAction v);
//! Set control flag "c" is "on" state //! Set control flag "c" is "on" state
PICout & setControl(PICoutManipulators::PICoutControl c, bool on = true) {co_.setFlag(c, on); return *this;} PICout & setControl(PICoutManipulators::PICoutControl c, bool on = true) {co_.setFlag(c, on); return *this;}
//! Set control flags "c" and if "save" exec \a saveControl() //! Set control flags "c" and if "save" exec \a saveControl()
PICout & setControl(PICoutManipulators::PICoutControls c, bool save = false) {if (save) saveControl(); co_ = c; return *this;} PICout & setControl(PICoutManipulators::PICoutControls c, bool save = false) {if (save) saveControl(); co_ = c; return *this;}
//! Save control flags to internal stack \sa \a restoreControl() //! Save control flags to internal stack \sa \a restoreControl()
PICout & saveControl(); PICout & saveControl();
//! Restore control flags from internal stack \sa \a saveControl() //! Restore control flags from internal stack \sa \a saveControl()
PICout & restoreControl(); PICout & restoreControl();
/*! \brief Conditional put space character to output /*! \brief Conditional put space character to output
* \details If it is not a first output and control \a AddSpaces is set * \details If it is not a first output and control \a AddSpaces is set
* space character is put \sa \a quote(), \a newLine() */ * space character is put \sa \a quote(), \a newLine() */
PICout & space(); PICout & space();
/*! \brief Conditional put quote character to output /*! \brief Conditional put quote character to output
* \details If control \a AddQuotes is set * \details If control \a AddQuotes is set
* quote character is put \sa \a space(), \a newLine() */ * quote character is put \sa \a space(), \a newLine() */
PICout & quote(); PICout & quote();
/*! \brief Conditional put new line character to output /*! \brief Conditional put new line character to output
* \details If control \a AddNewLine is set * \details If control \a AddNewLine is set
* new line character is put \sa \a space(), \a quote() */ * new line character is put \sa \a space(), \a quote() */
PICout & newLine(); PICout & newLine();
static bool setBufferActive(bool on, bool clear = false); static bool setBufferActive(bool on, bool clear = false);
static bool isBufferActive(); static bool isBufferActive();
static PIString buffer(bool clear = false); static PIString buffer(bool clear = false);
static void clearBuffer(); static void clearBuffer();
static bool setOutputDevice(OutputDevice d, bool on = true); static bool setOutputDevice(OutputDevice d, bool on = true);
static void setOutputDevices(OutputDevices d); static void setOutputDevices(OutputDevices d);
static bool isOutputDeviceActive(OutputDevice d); static bool isOutputDeviceActive(OutputDevice d);
static PIMutex & __mutex__(); static PIMutex & __mutex__();
static PIString & __string__(); static PIString & __string__();
private: private:
void init(); void init();
void applyFormat(PICoutManipulators::PICoutFormat f); void applyFormat(PICoutManipulators::PICoutFormat f);
static OutputDevices devs; static OutputDevices devs;
PRIVATE_DECLARATION PRIVATE_DECLARATION
bool fo_, cc_, fc_, act_; bool fo_, cc_, fc_, act_;
int cnb_, attr_, id_; int cnb_, attr_, id_;
PIString * buffer_; PIString * buffer_;
PICoutManipulators::PICoutControls co_; PICoutManipulators::PICoutControls co_;
}; };
#endif // PICOUT_H #endif // PICOUT_H

View File

@@ -1,137 +1,137 @@
/*! \file piflags.h /*! \file piflags.h
* \brief General flags class * \brief General flags class
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
General flags class General flags class
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PIFLAGS_H #ifndef PIFLAGS_H
#define PIFLAGS_H #define PIFLAGS_H
#include "pip_export.h" #include "pip_export.h"
/*! \brief This class used as container for bit flags /*! \brief This class used as container for bit flags
* \details PIFlags is wrapper around \c "int". There are many * \details PIFlags is wrapper around \c "int". There are many
* bit-wise operators, native conversion to int and function * bit-wise operators, native conversion to int and function
* to test flag. \n Example: * to test flag. \n Example:
* \snippet piincludes.cpp flags * \snippet piincludes.cpp flags
*/ */
template<typename Enum> template<typename Enum>
class PIP_EXPORT PIFlags { class PIP_EXPORT PIFlags {
public: public:
//! Constructor with flags = 0 //! Constructor with flags = 0
PIFlags(): flags(0) {;} PIFlags(): flags(0) {;}
//! Constructor with flags = Enum "e" //! Constructor with flags = Enum "e"
PIFlags(Enum e): flags(e) {;} PIFlags(Enum e): flags(e) {;}
//! Constructor with flags = PIFlags "f" //! Constructor with flags = PIFlags "f"
PIFlags(const PIFlags & f): flags(f.flags) {;} PIFlags(const PIFlags & f): flags(f.flags) {;}
//! Constructor with flags = int "i" //! Constructor with flags = int "i"
PIFlags(const int i): flags(i) {;} PIFlags(const int i): flags(i) {;}
//! Set flags "f" to value "on" //! Set flags "f" to value "on"
PIFlags & setFlag(const PIFlags & f, bool on = true) {if (on) flags |= f.flags; else flags &= ~f.flags; return *this;} PIFlags & setFlag(const PIFlags & f, bool on = true) {if (on) flags |= f.flags; else flags &= ~f.flags; return *this;}
//! Set flag "e" to value "on" //! Set flag "e" to value "on"
PIFlags & setFlag(const Enum & e, bool on = true) {if (on) flags |= e; else flags &= ~e; return *this;} PIFlags & setFlag(const Enum & e, bool on = true) {if (on) flags |= e; else flags &= ~e; return *this;}
//! Set flag "i" to value "on" //! Set flag "i" to value "on"
PIFlags & setFlag(const int & i, bool on = true) {if (on) flags |= i; else flags &= ~i; return *this;} PIFlags & setFlag(const int & i, bool on = true) {if (on) flags |= i; else flags &= ~i; return *this;}
//! copy operator //! copy operator
void operator =(const PIFlags & f) {flags = f.flags;} void operator =(const PIFlags & f) {flags = f.flags;}
//! copy operator //! copy operator
void operator =(const Enum & e) {flags = e;} void operator =(const Enum & e) {flags = e;}
//! copy operator //! copy operator
void operator =(const int & i) {flags = i;} void operator =(const int & i) {flags = i;}
//! compare operator //! compare operator
bool operator ==(const PIFlags & f) {return flags == f.flags;} bool operator ==(const PIFlags & f) {return flags == f.flags;}
//! compare operator //! compare operator
bool operator ==(const Enum & e) {return flags == e;} bool operator ==(const Enum & e) {return flags == e;}
//! compare operator //! compare operator
bool operator ==(const int i) {return flags == i;} bool operator ==(const int i) {return flags == i;}
//! compare operator //! compare operator
bool operator !=(const PIFlags & f) {return flags != f.flags;} bool operator !=(const PIFlags & f) {return flags != f.flags;}
//! compare operator //! compare operator
bool operator !=(const Enum & e) {return flags != e;} bool operator !=(const Enum & e) {return flags != e;}
//! compare operator //! compare operator
bool operator !=(const int i) {return flags != i;} bool operator !=(const int i) {return flags != i;}
//! compare operator //! compare operator
bool operator >(const PIFlags & f) {return flags > f.flags;} bool operator >(const PIFlags & f) {return flags > f.flags;}
//! compare operator //! compare operator
bool operator >(const Enum & e) {return flags > e;} bool operator >(const Enum & e) {return flags > e;}
//! compare operator //! compare operator
bool operator >(const int i) {return flags > i;} bool operator >(const int i) {return flags > i;}
//! compare operator //! compare operator
bool operator <(const PIFlags & f) {return flags < f.flags;} bool operator <(const PIFlags & f) {return flags < f.flags;}
//! compare operator //! compare operator
bool operator <(const Enum & e) {return flags < e;} bool operator <(const Enum & e) {return flags < e;}
//! compare operator //! compare operator
bool operator <(const int i) {return flags < i;} bool operator <(const int i) {return flags < i;}
//! compare operator //! compare operator
bool operator >=(const PIFlags & f) {return flags >= f.flags;} bool operator >=(const PIFlags & f) {return flags >= f.flags;}
//! compare operator //! compare operator
bool operator >=(const Enum & e) {return flags >= e;} bool operator >=(const Enum & e) {return flags >= e;}
//! compare operator //! compare operator
bool operator >=(const int i) {return flags >= i;} bool operator >=(const int i) {return flags >= i;}
//! compare operator //! compare operator
bool operator <=(const PIFlags & f) {return flags <= f.flags;} bool operator <=(const PIFlags & f) {return flags <= f.flags;}
//! compare operator //! compare operator
bool operator <=(const Enum & e) {return flags <= e;} bool operator <=(const Enum & e) {return flags <= e;}
//! compare operator //! compare operator
bool operator <=(const int i) {return flags <= i;} bool operator <=(const int i) {return flags <= i;}
//! Bit-wise AND operator //! Bit-wise AND operator
void operator &=(const PIFlags & f) {flags &= f.flags;} void operator &=(const PIFlags & f) {flags &= f.flags;}
//! Bit-wise AND operator //! Bit-wise AND operator
void operator &=(const Enum & e) {flags &= e;} void operator &=(const Enum & e) {flags &= e;}
//! Bit-wise AND operator //! Bit-wise AND operator
void operator &=(const int i) {flags &= i;} void operator &=(const int i) {flags &= i;}
//! Bit-wise OR operator //! Bit-wise OR operator
void operator |=(const PIFlags & f) {flags |= f.flags;} void operator |=(const PIFlags & f) {flags |= f.flags;}
//! Bit-wise OR operator //! Bit-wise OR operator
void operator |=(const Enum & e) {flags |= e;} void operator |=(const Enum & e) {flags |= e;}
//! Bit-wise OR operator //! Bit-wise OR operator
void operator |=(const int i) {flags |= i;} void operator |=(const int i) {flags |= i;}
//! Bit-wise XOR operator //! Bit-wise XOR operator
void operator ^=(const PIFlags & f) {flags ^= f.flags;} void operator ^=(const PIFlags & f) {flags ^= f.flags;}
//! Bit-wise XOR operator //! Bit-wise XOR operator
void operator ^=(const Enum & e) {flags ^= e;} void operator ^=(const Enum & e) {flags ^= e;}
//! Bit-wise XOR operator //! Bit-wise XOR operator
void operator ^=(const int i) {flags ^= i;} void operator ^=(const int i) {flags ^= i;}
//! Bit-wise AND operator //! Bit-wise AND operator
PIFlags operator &(PIFlags f) const {PIFlags tf(flags & f.flags); return tf;} PIFlags operator &(PIFlags f) const {PIFlags tf(flags & f.flags); return tf;}
//! Bit-wise AND operator //! Bit-wise AND operator
PIFlags operator &(Enum e) const {PIFlags tf(flags & e); return tf;} PIFlags operator &(Enum e) const {PIFlags tf(flags & e); return tf;}
//! Bit-wise AND operator //! Bit-wise AND operator
PIFlags operator &(int i) const {PIFlags tf(flags & i); return tf;} PIFlags operator &(int i) const {PIFlags tf(flags & i); return tf;}
//! Bit-wise OR operator //! Bit-wise OR operator
PIFlags operator |(PIFlags f) const {PIFlags tf(flags | f.flags); return tf;} PIFlags operator |(PIFlags f) const {PIFlags tf(flags | f.flags); return tf;}
//! Bit-wise OR operator //! Bit-wise OR operator
PIFlags operator |(Enum e) const {PIFlags tf(flags | e); return tf;} PIFlags operator |(Enum e) const {PIFlags tf(flags | e); return tf;}
//! Bit-wise OR operator //! Bit-wise OR operator
PIFlags operator |(int i) const {PIFlags tf(flags | i); return tf;} PIFlags operator |(int i) const {PIFlags tf(flags | i); return tf;}
//! Bit-wise XOR operator //! Bit-wise XOR operator
PIFlags operator ^(PIFlags f) const {PIFlags tf(flags ^ f.flags); return tf;} PIFlags operator ^(PIFlags f) const {PIFlags tf(flags ^ f.flags); return tf;}
//! Bit-wise XOR operator //! Bit-wise XOR operator
PIFlags operator ^(Enum e) const {PIFlags tf(flags ^ e); return tf;} PIFlags operator ^(Enum e) const {PIFlags tf(flags ^ e); return tf;}
//! Bit-wise XOR operator //! Bit-wise XOR operator
PIFlags operator ^(int i) const {PIFlags tf(flags ^ i); return tf;} PIFlags operator ^(int i) const {PIFlags tf(flags ^ i); return tf;}
//! Test flag operator //! Test flag operator
bool operator [](Enum e) const {return (flags & e) == e;} bool operator [](Enum e) const {return (flags & e) == e;}
//! Implicity conversion to \c int //! Implicity conversion to \c int
operator int() const {return flags;} operator int() const {return flags;}
private: private:
int flags; int flags;
}; };
#endif // PIFLAGS_H #endif // PIFLAGS_H

View File

112
src_main/core/piincludes.h → lib/main/core/piincludes.h Executable file → Normal file
View File

@@ -1,56 +1,56 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Minimal PIP includes Minimal PIP includes
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PIINCLUDES_H #ifndef PIINCLUDES_H
#define PIINCLUDES_H #define PIINCLUDES_H
#include "pibase.h" #include "pibase.h"
#include "piflags.h" #include "piflags.h"
#include <sys/types.h> #include <sys/types.h>
#ifdef PIP_STD_IOSTREAM #ifdef PIP_STD_IOSTREAM
# include <iostream> # include <iostream>
#endif #endif
class PIObject; class PIObject;
class PIMutex; class PIMutex;
class PIString; class PIString;
class PIByteArray; class PIByteArray;
class PIInit; class PIInit;
class PIChar; class PIChar;
class PICout; class PICout;
struct lconv; struct lconv;
extern lconv * currentLocale; extern lconv * currentLocale;
/*! \fn errorString() /*! \fn errorString()
* \brief Return readable error description in format "code <number> - <description>" */ * \brief Return readable error description in format "code <number> - <description>" */
PIP_EXPORT PIString errorString(); PIP_EXPORT PIString errorString();
PIP_EXPORT void errorClear(); PIP_EXPORT void errorClear();
PIP_EXPORT void piqsort(void* base, size_t num, size_t size, int (*compar)(const void*,const void*)); PIP_EXPORT void piqsort(void* base, size_t num, size_t size, int (*compar)(const void*,const void*));
PIP_EXPORT void randomize(); PIP_EXPORT void randomize();
PIP_EXPORT int randomi(); PIP_EXPORT int randomi();
/// Return readable version of PIP /// Return readable version of PIP
PIP_EXPORT PIString PIPVersion(); PIP_EXPORT PIString PIPVersion();
#endif // PIINCLUDES_H #endif // PIINCLUDES_H

View File

@@ -1,45 +1,45 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Private PIP includes Private PIP includes
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PIINCLUDES_P_H #ifndef PIINCLUDES_P_H
#define PIINCLUDES_P_H #define PIINCLUDES_P_H
#include "picout.h" #include "picout.h"
#ifdef WINDOWS #ifdef WINDOWS
# include <stdarg.h> # include <stdarg.h>
# include <windef.h> # include <windef.h>
# include <winbase.h> # include <winbase.h>
typedef LONG(NTAPI*PINtQueryTimerResolution)(PULONG, PULONG, PULONG); typedef LONG(NTAPI*PINtQueryTimerResolution)(PULONG, PULONG, PULONG);
typedef LONG(NTAPI*PINtSetTimerResolution)(ULONG, BOOLEAN, PULONG); typedef LONG(NTAPI*PINtSetTimerResolution)(ULONG, BOOLEAN, PULONG);
#endif #endif
#ifdef CC_GCC #ifdef CC_GCC
# include <unistd.h> # include <unistd.h>
#endif #endif
#include <string.h> #include <string.h>
#include <cstring> #include <cstring>
#include <string> #include <string>
#include <stdlib.h> #include <stdlib.h>
#include <cstdlib> #include <cstdlib>
#include <stdio.h> #include <stdio.h>
#include <cstdio> #include <cstdio>
#include <iostream> #include <iostream>
#endif // PIINCLUDES_P_H #endif // PIINCLUDES_P_H

View File

0
src_main/core/piobject.h → lib/main/core/piobject.h Executable file → Normal file
View File

View File

@@ -1,133 +1,133 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Storage of properties for GUI usage Storage of properties for GUI usage
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "pipropertystorage.h" #include "pipropertystorage.h"
bool PIPropertyStorage::isPropertyExists(const PIString & _name) const { bool PIPropertyStorage::isPropertyExists(const PIString & _name) const {
for (uint i = 0; i < props.size(); ++i) for (uint i = 0; i < props.size(); ++i)
if (props[i].name == _name) if (props[i].name == _name)
return true; return true;
return false; return false;
} }
void PIPropertyStorage::addProperty(const PIPropertyStorage::Property & p) { void PIPropertyStorage::addProperty(const PIPropertyStorage::Property & p) {
for (uint i = 0; i < props.size(); ++i) for (uint i = 0; i < props.size(); ++i)
if (props[i].name == p.name) { if (props[i].name == p.name) {
props[i] = p; props[i] = p;
return; return;
} }
props << p; props << p;
} }
void PIPropertyStorage::removeProperty(const PIString & _name) { void PIPropertyStorage::removeProperty(const PIString & _name) {
for (uint i = 0; i < props.size(); ++i) for (uint i = 0; i < props.size(); ++i)
if (props[i].name == _name) { if (props[i].name == _name) {
props.remove(i); props.remove(i);
return; return;
} }
} }
void PIPropertyStorage::removePropertiesByFlag(int flag) { void PIPropertyStorage::removePropertiesByFlag(int flag) {
for (int i = 0; i < props.size_s(); ++i) for (int i = 0; i < props.size_s(); ++i)
if ((props[i].flags & flag) == flag) { if ((props[i].flags & flag) == flag) {
props.remove(i); props.remove(i);
--i; --i;
} }
} }
void PIPropertyStorage::updateProperties(const PIVector<PIPropertyStorage::Property> & properties_, int flag_ignore) { void PIPropertyStorage::updateProperties(const PIVector<PIPropertyStorage::Property> & properties_, int flag_ignore) {
PIMap<PIString, PIVariant> values; PIMap<PIString, PIVariant> values;
piForeachC(Property & p, props) piForeachC(Property & p, props)
if (((p.flags & flag_ignore) != flag_ignore) || (flag_ignore == 0)) if (((p.flags & flag_ignore) != flag_ignore) || (flag_ignore == 0))
values[p.name] = p.value; values[p.name] = p.value;
props = properties_; props = properties_;
for (uint i = 0; i < props.size(); ++i) { for (uint i = 0; i < props.size(); ++i) {
Property & p(props[i]); Property & p(props[i]);
if (values.contains(p.name)) { if (values.contains(p.name)) {
PIVariant pv = values[p.name]; PIVariant pv = values[p.name];
if (pv.type() == p.value.type()) if (pv.type() == p.value.type())
p.value = pv; p.value = pv;
} }
} }
} }
PIPropertyStorage::Property PIPropertyStorage::propertyByName(const PIString & name) const { PIPropertyStorage::Property PIPropertyStorage::propertyByName(const PIString & name) const {
piForeachC(Property & p, props) piForeachC(Property & p, props)
if (p.name == name) if (p.name == name)
return p; return p;
return Property(); return Property();
} }
PIVariant PIPropertyStorage::propertyValueByName(const PIString & name) const { PIVariant PIPropertyStorage::propertyValueByName(const PIString & name) const {
piForeachC(Property & p, props) piForeachC(Property & p, props)
if (p.name == name) if (p.name == name)
return p.value; return p.value;
return PIVariant(); return PIVariant();
} }
void PIPropertyStorage::setPropertyValue(const PIString & name, const PIVariant & value) { void PIPropertyStorage::setPropertyValue(const PIString & name, const PIVariant & value) {
for (uint i = 0; i < props.size(); ++i) for (uint i = 0; i < props.size(); ++i)
if (props[i].name == name) { if (props[i].name == name) {
props[i].value = value; props[i].value = value;
return; return;
} }
} }
void PIPropertyStorage::setPropertyComment(const PIString & name, const PIString & comment) { void PIPropertyStorage::setPropertyComment(const PIString & name, const PIString & comment) {
for (uint i = 0; i < props.size(); ++i) for (uint i = 0; i < props.size(); ++i)
if (props[i].name == name) { if (props[i].name == name) {
props[i].comment = comment; props[i].comment = comment;
return; return;
} }
} }
void PIPropertyStorage::setPropertyFlags(const PIString & name, int flags) { void PIPropertyStorage::setPropertyFlags(const PIString & name, int flags) {
for (uint i = 0; i < props.size(); ++i) for (uint i = 0; i < props.size(); ++i)
if (props[i].name == name) { if (props[i].name == name) {
props[i].flags = flags; props[i].flags = flags;
return; return;
} }
} }
PIPropertyStorage::Property & PIPropertyStorage::operator[](const PIString & name) { PIPropertyStorage::Property & PIPropertyStorage::operator[](const PIString & name) {
piForeach (Property & p, props) piForeach (Property & p, props)
if (p.name == name) if (p.name == name)
return p; return p;
addProperty(name, ""); addProperty(name, "");
return props.back(); return props.back();
} }
const PIPropertyStorage::Property PIPropertyStorage::operator[](const PIString & name) const { const PIPropertyStorage::Property PIPropertyStorage::operator[](const PIString & name) const {
piForeachC (Property & p, props) piForeachC (Property & p, props)
if (p.name == name) if (p.name == name)
return p; return p;
return Property(); return Property();
} }

View File

@@ -1,172 +1,172 @@
/*! \file pipropertystorage.h /*! \file pipropertystorage.h
* \brief Storage of properties for GUI usage * \brief Storage of properties for GUI usage
* *
* This file declare PIPropertyStorage * This file declare PIPropertyStorage
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Storage of properties for GUI usage Storage of properties for GUI usage
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PIPROPERTYSTORAGE_H #ifndef PIPROPERTYSTORAGE_H
#define PIPROPERTYSTORAGE_H #define PIPROPERTYSTORAGE_H
#include "pivariant.h" #include "pivariant.h"
/** /**
* @brief Key-value storage, based on PIVector with PIPropertyStorage::Property elements. Each element in vector * @brief Key-value storage, based on PIVector with PIPropertyStorage::Property elements. Each element in vector
* contains unique name and you can identify property by name with propertyValueByName(), propertyByName(). * contains unique name and you can identify property by name with propertyValueByName(), propertyByName().
* You can add property using addProperty(const Property&), addProperty(const PIString&, const PIVariant&, const PIString&, int). * You can add property using addProperty(const Property&), addProperty(const PIString&, const PIVariant&, const PIString&, int).
*/ */
class PIPropertyStorage { class PIPropertyStorage {
public: public:
PIPropertyStorage() {} PIPropertyStorage() {}
/** /**
* @brief PIPropertyStorage element. * @brief PIPropertyStorage element.
*/ */
struct Property { struct Property {
Property(const PIString & n = PIString(), const PIString & c = PIString(), const PIVariant & v = PIVariant(), int f = 0): Property(const PIString & n = PIString(), const PIString & c = PIString(), const PIVariant & v = PIVariant(), int f = 0):
name(n), comment(c), value(v), flags(f) {} name(n), comment(c), value(v), flags(f) {}
bool toBool() const {return value.toBool();} bool toBool() const {return value.toBool();}
int toInt() const {return value.toInt();} int toInt() const {return value.toInt();}
float toFloat() const {return value.toFloat();} float toFloat() const {return value.toFloat();}
double toDouble() const {return value.toDouble();} double toDouble() const {return value.toDouble();}
PIString toString() const {return value.toString();} PIString toString() const {return value.toString();}
/*! Uniqueue id of property */ /*! Uniqueue id of property */
PIString name; PIString name;
/*! Optional description of property */ /*! Optional description of property */
PIString comment; PIString comment;
/*! Custom value of property */ /*! Custom value of property */
PIVariant value; PIVariant value;
/*! Abstract flags which may be used for user needs */ /*! Abstract flags which may be used for user needs */
int flags; int flags;
}; };
PIPropertyStorage(const PIVector<Property> & pl) {props = pl;} PIPropertyStorage(const PIVector<Property> & pl) {props = pl;}
typedef PIVector<Property>::const_iterator const_iterator; typedef PIVector<Property>::const_iterator const_iterator;
typedef PIVector<Property>::iterator iterator; typedef PIVector<Property>::iterator iterator;
typedef Property value_type; typedef Property value_type;
iterator begin() {return props.begin();} iterator begin() {return props.begin();}
const_iterator begin() const {return props.begin();} const_iterator begin() const {return props.begin();}
iterator end() {return props.end();} iterator end() {return props.end();}
const_iterator end() const {return props.end();} const_iterator end() const {return props.end();}
int length() const {return props.length();} int length() const {return props.length();}
int size() const {return props.size();} int size() const {return props.size();}
bool isEmpty() const {return props.isEmpty();} bool isEmpty() const {return props.isEmpty();}
Property & front() {return props.front();} Property & front() {return props.front();}
const Property & front() const {return props.front();} const Property & front() const {return props.front();}
Property & back() {return props.back();} Property & back() {return props.back();}
const Property & back() const {return props.back();} const Property & back() const {return props.back();}
void removeAt(int i) {props.remove(i);} void removeAt(int i) {props.remove(i);}
void clear() {props.clear();} void clear() {props.clear();}
PIPropertyStorage copy() const {return PIPropertyStorage(*this);} PIPropertyStorage copy() const {return PIPropertyStorage(*this);}
int propertiesCount() const {return props.size();} int propertiesCount() const {return props.size();}
PIVector<Property> & properties() {return props;} PIVector<Property> & properties() {return props;}
const PIVector<Property> & properties() const {return props;} const PIVector<Property> & properties() const {return props;}
const PIPropertyStorage & propertyStorage() const {return *this;} const PIPropertyStorage & propertyStorage() const {return *this;}
bool isPropertyExists(const PIString & _name) const; bool isPropertyExists(const PIString & _name) const;
void clearProperties() {props.clear();} void clearProperties() {props.clear();}
/** /**
* @brief Add property if name isn't present in storage, otherwrise update existing property with same name. * @brief Add property if name isn't present in storage, otherwrise update existing property with same name.
* *
* @param p to copy in storage * @param p to copy in storage
*/ */
void addProperty(const Property & p); void addProperty(const Property & p);
/** /**
* @brief First of all construct Property with method params. After then add property if name isn't present * @brief First of all construct Property with method params. After then add property if name isn't present
* in storage, otherwrise update existing property with same name. * in storage, otherwrise update existing property with same name.
*/ */
void addProperty(const PIString & _name, const PIVariant & _def_value, const PIString & _comment = PIString(), int _flags = 0) {addProperty(Property(_name, _comment, _def_value, _flags));} void addProperty(const PIString & _name, const PIVariant & _def_value, const PIString & _comment = PIString(), int _flags = 0) {addProperty(Property(_name, _comment, _def_value, _flags));}
void removeProperty(const PIString & _name); void removeProperty(const PIString & _name);
void removePropertiesByFlag(int flag); void removePropertiesByFlag(int flag);
void updateProperties(const PIVector<Property> & properties_, int flag_ignore = 0); void updateProperties(const PIVector<Property> & properties_, int flag_ignore = 0);
/** /**
* @brief Search property by name and return it. * @brief Search property by name and return it.
* *
* @param name of property * @param name of property
* @return property value or default constructed Property * @return property value or default constructed Property
*/ */
Property propertyByName(const PIString & name) const; Property propertyByName(const PIString & name) const;
/** /**
* @brief Search property by name and return property value. * @brief Search property by name and return property value.
* *
* @param name of property * @param name of property
* @return property value or invalid PIVariant if name unknown * @return property value or invalid PIVariant if name unknown
*/ */
PIVariant propertyValueByName(const PIString & name) const; PIVariant propertyValueByName(const PIString & name) const;
/** /**
* @brief Set value of property with specific name if name is present in storage. * @brief Set value of property with specific name if name is present in storage.
* *
* @param name of property to set value * @param name of property to set value
* @param value to set * @param value to set
*/ */
void setPropertyValue(const PIString & name, const PIVariant & value); void setPropertyValue(const PIString & name, const PIVariant & value);
/** /**
* @brief Set comment of property with specific name if name is present in storage. * @brief Set comment of property with specific name if name is present in storage.
* *
* @param name of property to set comment * @param name of property to set comment
* @param comment to set * @param comment to set
*/ */
void setPropertyComment(const PIString & name, const PIString & comment); void setPropertyComment(const PIString & name, const PIString & comment);
/** /**
* @brief Set flags of property with specific name if name is present in storage. * @brief Set flags of property with specific name if name is present in storage.
* *
* @param name of property to set flags * @param name of property to set flags
* @param flags to set * @param flags to set
*/ */
void setPropertyFlags(const PIString & name, int flags); void setPropertyFlags(const PIString & name, int flags);
PIPropertyStorage & operator <<(const PIPropertyStorage::Property & p) {props << p; return *this;} PIPropertyStorage & operator <<(const PIPropertyStorage::Property & p) {props << p; return *this;}
PIPropertyStorage & operator <<(const PIVector<Property> & p) {props << p; return *this;} PIPropertyStorage & operator <<(const PIVector<Property> & p) {props << p; return *this;}
PIPropertyStorage & operator <<(const PIPropertyStorage & p) {props << p.props; return *this;} PIPropertyStorage & operator <<(const PIPropertyStorage & p) {props << p.props; return *this;}
Property & operator[](int i) {return props[i];} Property & operator[](int i) {return props[i];}
const Property & operator[](int i) const {return props[i];} const Property & operator[](int i) const {return props[i];}
Property & operator[](const PIString & name); Property & operator[](const PIString & name);
const Property operator[](const PIString & name) const; const Property operator[](const PIString & name) const;
static Property parsePropertyLine(PIString l); static Property parsePropertyLine(PIString l);
protected: protected:
PIVector<Property> props; PIVector<Property> props;
}; };
inline PIByteArray & operator <<(PIByteArray & s, const PIPropertyStorage::Property & v) {s << v.name << v.value << v.comment << v.flags; return s;} inline PIByteArray & operator <<(PIByteArray & s, const PIPropertyStorage::Property & v) {s << v.name << v.value << v.comment << v.flags; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIPropertyStorage::Property & v) {s >> v.name >> v.value >> v.comment >> v.flags; return s;} inline PIByteArray & operator >>(PIByteArray & s, PIPropertyStorage::Property & v) {s >> v.name >> v.value >> v.comment >> v.flags; return s;}
inline PIByteArray & operator <<(PIByteArray & s, const PIPropertyStorage & v) {s << v.properties(); return s;} inline PIByteArray & operator <<(PIByteArray & s, const PIPropertyStorage & v) {s << v.properties(); return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIPropertyStorage & v) {s >> v.properties(); return s;} inline PIByteArray & operator >>(PIByteArray & s, PIPropertyStorage & v) {s >> v.properties(); return s;}
#endif // PIPROPERTYSTORAGE_H #endif // PIPROPERTYSTORAGE_H

View File

0
src_main/core/pistring.h → lib/main/core/pistring.h Executable file → Normal file
View File

View File

@@ -1,100 +1,100 @@
/*! \file pistring.h /*! \file pistring.h
* \brief String * \brief String
* *
* This file declare std operators and string conversions * This file declare std operators and string conversions
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
STD for PIString STD for PIString
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PISTRING_STD_H #ifndef PISTRING_STD_H
#define PISTRING_STD_H #define PISTRING_STD_H
#include <string> #include <string>
#ifdef QNX #ifdef QNX
typedef std::basic_string<wchar_t> wstring; typedef std::basic_string<wchar_t> wstring;
#endif #endif
#include "pistringlist.h" #include "pistringlist.h"
inline std::string PIString2StdString(const PIString & v) { inline std::string PIString2StdString(const PIString & v) {
std::string s; std::string s;
uint wc; uint wc;
uchar tc; uchar tc;
if (v.size() > 0) { if (v.size() > 0) {
for (int i = 0; i < v.length(); ++i) { for (int i = 0; i < v.length(); ++i) {
wc = uint(v.at(i).unicode16Code()); wc = uint(v.at(i).unicode16Code());
while (tc = wc & 0xFF, tc) { while (tc = wc & 0xFF, tc) {
s.push_back(char(tc)); s.push_back(char(tc));
wc >>= 8; wc >>= 8;
} }
} }
} }
return s; return s;
} }
inline PIString StdString2PIString(const std::string & v) { inline PIString StdString2PIString(const std::string & v) {
return PIString(v.c_str(), v.length()); return PIString(v.c_str(), v.length());
} }
#ifdef HAS_LOCALE #ifdef HAS_LOCALE
inline std::wstring PIString2StdWString(const PIString & v) { inline std::wstring PIString2StdWString(const PIString & v) {
std::wstring s; std::wstring s;
for (int i = 0; i < v.length(); ++i) for (int i = 0; i < v.length(); ++i)
s.push_back(v.at(i).toWChar()); s.push_back(v.at(i).toWChar());
return s; return s;
} }
inline PIString StdWString2PIString(const std::wstring & v) { inline PIString StdWString2PIString(const std::wstring & v) {
PIString s; PIString s;
uint l = v.size(); uint l = v.size();
for (uint i = 0; i < l; ++i) s.push_back(v[i]); for (uint i = 0; i < l; ++i) s.push_back(v[i]);
return s; return s;
} }
#endif #endif
//! \relatesalso PIChar \brief Output operator to \c std::ostream //! \relatesalso PIChar \brief Output operator to \c std::ostream
inline std::ostream & operator <<(std::ostream & s, const PIChar & v) {s << v.toCharPtr(); return s;} inline std::ostream & operator <<(std::ostream & s, const PIChar & v) {s << v.toCharPtr(); return s;}
//! \relatesalso PIString \brief Return concatenated string //! \relatesalso PIString \brief Return concatenated string
inline PIString operator +(const PIString & f, const std::string & str) {PIString s(f); s += StdString2PIString(str); return s;} inline PIString operator +(const PIString & f, const std::string & str) {PIString s(f); s += StdString2PIString(str); return s;}
//! \relatesalso PIString \brief Return concatenated string //! \relatesalso PIString \brief Return concatenated string
inline PIString operator +(const std::string & str, const PIString & f) {return StdString2PIString(str) + f;} inline PIString operator +(const std::string & str, const PIString & f) {return StdString2PIString(str) + f;}
//! \relatesalso PIString \brief Output operator to std::ostream (cout) //! \relatesalso PIString \brief Output operator to std::ostream (cout)
inline std::ostream & operator <<(std::ostream & s, const PIString & v) {for (int i = 0; i < v.length(); ++i) s << v[i]; return s;} inline std::ostream & operator <<(std::ostream & s, const PIString & v) {for (int i = 0; i < v.length(); ++i) s << v[i]; return s;}
//! \relatesalso PIString \brief Input operator from std::istream (cin) //! \relatesalso PIString \brief Input operator from std::istream (cin)
inline std::istream & operator >>(std::istream & s, PIString & v) {std::string ss; s >> ss; v = StdString2PIString(ss); return s;} inline std::istream & operator >>(std::istream & s, PIString & v) {std::string ss; s >> ss; v = StdString2PIString(ss); return s;}
//! \relatesalso PIStringList \brief Output operator to std::ostream (cout) //! \relatesalso PIStringList \brief Output operator to std::ostream (cout)
inline std::ostream & operator <<(std::ostream & s, const PIStringList & v) { inline std::ostream & operator <<(std::ostream & s, const PIStringList & v) {
s << PIChar("{"); s << PIChar("{");
for (uint i = 0; i < v.size(); ++i) { for (uint i = 0; i < v.size(); ++i) {
s << PIChar("\"") << v[i] << PIChar("\""); s << PIChar("\"") << v[i] << PIChar("\"");
if (i < v.size() - 1) s << PIStringAscii(", "); if (i < v.size() - 1) s << PIStringAscii(", ");
} }
s << PIChar("}"); s << PIChar("}");
return s; return s;
} }
#endif // PISTRING_STD_H #endif // PISTRING_STD_H

0
src_main/core/pitime.cpp → lib/main/core/pitime.cpp Executable file → Normal file
View File

0
src_main/core/pitime.h → lib/main/core/pitime.h Executable file → Normal file
View File

View File

@@ -1,87 +1,87 @@
/*! \file pitime_win.h /*! \file pitime_win.h
* \brief PITime conversions for Windows * \brief PITime conversions for Windows
* *
* This file declare time conversions for Windows * This file declare time conversions for Windows
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PITime conversions for Windows PITime conversions for Windows
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PITIME_WIN_H #ifndef PITIME_WIN_H
#define PITIME_WIN_H #define PITIME_WIN_H
#include "pibase.h" #include "pibase.h"
#ifdef WINDOWS #ifdef WINDOWS
#include "pitime.h" #include "pitime.h"
#include <windows.h> #include <windows.h>
inline PISystemTime FILETIME2PISystemTime(const FILETIME &t) { inline PISystemTime FILETIME2PISystemTime(const FILETIME &t) {
PISystemTime st; PISystemTime st;
ullong lt = ullong(t.dwHighDateTime) * 0x100000000U + ullong(t.dwLowDateTime); ullong lt = ullong(t.dwHighDateTime) * 0x100000000U + ullong(t.dwLowDateTime);
st.seconds = lt / 10000000U; st.seconds = lt / 10000000U;
st.nanoseconds = (lt % 10000000U) * 100U; st.nanoseconds = (lt % 10000000U) * 100U;
return st; return st;
} }
inline PIDateTime SYSTEMTIME2PIDateTime(const SYSTEMTIME &t) { inline PIDateTime SYSTEMTIME2PIDateTime(const SYSTEMTIME &t) {
PIDateTime dt; PIDateTime dt;
dt.year = t.wYear; dt.year = t.wYear;
dt.month = t.wMonth; dt.month = t.wMonth;
dt.day = t.wDay; dt.day = t.wDay;
dt.hours = t.wHour; dt.hours = t.wHour;
dt.minutes = t.wMinute; dt.minutes = t.wMinute;
dt.seconds = t.wSecond; dt.seconds = t.wSecond;
dt.milliseconds = t.wMilliseconds; dt.milliseconds = t.wMilliseconds;
return dt; return dt;
} }
inline PIDateTime FILETIME2PIDateTime(const FILETIME &t) { inline PIDateTime FILETIME2PIDateTime(const FILETIME &t) {
FILETIME lt; FILETIME lt;
SYSTEMTIME st; SYSTEMTIME st;
FileTimeToLocalFileTime(&t, &lt); FileTimeToLocalFileTime(&t, &lt);
FileTimeToSystemTime(&lt, &st); FileTimeToSystemTime(&lt, &st);
return SYSTEMTIME2PIDateTime(st); return SYSTEMTIME2PIDateTime(st);
} }
inline SYSTEMTIME PIDateTime2SYSTEMTIME(const PIDateTime &dt) { inline SYSTEMTIME PIDateTime2SYSTEMTIME(const PIDateTime &dt) {
SYSTEMTIME st; SYSTEMTIME st;
st.wYear = dt.year; st.wYear = dt.year;
st.wMonth = dt.month; st.wMonth = dt.month;
st.wDay = dt.day; st.wDay = dt.day;
st.wHour = dt.hours; st.wHour = dt.hours;
st.wMinute = dt.minutes; st.wMinute = dt.minutes;
st.wSecond = dt.seconds; st.wSecond = dt.seconds;
st.wMilliseconds = dt.milliseconds; st.wMilliseconds = dt.milliseconds;
return st; return st;
} }
inline FILETIME PIDateTime2FILETIME(const PIDateTime &dt) { inline FILETIME PIDateTime2FILETIME(const PIDateTime &dt) {
FILETIME lt, ret; FILETIME lt, ret;
SYSTEMTIME st = PIDateTime2SYSTEMTIME(dt); SYSTEMTIME st = PIDateTime2SYSTEMTIME(dt);
SystemTimeToFileTime(&st, &lt); SystemTimeToFileTime(&st, &lt);
LocalFileTimeToFileTime(&lt, &ret); LocalFileTimeToFileTime(&lt, &ret);
return ret; return ret;
} }
#endif // WINDOWS #endif // WINDOWS
#endif // PITIME_WIN_H #endif // PITIME_WIN_H

View File

Some files were not shown because too many files have changed in this diff Show More