From: g0dil Date: Mon, 5 Jan 2009 23:27:01 +0000 (+0000) Subject: Utils: Fix hexump() of nevative values X-Git-Url: http://g0dil.de/git?p=senf.git;a=commitdiff_plain;h=4004cfae8ca0e03a40385560e14bba730a801464 Utils: Fix hexump() of nevative values Utils/Console: Move telnet functionality to Utils/Termlib Utils/Termlib: Implement terminfo readier Utils/Termlib: Implement terminfo based keycode parser git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1036 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/SConstruct b/SConstruct index a898d6c..376a87d 100644 --- a/SConstruct +++ b/SConstruct @@ -118,8 +118,9 @@ INLINE_OPTS = [ '-finline-limit=5000' ] env.Append( CPPPATH = [ '#/include' ], CXXFLAGS = [ '-Wall', '-Woverloaded-virtual', '-Wno-long-long' ] + INLINE_OPTS, - LIBS = [ 'readline', 'rt', '$BOOSTREGEXLIB', '$BOOSTIOSTREAMSLIB', '$BOOSTSIGNALSLIB' ], - TEST_EXTRA_LIBS = [ '$BOOSTFSLIB' ], + LIBS = [ 'readline', 'rt', '$BOOSTREGEXLIB', '$BOOSTIOSTREAMSLIB', '$BOOSTSIGNALSLIB', + '$BOOSTFSLIB' ], + TEST_EXTRA_LIBS = [ ], DOXY_XREF_TYPES = [ 'bug', 'fixme', 'todo', 'idea' ], DOXY_HTML_XSL = '#/doclib/html-munge.xsl', ENV = { 'TODAY' : str(datetime.date.today()), diff --git a/Socket/Protocols/Raw/MACAddress.hh b/Socket/Protocols/Raw/MACAddress.hh index 4281efd..3b1e94c 100644 --- a/Socket/Protocols/Raw/MACAddress.hh +++ b/Socket/Protocols/Raw/MACAddress.hh @@ -67,14 +67,7 @@ namespace senf { INet6Address(0x2001u,0xDB8u,0x1u,0x0u,0x001Au,0x2BFFu,0xFE3Cu,0x3D5Fu).id()) \endcode - Since MACAddress is based on \c boo Ziel, aber nur ein paar davon sind standardkomform. - -Der aktuelle C++ Standard unterstützt drei verschiedene Möglichkeiten eine Zahl in einen String umzuwandeln. Diese Möglichkeiten sind: - - * sprintf - * std::strstream - * std::stringstream - st::array, you can access the raw data bytes of the + Since MACAddress is based on \c boost::array, you can access the raw data bytes of the address using \c begin(), \c end() or \c operator[]: \code MACAddress mac = ...; diff --git a/Utils/Console/SConscript b/Utils/Console/SConscript index a231c94..c54f55c 100644 --- a/Utils/Console/SConscript +++ b/Utils/Console/SConscript @@ -5,11 +5,10 @@ import SENFSCons ########################################################################### -sources, includes = SENFSCons.Glob(env, exclude=['testServer.cc', 'telnetServer.cc']) +sources, includes = SENFSCons.Glob(env, exclude=['testServer.cc']) SENFSCons.StandardTargets(env) SENFSCons.Lib(env, sources) SENFSCons.Doxygen(env) SENFSCons.InstallIncludeFiles(env, includes) SENFSCons.Binary(env, "testServer", ['testServer.cc']) -SENFSCons.Binary(env, "telnetServer", ['telnetServer.cc']) diff --git a/Utils/Termlib/Doxyfile b/Utils/Termlib/Doxyfile new file mode 100644 index 0000000..b7b820c --- /dev/null +++ b/Utils/Termlib/Doxyfile @@ -0,0 +1,12 @@ +@INCLUDE = "$(TOPDIR)/doclib/Doxyfile.global" + +PROJECT_NAME = libTermlib +GENERATE_TAGFILE = doc/Console.tag +EXAMPLE_PATH = . +EXCLUDE = telnetServer.cc + +TAGFILES = \ + "$(TOPDIR)/Socket/doc/Socket.tag" \ + "$(TOPDIR)/Scheduler/doc/Scheduler.tag" \ + "$(TOPDIR)/Utils/doc/Utils.tag" \ + "$(TOPDIR)/Utils/Logger/doc/Logger.tag" diff --git a/Utils/Termlib/SConscript b/Utils/Termlib/SConscript new file mode 100644 index 0000000..7fe6526 --- /dev/null +++ b/Utils/Termlib/SConscript @@ -0,0 +1,14 @@ +# -*- python -*- + +Import('env') +import SENFSCons + +########################################################################### + +sources, includes = SENFSCons.Glob(env, exclude=[ 'telnetServer.cc']) + +SENFSCons.StandardTargets(env) +SENFSCons.Lib(env, sources) +SENFSCons.Doxygen(env) +SENFSCons.InstallIncludeFiles(env, includes) +SENFSCons.Binary(env, "telnetServer", ['telnetServer.cc']) diff --git a/Utils/Console/Telnet.cc b/Utils/Termlib/Telnet.cc similarity index 75% rename from Utils/Console/Telnet.cc rename to Utils/Termlib/Telnet.cc index acf32ce..b32747a 100644 --- a/Utils/Console/Telnet.cc +++ b/Utils/Termlib/Telnet.cc @@ -34,36 +34,36 @@ #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// -prefix_ senf::console::detail::BaseTelnetProtocol::BaseTelnetProtocol(Handle handle) +prefix_ senf::term::BaseTelnetProtocol::BaseTelnetProtocol(Handle handle) : handle_ (handle), charState_ (NORMAL), command_ (CMD_NONE), option_ (0), - inputEvent_ ("senf::console::detail::BaseTelnetProtocol::input", + inputEvent_ ("senf::term::BaseTelnetProtocol::input", senf::membind(&BaseTelnetProtocol::readHandler, this), handle, senf::scheduler::FdEvent::EV_READ), - outputEvent_ ("senf::console::detail::BaseTelnetProtocol::output", + outputEvent_ ("senf::term::BaseTelnetProtocol::output", senf::membind(&BaseTelnetProtocol::writeHandler, this), handle, senf::scheduler::FdEvent::EV_WRITE, false), pendingRequests_ (0u), requestTimeout_ (ClockService::milliseconds(DEFAULT_REQUEST_TIMEOUT_MS)), - timeout_ ("senf::console::detail::BaseTelnetProtocol::timeout", + timeout_ ("senf::term::BaseTelnetProtocol::timeout", senf::membind(&BaseTelnetProtocol::timeout, this)) {} -prefix_ senf::console::detail::BaseTelnetProtocol::BaseTelnetProtocol() +prefix_ senf::term::BaseTelnetProtocol::BaseTelnetProtocol() : handle_ (), charState_ (NORMAL), command_ (CMD_NONE), option_ (0), - inputEvent_ ("senf::console::detail::BaseTelnetProtocol::input", 0), - outputEvent_ ("senf::console::detail::BaseTelnetProtocol::output", 0), + inputEvent_ ("senf::term::BaseTelnetProtocol::input", 0), + outputEvent_ ("senf::term::BaseTelnetProtocol::output", 0), pendingRequests_ (0u), requestTimeout_ (ClockService::milliseconds(DEFAULT_REQUEST_TIMEOUT_MS)), - timeout_ ("senf::console::detail::BaseTelnetProtocol::timeout", 0) + timeout_ ("senf::term::BaseTelnetProtocol::timeout", 0) {} -prefix_ void senf::console::detail::BaseTelnetProtocol::write(std::string const & s) +prefix_ void senf::term::BaseTelnetProtocol::write(std::string const & s) { for (std::string::const_iterator i (s.begin()); i != s.end(); ++i) write(*i); } -prefix_ void senf::console::detail::BaseTelnetProtocol::write(char c) +prefix_ void senf::term::BaseTelnetProtocol::write(char c) { switch (c) { case '\r': @@ -85,7 +85,7 @@ prefix_ void senf::console::detail::BaseTelnetProtocol::write(char c) } prefix_ void -senf::console::detail::BaseTelnetProtocol::sendOptionParameters(option_type option, +senf::term::BaseTelnetProtocol::sendOptionParameters(option_type option, std::string const & data) { transmit(CMD_IAC); @@ -102,31 +102,31 @@ senf::console::detail::BaseTelnetProtocol::sendOptionParameters(option_type opti transmit(CMD_SE); } -prefix_ void senf::console::detail::BaseTelnetProtocol::v_handleNOP() +prefix_ void senf::term::BaseTelnetProtocol::v_handleNOP() {} -prefix_ void senf::console::detail::BaseTelnetProtocol::v_handleBRK() +prefix_ void senf::term::BaseTelnetProtocol::v_handleBRK() {} -prefix_ void senf::console::detail::BaseTelnetProtocol::v_handleIP() +prefix_ void senf::term::BaseTelnetProtocol::v_handleIP() {} -prefix_ void senf::console::detail::BaseTelnetProtocol::v_handleAO() +prefix_ void senf::term::BaseTelnetProtocol::v_handleAO() {} -prefix_ void senf::console::detail::BaseTelnetProtocol::v_handleAYT() +prefix_ void senf::term::BaseTelnetProtocol::v_handleAYT() {} -prefix_ void senf::console::detail::BaseTelnetProtocol::v_handleEC() +prefix_ void senf::term::BaseTelnetProtocol::v_handleEC() {} -prefix_ void senf::console::detail::BaseTelnetProtocol::v_handleEL() +prefix_ void senf::term::BaseTelnetProtocol::v_handleEL() {} -prefix_ void senf::console::detail::BaseTelnetProtocol::v_handleGA() +prefix_ void senf::term::BaseTelnetProtocol::v_handleGA() {} -prefix_ void senf::console::detail::BaseTelnetProtocol::handleChar(char c) +prefix_ void senf::term::BaseTelnetProtocol::handleChar(char c) { switch (charState_) { case NORMAL: @@ -153,7 +153,7 @@ prefix_ void senf::console::detail::BaseTelnetProtocol::handleChar(char c) } } -prefix_ void senf::console::detail::BaseTelnetProtocol::handleNormalChar(char c) +prefix_ void senf::term::BaseTelnetProtocol::handleNormalChar(char c) { switch (c) { case '\r': @@ -168,7 +168,7 @@ prefix_ void senf::console::detail::BaseTelnetProtocol::handleNormalChar(char c) } } -prefix_ void senf::console::detail::BaseTelnetProtocol::handleCommand(char c) +prefix_ void senf::term::BaseTelnetProtocol::handleCommand(char c) { switch (c) { case CMD_SE: @@ -211,14 +211,14 @@ prefix_ void senf::console::detail::BaseTelnetProtocol::handleCommand(char c) } } -prefix_ void senf::console::detail::BaseTelnetProtocol::handleOption(char c) +prefix_ void senf::term::BaseTelnetProtocol::handleOption(char c) { option_ = c; processCommand(); charState_ = NORMAL; } -prefix_ void senf::console::detail::BaseTelnetProtocol::handleCR(char c) +prefix_ void senf::term::BaseTelnetProtocol::handleCR(char c) { switch (c) { case '\0': @@ -237,14 +237,14 @@ prefix_ void senf::console::detail::BaseTelnetProtocol::handleCR(char c) } } -prefix_ void senf::console::detail::BaseTelnetProtocol::handleSBOption(char c) +prefix_ void senf::term::BaseTelnetProtocol::handleSBOption(char c) { option_ = c; charState_ = SB_DATA; data_.clear(); } -prefix_ void senf::console::detail::BaseTelnetProtocol::handleSBData(char c) +prefix_ void senf::term::BaseTelnetProtocol::handleSBData(char c) { if (c == '\xff') charState_ = SB_IAC_SEEN; @@ -252,7 +252,7 @@ prefix_ void senf::console::detail::BaseTelnetProtocol::handleSBData(char c) data_.push_back(c); } -prefix_ void senf::console::detail::BaseTelnetProtocol::handleSBIAC(char c) +prefix_ void senf::term::BaseTelnetProtocol::handleSBIAC(char c) { switch (c) { case CMD_IAC: @@ -270,7 +270,7 @@ prefix_ void senf::console::detail::BaseTelnetProtocol::handleSBIAC(char c) } } -prefix_ void senf::console::detail::BaseTelnetProtocol::processCommand() +prefix_ void senf::term::BaseTelnetProtocol::processCommand() { switch (command_) { case CMD_NONE: @@ -320,13 +320,13 @@ prefix_ void senf::console::detail::BaseTelnetProtocol::processCommand() } } -prefix_ void senf::console::detail::BaseTelnetProtocol::transmit(char c) +prefix_ void senf::term::BaseTelnetProtocol::transmit(char c) { sendQueue_.push_back(c); outputEvent_.enable(); } -prefix_ void senf::console::detail::BaseTelnetProtocol::readHandler(int state) +prefix_ void senf::term::BaseTelnetProtocol::readHandler(int state) { if (state != senf::scheduler::FdEvent::EV_READ || handle_.eof()) { inputEvent_.disable(); @@ -339,7 +339,7 @@ prefix_ void senf::console::detail::BaseTelnetProtocol::readHandler(int state) handleChar(*i); } -prefix_ void senf::console::detail::BaseTelnetProtocol::writeHandler(int state) +prefix_ void senf::term::BaseTelnetProtocol::writeHandler(int state) { if (state != senf::scheduler::FdEvent::EV_WRITE) { outputEvent_.disable(); @@ -353,7 +353,7 @@ prefix_ void senf::console::detail::BaseTelnetProtocol::writeHandler(int state) outputEvent_.disable(); } -prefix_ void senf::console::detail::BaseTelnetProtocol::timeout() +prefix_ void senf::term::BaseTelnetProtocol::timeout() { if (pendingRequests_ > 0u) { pendingRequests_ = 0u; @@ -361,8 +361,8 @@ prefix_ void senf::console::detail::BaseTelnetProtocol::timeout() } } -prefix_ senf::console::detail::BaseTelnetProtocol::OptInfo & -senf::console::detail::BaseTelnetProtocol::getOption(bool local, option_type option) +prefix_ senf::term::BaseTelnetProtocol::OptInfo & +senf::term::BaseTelnetProtocol::getOption(bool local, option_type option) { OptionsMap::iterator i (options_.find(std::make_pair(local, option))); if (i == options_.end()) @@ -371,7 +371,7 @@ senf::console::detail::BaseTelnetProtocol::getOption(bool local, option_type opt return i->second; } -prefix_ void senf::console::detail::BaseTelnetProtocol::request(OptInfo & info, bool enabled) +prefix_ void senf::term::BaseTelnetProtocol::request(OptInfo & info, bool enabled) { info.wantState = enabled ? OptInfo::WANTED : OptInfo::DISABLED; if (enabled != info.enabled) { @@ -383,7 +383,7 @@ prefix_ void senf::console::detail::BaseTelnetProtocol::request(OptInfo & info, } } -prefix_ void senf::console::detail::BaseTelnetProtocol::response(OptInfo & info, bool enabled) +prefix_ void senf::term::BaseTelnetProtocol::response(OptInfo & info, bool enabled) { bool decrementCount (false); @@ -417,12 +417,12 @@ prefix_ void senf::console::detail::BaseTelnetProtocol::response(OptInfo & info, i->second->v_init(); } if (decrementCount) - // This call must be AFTER calling v_init since v_init might increment the request count. + // This call must be AFTER calling v_init since v_init might increment the request count // and v_setupComplete() might be called prematurely. decrementRequestCounter(); } -prefix_ void senf::console::detail::BaseTelnetProtocol::decrementRequestCounter() +prefix_ void senf::term::BaseTelnetProtocol::decrementRequestCounter() { if (pendingRequests_ > 0u) { -- pendingRequests_; @@ -434,19 +434,19 @@ prefix_ void senf::console::detail::BaseTelnetProtocol::decrementRequestCounter( } /////////////////////////////////////////////////////////////////////////// -// senf::console::detail::telnethandler::TerminalType +// senf::term::telnethandler::TerminalType -prefix_ senf::console::detail::telnethandler::TerminalType::TerminalType() +prefix_ senf::term::telnethandler::TerminalType::TerminalType() { registerHandler(this); } -prefix_ void senf::console::detail::telnethandler::TerminalType::nextTerminalType() +prefix_ void senf::term::telnethandler::TerminalType::nextTerminalType() { sendOptionParameters(telnetopt::TERMINAL_TYPE, "\x01"); } -prefix_ void senf::console::detail::telnethandler::TerminalType:: +prefix_ void senf::term::telnethandler::TerminalType:: v_handleOptionParameters(std::string const & data) { if (data.size() <= 0) @@ -457,28 +457,28 @@ v_handleOptionParameters(std::string const & data) } } -prefix_ void senf::console::detail::telnethandler::TerminalType::v_init() +prefix_ void senf::term::telnethandler::TerminalType::v_init() { nextTerminalType(); incrementRequestCounter(); } /////////////////////////////////////////////////////////////////////////// -// senf::console::detail::telnethandler::NAWS +// senf::term::telnethandler::NAWS -prefix_ senf::console::detail::telnethandler::NAWS::NAWS() +prefix_ senf::term::telnethandler::NAWS::NAWS() : width_ (0u), height_ (0u) { registerHandler(this); } -prefix_ void senf::console::detail::telnethandler::NAWS::v_init() +prefix_ void senf::term::telnethandler::NAWS::v_init() { incrementRequestCounter(); } prefix_ void -senf::console::detail::telnethandler::NAWS::v_handleOptionParameters(std::string const & data) +senf::term::telnethandler::NAWS::v_handleOptionParameters(std::string const & data) { if (data.size() != 4) return; diff --git a/Utils/Console/Telnet.cci b/Utils/Termlib/Telnet.cci similarity index 62% rename from Utils/Console/Telnet.cci rename to Utils/Termlib/Telnet.cci index 7dc6f2a..ed7d902 100644 --- a/Utils/Console/Telnet.cci +++ b/Utils/Termlib/Telnet.cci @@ -31,133 +31,133 @@ ///////////////////////////////cci.p/////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// -// senf::console::detail::BaseTelnetProtocol::OptInfo +// senf::term::BaseTelnetProtocol::OptInfo -prefix_ senf::console::detail::BaseTelnetProtocol::OptInfo::OptInfo() +prefix_ senf::term::BaseTelnetProtocol::OptInfo::OptInfo() : local (false), option (0u), wantState (DISABLED), optionState (NONE), enabled (false) {} -prefix_ senf::console::detail::BaseTelnetProtocol::OptInfo::OptInfo(bool l, option_type o) +prefix_ senf::term::BaseTelnetProtocol::OptInfo::OptInfo(bool l, option_type o) : local (l), option (o), wantState (DISABLED), optionState (NONE), enabled (false) {} /////////////////////////////////////////////////////////////////////////// -// senf::console::detail::BaseTelnetProtocol::TelnetHandler +// senf::term::BaseTelnetProtocol::TelnetHandler -prefix_ senf::console::detail::BaseTelnetProtocol::TelnetHandler::~TelnetHandler() +prefix_ senf::term::BaseTelnetProtocol::TelnetHandler::~TelnetHandler() {} -prefix_ std::string const & senf::console::detail::telnethandler::TerminalType::terminalType() +prefix_ std::string const & senf::term::telnethandler::TerminalType::terminalType() const { return type_; } /////////////////////////////////////////////////////////////////////////// -// senf::console::detail::telnethandler::NAWS +// senf::term::telnethandler::NAWS -prefix_ unsigned senf::console::detail::telnethandler::NAWS::width() +prefix_ unsigned senf::term::telnethandler::NAWS::width() const { return width_; } -prefix_ unsigned senf::console::detail::telnethandler::NAWS::height() +prefix_ unsigned senf::term::telnethandler::NAWS::height() const { return height_; } /////////////////////////////////////////////////////////////////////////// -// senf::console::detail::BaseTelnetProtocol +// senf::term::BaseTelnetProtocol -prefix_ senf::console::detail::BaseTelnetProtocol::~BaseTelnetProtocol() +prefix_ senf::term::BaseTelnetProtocol::~BaseTelnetProtocol() {} -prefix_ void senf::console::detail::BaseTelnetProtocol::incrementRequestCounter() +prefix_ void senf::term::BaseTelnetProtocol::incrementRequestCounter() { ++ pendingRequests_; timeout_.timeout(senf::scheduler::eventTime() + requestTimeout_); } -prefix_ bool senf::console::detail::BaseTelnetProtocol::requestsPending() +prefix_ bool senf::term::BaseTelnetProtocol::requestsPending() { return pendingRequests_ > 0u; } -prefix_ void senf::console::detail::BaseTelnetProtocol::sendNOP() +prefix_ void senf::term::BaseTelnetProtocol::sendNOP() { transmit(CMD_IAC); transmit(CMD_NOP); } -prefix_ void senf::console::detail::BaseTelnetProtocol::sendBRK() +prefix_ void senf::term::BaseTelnetProtocol::sendBRK() { transmit(CMD_IAC); transmit(CMD_BRK); } -prefix_ void senf::console::detail::BaseTelnetProtocol::sendIP() +prefix_ void senf::term::BaseTelnetProtocol::sendIP() { transmit(CMD_IAC); transmit(CMD_IP); } -prefix_ void senf::console::detail::BaseTelnetProtocol::sendAO() +prefix_ void senf::term::BaseTelnetProtocol::sendAO() { transmit(CMD_IAC); transmit(CMD_AO); } -prefix_ void senf::console::detail::BaseTelnetProtocol::sendAYT() +prefix_ void senf::term::BaseTelnetProtocol::sendAYT() { transmit(CMD_IAC); transmit(CMD_AYT); } -prefix_ void senf::console::detail::BaseTelnetProtocol::sendEC() +prefix_ void senf::term::BaseTelnetProtocol::sendEC() { transmit(CMD_IAC); transmit(CMD_EC); } -prefix_ void senf::console::detail::BaseTelnetProtocol::sendEL() +prefix_ void senf::term::BaseTelnetProtocol::sendEL() { transmit(CMD_IAC); transmit(CMD_EL); } -prefix_ void senf::console::detail::BaseTelnetProtocol::sendGA() +prefix_ void senf::term::BaseTelnetProtocol::sendGA() { transmit(CMD_IAC); transmit(CMD_GA); } -prefix_ void senf::console::detail::BaseTelnetProtocol::requestLocalOption(option_type option, +prefix_ void senf::term::BaseTelnetProtocol::requestLocalOption(option_type option, bool enabled) { request(getOption(true, option), enabled); } -prefix_ void senf::console::detail::BaseTelnetProtocol::acceptLocalOption(option_type option, +prefix_ void senf::term::BaseTelnetProtocol::acceptLocalOption(option_type option, bool enabled) { getOption(true, option).wantState = OptInfo::ACCEPTED; } -prefix_ void senf::console::detail::BaseTelnetProtocol::requestPeerOption(option_type option, +prefix_ void senf::term::BaseTelnetProtocol::requestPeerOption(option_type option, bool enabled) { request(getOption(false, option), enabled); } -prefix_ void senf::console::detail::BaseTelnetProtocol::acceptPeerOption(option_type option, +prefix_ void senf::term::BaseTelnetProtocol::acceptPeerOption(option_type option, bool enabled) { getOption(false, option).wantState = OptInfo::ACCEPTED; } -prefix_ void senf::console::detail::BaseTelnetProtocol::emit(char c) +prefix_ void senf::term::BaseTelnetProtocol::emit(char c) { v_charReceived(c); } diff --git a/Utils/Console/Telnet.cti b/Utils/Termlib/Telnet.cti similarity index 93% rename from Utils/Console/Telnet.cti rename to Utils/Termlib/Telnet.cti index 42b50a6..e50e845 100644 --- a/Utils/Console/Telnet.cti +++ b/Utils/Termlib/Telnet.cti @@ -31,10 +31,10 @@ ///////////////////////////////cti.p/////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// -// senf::console::detail::BaseTelnetProtocol +// senf::term::BaseTelnetProtocol template -prefix_ void senf::console::detail::BaseTelnetProtocol::registerHandler(Handler * h, +prefix_ void senf::term::BaseTelnetProtocol::registerHandler(Handler * h, bool request) { handlers_.insert(std::make_pair(Handler::OPTION_CODE, h)); diff --git a/Utils/Console/Telnet.hh b/Utils/Termlib/Telnet.hh similarity index 97% rename from Utils/Console/Telnet.hh rename to Utils/Termlib/Telnet.hh index d813474..c50f87b 100644 --- a/Utils/Console/Telnet.hh +++ b/Utils/Termlib/Telnet.hh @@ -37,14 +37,13 @@ ///////////////////////////////hh.p//////////////////////////////////////// namespace senf { -namespace console { -namespace detail { +namespace term { /** \brief Telnet server \see - RFC 855 Telnet option specifications + RFC 854 The Telnet protocol \n + RFC 855 Telnet option specifications \todo SYNCH handling */ @@ -95,8 +94,6 @@ namespace detail { void decrementRequestCounter(); bool requestsPending(); - private: - #ifndef DOXYGEN private: #endif @@ -271,7 +268,7 @@ namespace telnethandler { } -}}} +}} ///////////////////////////////hh.e//////////////////////////////////////// #include "Telnet.cci" diff --git a/Utils/Console/Telnet.test.cc b/Utils/Termlib/Telnet.test.cc similarity index 100% copy from Utils/Console/Telnet.test.cc copy to Utils/Termlib/Telnet.test.cc diff --git a/Utils/Termlib/TelnetTerminal.cc b/Utils/Termlib/TelnetTerminal.cc new file mode 100644 index 0000000..1c244ba --- /dev/null +++ b/Utils/Termlib/TelnetTerminal.cc @@ -0,0 +1,94 @@ +// $Id$ +// +// Copyright (C) 2009 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief TelnetTerminal non-inline non-template implementation */ + +#include "TelnetTerminal.hh" +//#include "TelnetTerminal.ih" + +// Custom includes +#include + +//#include "TelnetTerminal.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ senf::term::TelnetTerminal::TelnetTerminal() + : keyTimeout_ (senf::ClockService::milliseconds(DEFAULT_KEY_TIMEOUT_MS)), + timer_ ("senf::term::TelnetTerminal::keySequenceTimeout", + senf::membind(&TelnetTerminal::keySequenceTimeout, this)) +{ + requestPeerOption(telnetopt::SUPPRESS_GO_AHEAD); + requestLocalOption(telnetopt::SUPPRESS_GO_AHEAD); + requestLocalOption(telnetopt::ECHO); +} + +prefix_ void senf::term::TelnetTerminal::v_setupComplete() +{ + tifo_.load(terminalType()); + keyParser_.load(tifo_); +} + +prefix_ void senf::term::TelnetTerminal::v_charReceived(char c) +{ + inputBuffer_ += c; + timer_.timeout(senf::scheduler::eventTime() + keyTimeout_); + processKeys(); +} + +prefix_ void senf::term::TelnetTerminal::keySequenceTimeout() +{ + while (!inputBuffer_.empty()) { + processKeys(); + v_keyReceived(keycode_t(inputBuffer_[0])); + inputBuffer_.erase(0, 1); + } +} + +prefix_ void senf::term::TelnetTerminal::processKeys() +{ + do { + std::pair result + (keyParser_.lookup(inputBuffer_)); + if (result.first == senf::term::KeyParser::Incomplete) + return; + v_keyReceived(result.first); + inputBuffer_.erase(0, result.second); + } while (! inputBuffer_.empty()); + timer_.disable(); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "TelnetTerminal.mpp" + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/Utils/Termlib/TelnetTerminal.hh b/Utils/Termlib/TelnetTerminal.hh new file mode 100644 index 0000000..0514c63 --- /dev/null +++ b/Utils/Termlib/TelnetTerminal.hh @@ -0,0 +1,85 @@ +// $Id$ +// +// Copyright (C) 2009 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief TelnetTerminal public header */ + +#ifndef HH_SENF_Utils_Termlib_TelnetTerminal_ +#define HH_SENF_Utils_Termlib_TelnetTerminal_ 1 + +// Custom includes +#include +#include +#include "Telnet.hh" +#include "Terminfo.hh" + +//#include "TelnetTerminal.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace senf { +namespace term { + + class TelnetTerminal + : public telnethandler::TerminalType, + public telnethandler::NAWS + { + public: + typedef KeyParser::keycode_t keycode_t; + + static unsigned const DEFAULT_KEY_TIMEOUT_MS = 500u; + + TelnetTerminal(); + + protected: + virtual void v_setupComplete(); + + private: + virtual void v_keyReceived(keycode_t key) = 0; + + virtual void v_charReceived(char c); + void keySequenceTimeout(); + void processKeys(); + + senf::term::Terminfo tifo_; + senf::term::KeyParser keyParser_; + std::string inputBuffer_; + senf::ClockService::clock_type keyTimeout_; + senf::scheduler::TimerEvent timer_; + }; +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "TelnetTerminal.cci" +//#include "TelnetTerminal.ct" +//#include "TelnetTerminal.cti" +#endif + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/Utils/Termlib/Terminfo.cc b/Utils/Termlib/Terminfo.cc new file mode 100644 index 0000000..1a7c50f --- /dev/null +++ b/Utils/Termlib/Terminfo.cc @@ -0,0 +1,473 @@ +// $Id$ +// +// Copyright (C) 2009 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief Terminfo non-inline non-template implementation */ + +#include "Terminfo.hh" +//#include "Terminfo.ih" + +// Custom includes +#include +#include +#include +#include +#include +#include +#include + +//#include "Terminfo.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +char const * const senf::term::Terminfo::properties::BooleanNames [] = { + "AutoLeftMargin", "AutoRightMargin", "NoEscCtlc", "CeolStandoutGlitch", "EatNewlineGlitch", + "EraseOverstrike", "GenericType", "HardCopy", "HasMetaKey", "HasStatusLine", "InsertNullGlitch", + "MemoryAbove", "MemoryBelow", "MoveInsertMode", "MoveStandoutMode", "OverStrike", + "StatusLineEscOk", "DestTabsMagicSmso", "TildeGlitch", "TransparentUnderline", "XonXoff", + "NeedsXonXoff", "PrtrSilent", "HardCursor", "NonRevRmcup", "NoPadChar", "NonDestScrollRegion", + "CanChange", "BackColorErase", "HueLightnessSaturation", "ColAddrGlitch", "CrCancelsMicroMode", + "HasPrintWheel", "RowAddrGlitch", "SemiAutoRightMargin", "CpiChangesRes", "LpiChangesRes", + "BackspacesWithBs", "CrtNoScrolling", "NoCorrectlyWorkingCr", "GnuHasMetaKey", + "LinefeedIsNewline", "HasHardwareTabs", "ReturnDoesClrEol" }; + +char const * const senf::term::Terminfo::properties::NumericNames[] = { + "Columns", "InitTabs", "Lines", "LinesOfMemory", "MagicCookieGlitch", "PaddingBaudRate", + "VirtualTerminal", "WidthStatusLine", "NumLabels", "LabelHeight", "LabelWidth", "MaxAttributes", + "MaximumWindows", "MaxColors", "MaxPairs", "NoColorVideo", "BufferCapacity", "DotVertSpacing", + "DotHorzSpacing", "MaxMicroAddress", "MaxMicroJump", "MicroColSize", "MicroLineSize", + "NumberOfPins", "OutputResChar", "OutputResLine", "OutputResHorzInch", "OutputResVertInch", + "PrintRate", "WideCharSize", "Buttons", "BitImageEntwining", "BitImageType", + "MagicCookieGlitchUl", "CarriageReturnDelay", "NewLineDelay", "BackspaceDelay", + "HorizontalTabDelay", "NumberOfFunctionKeys" }; + +char const * const senf::term::Terminfo::properties::StringNames[] = { + "BackTab", "Bell", "CarriageReturn", "ChangeScrollRegion", "ClearAllTabs", "ClearScreen", + "ClrEol", "ClrEos", "ColumnAddress", "CommandCharacter", "CursorAddress", "CursorDown", + "CursorHome", "CursorInvisible", "CursorLeft", "CursorMemAddress", "CursorNormal", + "CursorRight", "CursorToLl", "CursorUp", "CursorVisible", "DeleteCharacter", "DeleteLine", + "DisStatusLine", "DownHalfLine", "EnterAltCharsetMode", "EnterBlinkMode", "EnterBoldMode", + "EnterCaMode", "EnterDeleteMode", "EnterDimMode", "EnterInsertMode", "EnterSecureMode", + "EnterProtectedMode", "EnterReverseMode", "EnterStandoutMode", "EnterUnderlineMode", + "EraseChars", "ExitAltCharsetMode", "ExitAttributeMode", "ExitCaMode", "ExitDeleteMode", + "ExitInsertMode", "ExitStandoutMode", "ExitUnderlineMode", "FlashScreen", "FormFeed", + "FromStatusLine", "Init1string", "Init2string", "Init3string", "InitFile", "InsertCharacter", + "InsertLine", "InsertPadding", "KeyBackspace", "KeyCatab", "KeyClear", "KeyCtab", "KeyDc", + "KeyDl", "KeyDown", "KeyEic", "KeyEol", "KeyEos", "KeyF0", "KeyF1", "KeyF10", "KeyF2", "KeyF3", + "KeyF4", "KeyF5", "KeyF6", "KeyF7", "KeyF8", "KeyF9", "KeyHome", "KeyIc", "KeyIl", "KeyLeft", + "KeyLl", "KeyNpage", "KeyPpage", "KeyRight", "KeySf", "KeySr", "KeyStab", "KeyUp", + "KeypadLocal", "KeypadXmit", "LabF0", "LabF1", "LabF10", "LabF2", "LabF3", "LabF4", "LabF5", + "LabF6", "LabF7", "LabF8", "LabF9", "MetaOff", "MetaOn", "Newline", "PadChar", "ParmDch", + "ParmDeleteLine", "ParmDownCursor", "ParmIch", "ParmIndex", "ParmInsertLine", "ParmLeftCursor", + "ParmRightCursor", "ParmRindex", "ParmUpCursor", "PkeyKey", "PkeyLocal", "PkeyXmit", + "PrintScreen", "PrtrOff", "PrtrOn", "RepeatChar", "Reset1string", "Reset2string", + "Reset3string", "ResetFile", "RestoreCursor", "RowAddress", "SaveCursor", "ScrollForward", + "ScrollReverse", "SetAttributes", "SetTab", "SetWindow", "Tab", "ToStatusLine", "UnderlineChar", + "UpHalfLine", "InitProg", "KeyA1", "KeyA3", "KeyB2", "KeyC1", "KeyC3", "PrtrNon", "CharPadding", + "AcsChars", "PlabNorm", "KeyBtab", "EnterXonMode", "ExitXonMode", "EnterAmMode", "ExitAmMode", + "XonCharacter", "XoffCharacter", "EnaAcs", "LabelOn", "LabelOff", "KeyBeg", "KeyCancel", + "KeyClose", "KeyCommand", "KeyCopy", "KeyCreate", "KeyEnd", "KeyEnter", "KeyExit", "KeyFind", + "KeyHelp", "KeyMark", "KeyMessage", "KeyMove", "KeyNext", "KeyOpen", "KeyOptions", + "KeyPrevious", "KeyPrint", "KeyRedo", "KeyReference", "KeyRefresh", "KeyReplace", "KeyRestart", + "KeyResume", "KeySave", "KeySuspend", "KeyUndo", "KeySbeg", "KeyScancel", "KeyScommand", + "KeyScopy", "KeyScreate", "KeySdc", "KeySdl", "KeySelect", "KeySend", "KeySeol", "KeySexit", + "KeySfind", "KeyShelp", "KeyShome", "KeySic", "KeySleft", "KeySmessage", "KeySmove", "KeySnext", + "KeySoptions", "KeySprevious", "KeySprint", "KeySredo", "KeySreplace", "KeySright", "KeySrsume", + "KeySsave", "KeySsuspend", "KeySundo", "ReqForInput", "KeyF11", "KeyF12", "KeyF13", "KeyF14", + "KeyF15", "KeyF16", "KeyF17", "KeyF18", "KeyF19", "KeyF20", "KeyF21", "KeyF22", "KeyF23", + "KeyF24", "KeyF25", "KeyF26", "KeyF27", "KeyF28", "KeyF29", "KeyF30", "KeyF31", "KeyF32", + "KeyF33", "KeyF34", "KeyF35", "KeyF36", "KeyF37", "KeyF38", "KeyF39", "KeyF40", "KeyF41", + "KeyF42", "KeyF43", "KeyF44", "KeyF45", "KeyF46", "KeyF47", "KeyF48", "KeyF49", "KeyF50", + "KeyF51", "KeyF52", "KeyF53", "KeyF54", "KeyF55", "KeyF56", "KeyF57", "KeyF58", "KeyF59", + "KeyF60", "KeyF61", "KeyF62", "KeyF63", "ClrBol", "ClearMargins", "SetLeftMargin", + "SetRightMargin", "LabelFormat", "SetClock", "DisplayClock", "RemoveClock", "CreateWindow", + "GotoWindow", "Hangup", "DialPhone", "QuickDial", "Tone", "Pulse", "FlashHook", "FixedPause", + "WaitTone", "User0", "User1", "User2", "User3", "User4", "User5", "User6", "User7", "User8", + "User9", "OrigPair", "OrigColors", "InitializeColor", "InitializePair", "SetColorPair", + "SetForeground", "SetBackground", "ChangeCharPitch", "ChangeLinePitch", "ChangeResHorz", + "ChangeResVert", "DefineChar", "EnterDoublewideMode", "EnterDraftQuality", "EnterItalicsMode", + "EnterLeftwardMode", "EnterMicroMode", "EnterNearLetterQuality", "EnterNormalQuality", + "EnterShadowMode", "EnterSubscriptMode", "EnterSuperscriptMode", "EnterUpwardMode", + "ExitDoublewideMode", "ExitItalicsMode", "ExitLeftwardMode", "ExitMicroMode", "ExitShadowMode", + "ExitSubscriptMode", "ExitSuperscriptMode", "ExitUpwardMode", "MicroColumnAddress", "MicroDown", + "MicroLeft", "MicroRight", "MicroRowAddress", "MicroUp", "OrderOfPins", "ParmDownMicro", + "ParmLeftMicro", "ParmRightMicro", "ParmUpMicro", "SelectCharSet", "SetBottomMargin", + "SetBottomMarginParm", "SetLeftMarginParm", "SetRightMarginParm", "SetTopMargin", + "SetTopMarginParm", "StartBitImage", "StartCharSetDef", "StopBitImage", "StopCharSetDef", + "SubscriptCharacters", "SuperscriptCharacters", "TheseCauseCr", "ZeroMotion", "CharSetNames", + "KeyMouse", "MouseInfo", "ReqMousePos", "GetMouse", "SetAForeground", "SetABackground", + "PkeyPlab", "DeviceType", "CodeSetInit", "Set0DesSeq", "Set1DesSeq", "Set2DesSeq", "Set3DesSeq", + "SetLrMargin", "SetTbMargin", "BitImageRepeat", "BitImageNewline", "BitImageCarriageReturn", + "ColorNames", "DefineBitImageRegion", "EndBitImageRegion", "SetColorBand", "SetPageLength", + "DisplayPcChar", "EnterPcCharsetMode", "ExitPcCharsetMode", "EnterScancodeMode", + "ExitScancodeMode", "PcTermOptions", "ScancodeEscape", "AltScancodeEsc", + "EnterHorizontalHlMode", "EnterLeftHlMode", "EnterLowHlMode", "EnterRightHlMode", + "EnterTopHlMode", "EnterVerticalHlMode", "SetAAttributes", "SetPglenInch", "TermcapInit2", + "TermcapReset", "LinefeedIfNotLf", "BackspaceIfNotBs", "OtherNonFunctionKeys", "ArrowKeyMap", + "AcsUlcorner", "AcsLlcorner", "AcsUrcorner", "AcsLrcorner", "AcsLtee", "AcsRtee", "AcsBtee", + "AcsTtee", "AcsHline", "AcsVline", "AcsPlus", "MemoryLock", "MemoryUnlock", "BoxChars1" }; + +/////////////////////////////////////////////////////////////////////////// +// senf::term::Terminfo + +prefix_ senf::term::Terminfo::Terminfo() +{} + +prefix_ senf::term::Terminfo::Terminfo(std::string const & term) +{ + load(term); +} + +prefix_ void senf::term::Terminfo::load(std::string const & term) +{ + std::string filename (findTerminfo(term)); + std::ifstream is (filename.c_str()); + if (!is) + throw InvalidTerminfoException(); + load(is); +} + +prefix_ bool senf::term::Terminfo::getFlag(properties::Boolean p) + const +{ + if (BoolVec::size_type(p) >= booleans_.size()) + return false; + return booleans_[p]; +} + +prefix_ senf::term::Terminfo::number_t senf::term::Terminfo::getNumber(properties::Numeric p) + const +{ + if (NumberVec::size_type(p) >= numbers_.size()) + return NoValue; + return numbers_[p]; +} + +prefix_ senf::term::Terminfo::string_t senf::term::Terminfo::getString(properties::String p) + const +{ + if (StringVec::size_type(p) >= strings_.size()) + return 0; + return strings_[p]; +} + + prefix_ void senf::term::Terminfo::dump(std::ostream & os) + const + { + os << "Terminfo entry: " << name_ << "\n"; + os << "Booleans: " << booleans_.size() << "\n"; + os << "Numbers: " << numbers_.size() << "\n"; + os << "Strings: " << strings_.size() << "\n"; + os << "String pool size: " << stringPool_.size() << "\n"; + + { + os << "Flags:\n"; + unsigned n (0); + BoolVec::const_iterator i (booleans_.begin()); + BoolVec::const_iterator const i_end (booleans_.end()); + for (; i != i_end; ++i, ++n) + if (*i && n < sizeof(properties::BooleanNames)/sizeof(properties::BooleanNames[0])) + os << " " << properties::BooleanNames[n] << "\n"; + } + + { + os << "Numbers:\n"; + unsigned n (0); + NumberVec::const_iterator i (numbers_.begin()); + NumberVec::const_iterator const i_end (numbers_.end()); + for (; i != i_end; ++i, ++n) + if (*i != NoValue + && n < sizeof(properties::NumericNames)/sizeof(properties::NumericNames[0])) + os << " " << properties::NumericNames[n] << " = " << *i << "\n"; + } + + { + os << "Strings:\n"; + unsigned n (0); + StringVec::const_iterator i (strings_.begin()); + StringVec::const_iterator const i_end (strings_.end()); + for (; i != i_end; ++i, ++n) + if (*i && n < sizeof(properties::StringNames)/sizeof(properties::StringNames[0])) { + os << " " << std::setw(32) << properties::StringNames[n] << " = "; + hexdump(*i, *i + strlen(*i), os, 32); + } + } + +} + +prefix_ std::string senf::term::Terminfo::findTerminfo(std::string const & name) +{ + boost::filesystem::path subdir (name.substr(0,1)); subdir /= name; + boost::filesystem::path tientry, tipath; + + { + char const * tivar (::getenv("TERMINFO")); + if (tivar) { + tipath = tivar; + tientry = tipath / subdir; + if (boost::filesystem::exists(tientry)) return tientry.native_file_string(); + } + } + + tipath = "/etc/terminfo"; + tientry = tipath / subdir; + if (boost::filesystem::exists(tientry)) return tientry.native_file_string(); + + tipath = "/lib/terminfo"; + tientry = tipath / subdir; + if (boost::filesystem::exists(tientry)) return tientry.native_file_string(); + + tipath = "/usr/share/terminfo"; + tientry = tipath / subdir; + if (boost::filesystem::exists(tientry)) return tientry.native_file_string(); + + return ""; +} + +namespace { + + boost::uint16_t const TerminfoMagic = 0x011A; + + struct TerminfoHeader { + boost::uint16_t magic; + boost::uint16_t namesSz; + boost::uint16_t nBooleans; + boost::uint16_t nNumbers; + boost::uint16_t nStrings; + boost::uint16_t stringPoolSz; + }; + +} + +prefix_ void senf::term::Terminfo::load(std::istream & is) +{ + TerminfoHeader h; + is.read(static_cast(static_cast(&h)), sizeof(h)); + if (h.magic != TerminfoMagic) + throw InvalidTerminfoException(); + + name_.resize(h.namesSz); + is.read(&(name_[0]), name_.size()); + { + std::string::size_type n (name_.find('\0')); + if (n != std::string::npos) + name_.erase(n); + } + + booleans_.resize(h.nBooleans); + for (BoolVec::iterator i (booleans_.begin()); i != booleans_.end(); ++i) { + char v; + is.read(&v, sizeof(v)); + *i = v; + } + if (booleans_.size() & 1) + is.ignore(1u); + + numbers_.resize(h.nNumbers); + for (NumberVec::iterator i (numbers_.begin()); i != numbers_.end(); ++i) { + number_t v; + is.read(static_cast(static_cast(&v)), sizeof(v)); + *i = v; + } + + typedef std::vector OffsetVec; + OffsetVec offsets; + offsets.resize (h.nStrings); + for (OffsetVec::iterator i (offsets.begin()); i != offsets.end(); ++i) { + number_t v; + is.read(static_cast(static_cast(&v)), sizeof(v)); + *i = v; + } + + stringPool_.resize(h.stringPoolSz); + is.read(&(stringPool_[0]), stringPool_.size()); + + strings_.resize(offsets.size()); + StringVec::iterator j (strings_.begin()); + for (OffsetVec::iterator i (offsets.begin()); i != offsets.end(); ++i, ++j) + if (*i != NoValue) + *j = &(stringPool_[0]) + *i; +} + +/////////////////////////////////////////////////////////////////////////// +// senf::term::KeyParser + +char const * const senf::term::KeyParser::KeyNames[] = { + "Esc", "Backspace", "Backtab", "Begin", "CATab", "CTab", "Cancel", "Center", "Clear", + "ClearToEOL", "ClearToEOS", "Close", "Command", "Copy", "Create", "Delete", "DeleteLine", + "Down", "DownLeft", "DownRight", "End", "Enter", "Exit", "F0", "F1", "F2", "F3", "F4", "F5", + "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "F19", + "F20", "F21", "F22", "F23", "F24", "F25", "F26", "F27", "F28", "F29", "F30", "F31", "F32", + "F33", "F34", "F35", "F36", "F37", "F38", "F39", "F40", "F41", "F42", "F43", "F44", "F45", + "F46", "F47", "F48", "F49", "F50", "F51", "F52", "F53", "F54", "F55", "F56", "F57", "F58", + "F59", "F60", "F61", "F62", "F63", "Find", "Help", "Home", "Insert", "InsertLine", "Left", + "Mark", "Message", "Mouse", "Move", "Next", "Open", "Options", "PageDown", "PageUp", "Previous", + "Print", "Redo", "Reference", "Refresh", "Replace", "Restart", "Resume", "Right", "Save", + "Select", "ShiftBegin", "ShiftCancel", "ShiftCommand", "ShiftCopy", "ShiftCreate", + "ShiftDelete", "ShiftDeleteLine", "ShiftEnd", "ShiftClearToEOL", "ShiftExit", "ShiftFind", + "ShiftHelp", "ShiftHome", "ShiftInsert", "ShiftLeft", "ShiftMessage", "ShiftMove", "ShiftNext", + "ShiftOptions", "ShiftPrevious", "ShiftPrint", "ShiftRedo", "ShiftReplace", "ShiftResume", + "ShiftRight", "ShiftSave", "ShiftSuspend", "ShiftTab", "ShiftUndo", "Suspend", "Undo", "Up", + "UpLeft", "UpRight" }; + +prefix_ senf::term::KeyParser::KeyParser() +{} + +prefix_ senf::term::KeyParser::KeyParser(Terminfo const & ti) +{ + load(ti); +} + +prefix_ void senf::term::KeyParser::load(Terminfo const & ti) +{ + static Terminfo::properties::String keyStrings [] = { + Terminfo::properties::KeyCommand, Terminfo::properties::KeyBackspace, + Terminfo::properties::KeyBtab, Terminfo::properties::KeyBeg, Terminfo::properties::KeyCatab, + Terminfo::properties::KeyCtab, Terminfo::properties::KeyCancel, Terminfo::properties::KeyB2, + Terminfo::properties::KeyClear, Terminfo::properties::KeyEol, Terminfo::properties::KeyEos, + Terminfo::properties::KeyClose, Terminfo::properties::KeyCommand, + Terminfo::properties::KeyCopy, Terminfo::properties::KeyCreate, Terminfo::properties::KeyDc, + Terminfo::properties::KeyDl, Terminfo::properties::KeyDown, Terminfo::properties::KeyC1, + Terminfo::properties::KeyC3, Terminfo::properties::KeyEnd, Terminfo::properties::KeyEnter, + Terminfo::properties::KeyExit, Terminfo::properties::KeyF0, Terminfo::properties::KeyF1, + Terminfo::properties::KeyF2, Terminfo::properties::KeyF3, Terminfo::properties::KeyF4, + Terminfo::properties::KeyF5, Terminfo::properties::KeyF6, Terminfo::properties::KeyF7, + Terminfo::properties::KeyF8, Terminfo::properties::KeyF9, Terminfo::properties::KeyF10, + Terminfo::properties::KeyF11, Terminfo::properties::KeyF12, Terminfo::properties::KeyF13, + Terminfo::properties::KeyF14, Terminfo::properties::KeyF15, Terminfo::properties::KeyF16, + Terminfo::properties::KeyF17, Terminfo::properties::KeyF18, Terminfo::properties::KeyF19, + Terminfo::properties::KeyF20, Terminfo::properties::KeyF21, Terminfo::properties::KeyF22, + Terminfo::properties::KeyF23, Terminfo::properties::KeyF24, Terminfo::properties::KeyF25, + Terminfo::properties::KeyF26, Terminfo::properties::KeyF27, Terminfo::properties::KeyF28, + Terminfo::properties::KeyF29, Terminfo::properties::KeyF30, Terminfo::properties::KeyF31, + Terminfo::properties::KeyF32, Terminfo::properties::KeyF33, Terminfo::properties::KeyF34, + Terminfo::properties::KeyF35, Terminfo::properties::KeyF36, Terminfo::properties::KeyF37, + Terminfo::properties::KeyF38, Terminfo::properties::KeyF39, Terminfo::properties::KeyF40, + Terminfo::properties::KeyF41, Terminfo::properties::KeyF42, Terminfo::properties::KeyF43, + Terminfo::properties::KeyF44, Terminfo::properties::KeyF45, Terminfo::properties::KeyF46, + Terminfo::properties::KeyF47, Terminfo::properties::KeyF48, Terminfo::properties::KeyF49, + Terminfo::properties::KeyF50, Terminfo::properties::KeyF51, Terminfo::properties::KeyF52, + Terminfo::properties::KeyF53, Terminfo::properties::KeyF54, Terminfo::properties::KeyF55, + Terminfo::properties::KeyF56, Terminfo::properties::KeyF57, Terminfo::properties::KeyF58, + Terminfo::properties::KeyF59, Terminfo::properties::KeyF60, Terminfo::properties::KeyF61, + Terminfo::properties::KeyF62, Terminfo::properties::KeyF63, Terminfo::properties::KeyFind, + Terminfo::properties::KeyHelp, Terminfo::properties::KeyHome, Terminfo::properties::KeyIc, + Terminfo::properties::KeyIl, Terminfo::properties::KeyLeft, Terminfo::properties::KeyMark, + Terminfo::properties::KeyMessage, Terminfo::properties::KeyMouse, + Terminfo::properties::KeyMove, Terminfo::properties::KeyNext, Terminfo::properties::KeyOpen, + Terminfo::properties::KeyOptions, Terminfo::properties::KeyNpage, + Terminfo::properties::KeyPpage, Terminfo::properties::KeyPrevious, + Terminfo::properties::KeyPrint, Terminfo::properties::KeyRedo, + Terminfo::properties::KeyReference, Terminfo::properties::KeyRefresh, + Terminfo::properties::KeyReplace, Terminfo::properties::KeyRestart, + Terminfo::properties::KeyResume, Terminfo::properties::KeyRight, + Terminfo::properties::KeySave, Terminfo::properties::KeySelect, + Terminfo::properties::KeySbeg, Terminfo::properties::KeyScancel, + Terminfo::properties::KeyScommand, Terminfo::properties::KeyScopy, + Terminfo::properties::KeyScreate, Terminfo::properties::KeySdc, + Terminfo::properties::KeySdl, Terminfo::properties::KeySend, Terminfo::properties::KeySeol, + Terminfo::properties::KeySexit, Terminfo::properties::KeySfind, + Terminfo::properties::KeyShelp, Terminfo::properties::KeyShome, + Terminfo::properties::KeySic, Terminfo::properties::KeySleft, + Terminfo::properties::KeySmessage, Terminfo::properties::KeySmove, + Terminfo::properties::KeySnext, Terminfo::properties::KeySoptions, + Terminfo::properties::KeySprevious, Terminfo::properties::KeySprint, + Terminfo::properties::KeySredo, Terminfo::properties::KeySreplace, + Terminfo::properties::KeySrsume, Terminfo::properties::KeySright, + Terminfo::properties::KeySsave, Terminfo::properties::KeySsuspend, + Terminfo::properties::KeyStab, Terminfo::properties::KeySundo, + Terminfo::properties::KeySuspend, Terminfo::properties::KeyUndo, + Terminfo::properties::KeyUp, Terminfo::properties::KeyA1, Terminfo::properties::KeyA3 }; + + table_.clear(); + for (unsigned i (0); i < sizeof(keyStrings)/sizeof(keyStrings[0]); ++i) { + char const * key (ti.getString(keyStrings[i])); + if (key) + table_.insert(std::make_pair(key, KeyCode(i+First))); + } +} + +prefix_ std::pair +senf::term::KeyParser::lookup(std::string const & key) + const +{ + if (key.empty()) + return std::make_pair(KeyCode(0), 0); + + // There are several cases: + // a) 'key' is an incomplete key sequence. In this case, 'key' will precede all completions in + // the key table. The first possible completion is found by 'upper_bound' + // b) 'key' is a complete key sequence. This is the key sequence *preceding* the 'upper_bound' + // c) 'key' is a complete key sequence with additional trailing characters. In this case, 'key' + // will follow the correct entry in the key table. Again, the correct key sequence is + // the one preceding the 'upper_bound' + + Keytable::const_iterator i (table_.upper_bound(key)); + if (i != table_.end() && i->first.substr(0, key.size()) == key) + return std::make_pair(Incomplete, key.size()); + if (i == table_.begin()) + return std::make_pair(keycode_t(key[0]), 1); + --i; + if (key.substr(0, i->first.size()) == i->first) + return std::make_pair(i->second, i->first.size()); + return std::make_pair(keycode_t(key[0]), 1); +} + +prefix_ std::string senf::term::KeyParser::describe(keycode_t key) +{ + if (key < keycode_t(' ')) + return "^" + std::string(1, '@' + key); + if (key < 256) + return std::string(1, char(key)); + if (key >= keycode_t(First) && key < keycode_t(First + sizeof(KeyNames) / sizeof(KeyNames[0]))) + return std::string(KeyNames[key-First]); + else + return "<" + boost::lexical_cast(unsigned(key)) + ">"; +} + +prefix_ void senf::term::KeyParser::dump(std::ostream & os) + const +{ + os << "Keytable:\n"; + for (Keytable::const_iterator i (table_.begin()); i != table_.end(); ++i) { + unsigned index (i->second - First); + if (index < sizeof(KeyNames)/sizeof(KeyNames[0])) { + std::cout << " " << std::setw(32) << KeyNames[index] << ": "; + hexdump(i->first.begin(), i->first.end(), os); + } + } +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "Terminfo.mpp" + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/Utils/Termlib/Terminfo.hh b/Utils/Termlib/Terminfo.hh new file mode 100644 index 0000000..c34a568 --- /dev/null +++ b/Utils/Termlib/Terminfo.hh @@ -0,0 +1,253 @@ +// $Id$ +// +// Copyright (C) 2009 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief Terminfo public header */ + +#ifndef HH_SENF_Utils_Termlib_Terminfo_ +#define HH_SENF_Utils_Termlib_Terminfo_ 1 + +// Custom includes +#include +#include +#include +#include +#include +#include +#include + +//#include "Terminfo.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace senf { +namespace term { + + class Terminfo + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + enum Color { + Black, Red, Green, Brown, Blue, Magenta, Cyan, LightGray, DarkGray, LightRed, + LightGreen, Yellow, LightBlue, Pink, LightCyan, White, + Preserve, LastColor = Preserve }; + + enum Attribute { + Standout, Underline, Reverse, Blink, HalfBright, Bold, Invisible, Protect, AltCharset, + Italic, Substript, Superscript, LastAttribute }; + + enum { NoValue = -1 }; + + struct properties + { + enum Boolean { + AutoLeftMargin, AutoRightMargin, NoEscCtlc, CeolStandoutGlitch, EatNewlineGlitch, + EraseOverstrike, GenericType, HardCopy, HasMetaKey, HasStatusLine, InsertNullGlitch, + MemoryAbove, MemoryBelow, MoveInsertMode, MoveStandoutMode, OverStrike, + StatusLineEscOk, DestTabsMagicSmso, TildeGlitch, TransparentUnderline, XonXoff, + NeedsXonXoff, PrtrSilent, HardCursor, NonRevRmcup, NoPadChar, NonDestScrollRegion, + CanChange, BackColorErase, HueLightnessSaturation, ColAddrGlitch, + CrCancelsMicroMode, HasPrintWheel, RowAddrGlitch, SemiAutoRightMargin, + CpiChangesRes, LpiChangesRes, BackspacesWithBs, CrtNoScrolling, + NoCorrectlyWorkingCr, GnuHasMetaKey, LinefeedIsNewline, HasHardwareTabs, + ReturnDoesClrEol }; + + static char const * const BooleanNames[]; + + enum Numeric { + Columns, InitTabs, Lines, LinesOfMemory, MagicCookieGlitch, PaddingBaudRate, + VirtualTerminal, WidthStatusLine, NumLabels, LabelHeight, LabelWidth, MaxAttributes, + MaximumWindows, MaxColors, MaxPairs, NoColorVideo, BufferCapacity, DotVertSpacing, + DotHorzSpacing, MaxMicroAddress, MaxMicroJump, MicroColSize, MicroLineSize, + NumberOfPins, OutputResChar, OutputResLine, OutputResHorzInch, OutputResVertInch, + PrintRate, WideCharSize, Buttons, BitImageEntwining, BitImageType, + MagicCookieGlitchUl, CarriageReturnDelay, NewLineDelay, BackspaceDelay, + HorizontalTabDelay, NumberOfFunctionKeys }; + + static char const * const NumericNames[]; + + enum String { + BackTab, Bell, CarriageReturn, ChangeScrollRegion, ClearAllTabs, ClearScreen, + ClrEol, ClrEos, ColumnAddress, CommandCharacter, CursorAddress, CursorDown, + CursorHome, CursorInvisible, CursorLeft, CursorMemAddress, CursorNormal, + CursorRight, CursorToLl, CursorUp, CursorVisible, DeleteCharacter, DeleteLine, + DisStatusLine, DownHalfLine, EnterAltCharsetMode, EnterBlinkMode, EnterBoldMode, + EnterCaMode, EnterDeleteMode, EnterDimMode, EnterInsertMode, EnterSecureMode, + EnterProtectedMode, EnterReverseMode, EnterStandoutMode, EnterUnderlineMode, + EraseChars, ExitAltCharsetMode, ExitAttributeMode, ExitCaMode, ExitDeleteMode, + ExitInsertMode, ExitStandoutMode, ExitUnderlineMode, FlashScreen, FormFeed, + FromStatusLine, Init1string, Init2string, Init3string, InitFile, InsertCharacter, + InsertLine, InsertPadding, KeyBackspace, KeyCatab, KeyClear, KeyCtab, KeyDc, KeyDl, + KeyDown, KeyEic, KeyEol, KeyEos, KeyF0, KeyF1, KeyF10, KeyF2, KeyF3, KeyF4, KeyF5, + KeyF6, KeyF7, KeyF8, KeyF9, KeyHome, KeyIc, KeyIl, KeyLeft, KeyLl, KeyNpage, + KeyPpage, KeyRight, KeySf, KeySr, KeyStab, KeyUp, KeypadLocal, KeypadXmit, LabF0, + LabF1, LabF10, LabF2, LabF3, LabF4, LabF5, LabF6, LabF7, LabF8, LabF9, MetaOff, + MetaOn, Newline, PadChar, ParmDch, ParmDeleteLine, ParmDownCursor, ParmIch, + ParmIndex, ParmInsertLine, ParmLeftCursor, ParmRightCursor, ParmRindex, + ParmUpCursor, PkeyKey, PkeyLocal, PkeyXmit, PrintScreen, PrtrOff, PrtrOn, + RepeatChar, Reset1string, Reset2string, Reset3string, ResetFile, RestoreCursor, + RowAddress, SaveCursor, ScrollForward, ScrollReverse, SetAttributes, SetTab, + SetWindow, Tab, ToStatusLine, UnderlineChar, UpHalfLine, InitProg, KeyA1, KeyA3, + KeyB2, KeyC1, KeyC3, PrtrNon, CharPadding, AcsChars, PlabNorm, KeyBtab, + EnterXonMode, ExitXonMode, EnterAmMode, ExitAmMode, XonCharacter, XoffCharacter, + EnaAcs, LabelOn, LabelOff, KeyBeg, KeyCancel, KeyClose, KeyCommand, KeyCopy, + KeyCreate, KeyEnd, KeyEnter, KeyExit, KeyFind, KeyHelp, KeyMark, KeyMessage, + KeyMove, KeyNext, KeyOpen, KeyOptions, KeyPrevious, KeyPrint, KeyRedo, KeyReference, + KeyRefresh, KeyReplace, KeyRestart, KeyResume, KeySave, KeySuspend, KeyUndo, + KeySbeg, KeyScancel, KeyScommand, KeyScopy, KeyScreate, KeySdc, KeySdl, KeySelect, + KeySend, KeySeol, KeySexit, KeySfind, KeyShelp, KeyShome, KeySic, KeySleft, + KeySmessage, KeySmove, KeySnext, KeySoptions, KeySprevious, KeySprint, KeySredo, + KeySreplace, KeySright, KeySrsume, KeySsave, KeySsuspend, KeySundo, ReqForInput, + KeyF11, KeyF12, KeyF13, KeyF14, KeyF15, KeyF16, KeyF17, KeyF18, KeyF19, KeyF20, + KeyF21, KeyF22, KeyF23, KeyF24, KeyF25, KeyF26, KeyF27, KeyF28, KeyF29, KeyF30, + KeyF31, KeyF32, KeyF33, KeyF34, KeyF35, KeyF36, KeyF37, KeyF38, KeyF39, KeyF40, + KeyF41, KeyF42, KeyF43, KeyF44, KeyF45, KeyF46, KeyF47, KeyF48, KeyF49, KeyF50, + KeyF51, KeyF52, KeyF53, KeyF54, KeyF55, KeyF56, KeyF57, KeyF58, KeyF59, KeyF60, + KeyF61, KeyF62, KeyF63, ClrBol, ClearMargins, SetLeftMargin, SetRightMargin, + LabelFormat, SetClock, DisplayClock, RemoveClock, CreateWindow, GotoWindow, Hangup, + DialPhone, QuickDial, Tone, Pulse, FlashHook, FixedPause, WaitTone, User0, User1, + User2, User3, User4, User5, User6, User7, User8, User9, OrigPair, OrigColors, + InitializeColor, InitializePair, SetColorPair, SetForeground, SetBackground, + ChangeCharPitch, ChangeLinePitch, ChangeResHorz, ChangeResVert, DefineChar, + EnterDoublewideMode, EnterDraftQuality, EnterItalicsMode, EnterLeftwardMode, + EnterMicroMode, EnterNearLetterQuality, EnterNormalQuality, EnterShadowMode, + EnterSubscriptMode, EnterSuperscriptMode, EnterUpwardMode, ExitDoublewideMode, + ExitItalicsMode, ExitLeftwardMode, ExitMicroMode, ExitShadowMode, ExitSubscriptMode, + ExitSuperscriptMode, ExitUpwardMode, MicroColumnAddress, MicroDown, MicroLeft, + MicroRight, MicroRowAddress, MicroUp, OrderOfPins, ParmDownMicro, ParmLeftMicro, + ParmRightMicro, ParmUpMicro, SelectCharSet, SetBottomMargin, SetBottomMarginParm, + SetLeftMarginParm, SetRightMarginParm, SetTopMargin, SetTopMarginParm, + StartBitImage, StartCharSetDef, StopBitImage, StopCharSetDef, SubscriptCharacters, + SuperscriptCharacters, TheseCauseCr, ZeroMotion, CharSetNames, KeyMouse, MouseInfo, + ReqMousePos, GetMouse, SetAForeground, SetABackground, PkeyPlab, DeviceType, + CodeSetInit, Set0DesSeq, Set1DesSeq, Set2DesSeq, Set3DesSeq, SetLrMargin, + SetTbMargin, BitImageRepeat, BitImageNewline, BitImageCarriageReturn, ColorNames, + DefineBitImageRegion, EndBitImageRegion, SetColorBand, SetPageLength, DisplayPcChar, + EnterPcCharsetMode, ExitPcCharsetMode, EnterScancodeMode, ExitScancodeMode, + PcTermOptions, ScancodeEscape, AltScancodeEsc, EnterHorizontalHlMode, + EnterLeftHlMode, EnterLowHlMode, EnterRightHlMode, EnterTopHlMode, + EnterVerticalHlMode, SetAAttributes, SetPglenInch, TermcapInit2, TermcapReset, + LinefeedIfNotLf, BackspaceIfNotBs, OtherNonFunctionKeys, ArrowKeyMap, AcsUlcorner, + AcsLlcorner, AcsUrcorner, AcsLrcorner, AcsLtee, AcsRtee, AcsBtee, AcsTtee, AcsHline, + AcsVline, AcsPlus, MemoryLock, MemoryUnlock, BoxChars1 }; + + static char const * const StringNames[]; + }; + + typedef boost::int16_t number_t; + typedef char const* string_t; + + /////////////////////////////////////////////////////////////////////////// + + Terminfo(); + explicit Terminfo(std::string const & term); + void load(std::string const & term); + + bool getFlag(properties::Boolean p) const; + number_t getNumber(properties::Numeric p) const; + string_t getString(properties::String p) const; + + void dump(std::ostream & os) const; + + struct InvalidTerminfoException : public senf::Exception + { InvalidTerminfoException() : senf::Exception("Unreadable terminfo file") {} }; + + private: + typedef std::vector BoolVec; + typedef std::vector NumberVec; + typedef std::vector StringVec; + typedef std::vector StringPool; + + std::string findTerminfo(std::string const & name); + void load(std::istream & is); + + std::string name_; + BoolVec booleans_; + NumberVec numbers_; + StringVec strings_; + StringPool stringPool_; + }; + + + class KeyParser + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + enum KeyCode { + Space = ' ', Tab = '\t', First = 0xE000, Esc = First, Backspace, Backtab, Begin, CATab, + CTab, Cancel, Center, Clear, ClearToEOL, ClearToEOS, Close, Command, Copy, Create, + Delete, DeleteLine, Down, DownLeft, DownRight, End, Enter, Exit, F0, F1, F2, F3, F4, F5, + F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, + F24, F25, F26, F27, F28, F29, F30, F31, F32, F33, F34, F35, F36, F37, F38, F39, F40, + F41, F42, F43, F44, F45, F46, F47, F48, F49, F50, F51, F52, F53, F54, F55, F56, F57, + F58, F59, F60, F61, F62, F63, Find, Help, Home, Insert, InsertLine, Left, Mark, Message, + Mouse, Move, Next, Open, Options, PageDown, PageUp, Previous, Print, Redo, Reference, + Refresh, Replace, Restart, Resume, Right, Save, Select, ShiftBegin, ShiftCancel, + ShiftCommand, ShiftCopy, ShiftCreate, ShiftDelete, ShiftDeleteLine, ShiftEnd, + ShiftClearToEOL, ShiftExit, ShiftFind, ShiftHelp, ShiftHome, ShiftInsert, ShiftLeft, + ShiftMessage, ShiftMove, ShiftNext, ShiftOptions, ShiftPrevious, ShiftPrint, ShiftRedo, + ShiftReplace, ShiftResume, ShiftRight, ShiftSave, ShiftSuspend, ShiftTab, ShiftUndo, + Suspend, Undo, Up, UpLeft, UpRight, Incomplete = 0xE0FF }; + + static char const * const KeyNames[]; + + typedef wchar_t keycode_t; + typedef std::string::size_type size_type; + + /////////////////////////////////////////////////////////////////////////// + + KeyParser(); + explicit KeyParser(Terminfo const & ti); + void load(Terminfo const & ti); + + std::pair lookup(std::string const & key) const; + static std::string describe(keycode_t key); + + void dump(std::ostream & os) const; + + private: + typedef std::map Keytable; + + Keytable table_; + }; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "Terminfo.cci" +//#include "Terminfo.ct" +//#include "Terminfo.cti" +#endif + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/Utils/Termlib/Terminfo.test.cc b/Utils/Termlib/Terminfo.test.cc new file mode 100644 index 0000000..8ef55b3 --- /dev/null +++ b/Utils/Termlib/Terminfo.test.cc @@ -0,0 +1,91 @@ +// $Id$ +// +// Copyright (C) 2009 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief Terminfo.test unit tests */ + +//#include "Terminfo.test.hh" +//#include "Terminfo.test.ih" + +// Custom includes +#include "Terminfo.hh" + +#include "../../Utils/auto_unit_test.hh" +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +namespace { + typedef std::pair Pair; +} + +namespace std { + + std::ostream & operator<<(std::ostream & os, Pair const & pair) + { + os << '(' << pair.first << ',' << pair.second << ')'; + return os; + } +} + +BOOST_AUTO_UNIT_TEST(terminfo) +{ + senf::term::Terminfo ifo ("vt220"); + senf::term::KeyParser kp (ifo); + + //ifo.dump(std::cout); + //kp.dump(std::cout); + + BOOST_CHECK_EQUAL( kp.lookup("\e[5\x7e"), + Pair(senf::term::KeyParser::PageUp, 4u) ); + BOOST_CHECK_EQUAL( kp.lookup("\e"), + Pair(senf::term::KeyParser::Incomplete, 1u) ); + BOOST_CHECK_EQUAL( kp.lookup("\e["), + Pair(senf::term::KeyParser::Incomplete, 2u) ); + BOOST_CHECK_EQUAL( kp.lookup("\e[A"), + Pair(senf::term::KeyParser::Up, 3u) ); + BOOST_CHECK_EQUAL( kp.lookup("\e[\e"), + Pair(senf::term::KeyParser::keycode_t('\e'), 1u) ); + BOOST_CHECK_EQUAL( kp.lookup("a\e[Ab"), + Pair(senf::term::KeyParser::keycode_t('a'), 1u) ); + BOOST_CHECK_EQUAL( kp.lookup("\e[Ab"), + Pair(senf::term::KeyParser::Up, 3u) ); + BOOST_CHECK_EQUAL( kp.lookup("b"), + Pair(senf::term::KeyParser::keycode_t('b'), 1u) ); + BOOST_CHECK_EQUAL( kp.lookup(""), + Pair(senf::term::KeyParser::keycode_t('\0'), 0u) ); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/Utils/Console/Telnet.test.cc b/Utils/Termlib/main.test.cc similarity index 88% rename from Utils/Console/Telnet.test.cc rename to Utils/Termlib/main.test.cc index 124897d..c6b4f24 100644 --- a/Utils/Console/Telnet.test.cc +++ b/Utils/Termlib/main.test.cc @@ -1,6 +1,6 @@ // $Id$ // -// Copyright (C) 2008 +// Copyright (C) 2006 // Fraunhofer Institute for Open Communication Systems (FOKUS) // Competence Center NETwork research (NET), St. Augustin, GERMANY // Stefan Bund @@ -20,23 +20,19 @@ // Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -/** \file - \brief Telnet.test unit tests */ +// Definition of non-inline non-template functions -//#include "Telnet.test.hh" -//#include "Telnet.test.ih" +//#include "test.hh" +//#include "test.ih" // Custom includes -#include "Telnet.hh" - +#define BOOST_AUTO_TEST_MAIN #include "../../Utils/auto_unit_test.hh" #include #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// -BOOST_AUTO_UNIT_TEST(telnet) -{} ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ @@ -45,9 +41,9 @@ BOOST_AUTO_UNIT_TEST(telnet) // Local Variables: // mode: c++ // fill-column: 100 -// comment-column: 40 // c-file-style: "senf" // indent-tabs-mode: nil // ispell-local-dictionary: "american" // compile-command: "scons -u test" +// comment-column: 40 // End: diff --git a/Utils/Console/telnetServer.cc b/Utils/Termlib/telnetServer.cc similarity index 81% rename from Utils/Console/telnetServer.cc rename to Utils/Termlib/telnetServer.cc index 95f290c..da4c15a 100644 --- a/Utils/Console/telnetServer.cc +++ b/Utils/Termlib/telnetServer.cc @@ -28,7 +28,7 @@ // Custom includes #include -#include "Telnet.hh" +#include "TelnetTerminal.hh" #include "../../Scheduler/Scheduler.hh" #include "../Logger.hh" #include "../../Socket/Protocols/INet.hh" @@ -39,23 +39,15 @@ namespace { - class MyTelnet - : public virtual senf::console::detail::BaseTelnetProtocol, - public senf::console::detail::telnethandler::TerminalType, - public senf::console::detail::telnethandler::NAWS + class MyTelnet : public senf::term::TelnetTerminal { public: - explicit MyTelnet(Handle handle) : senf::console::detail::BaseTelnetProtocol(handle) - { - requestPeerOption(senf::console::detail::telnetopt::SUPPRESS_GO_AHEAD); - requestLocalOption(senf::console::detail::telnetopt::SUPPRESS_GO_AHEAD); - requestLocalOption(senf::console::detail::telnetopt::ECHO); - } + explicit MyTelnet(Handle handle) : senf::term::BaseTelnetProtocol(handle) {} private: - virtual void v_charReceived(char c) + virtual void v_keyReceived(keycode_t key) { - SENF_LOG(("Char: " << c)); + SENF_LOG(("Key " << senf::term::KeyParser::describe(key))); } virtual void v_eof() @@ -66,6 +58,7 @@ namespace { virtual void v_setupComplete() { + TelnetTerminal::v_setupComplete(); SENF_LOG(("Terminal type is '" << terminalType() << "', window size is " << width() << "x" << height())); } diff --git a/Utils/hexdump.cc b/Utils/hexdump.cc index 9f08553..3cf9b73 100644 --- a/Utils/hexdump.cc +++ b/Utils/hexdump.cc @@ -33,7 +33,7 @@ #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// -prefix_ void senf::detail::HexDumper::operator()(unsigned ch) +prefix_ void senf::detail::HexDumper::operator()(unsigned char ch) { if ((offset_ % block_size_) == 0) { if (!ascii_.empty()) { @@ -48,7 +48,7 @@ prefix_ void senf::detail::HexDumper::operator()(unsigned ch) ascii_ += ' '; } os_ << ' ' << std::hex << std::setw(2) << std::setfill('0') - << ch; + << unsigned(ch); ascii_ += (ch >= ' ' && ch < 126) ? ch : '.'; ++ offset_; } diff --git a/Utils/hexdump.ih b/Utils/hexdump.ih index c03f51b..0acf34a 100644 --- a/Utils/hexdump.ih +++ b/Utils/hexdump.ih @@ -45,7 +45,7 @@ namespace detail { HexDumper(std::ostream & os, unsigned block_size); ~HexDumper(); - void operator()(unsigned ch); + void operator()(unsigned char ch); private: std::ostream & os_;