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()),
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 = ...;
###########################################################################
-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'])
--- /dev/null
+@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"
--- /dev/null
+# -*- 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'])
#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':
}
prefix_ void
-senf::console::detail::BaseTelnetProtocol::sendOptionParameters(option_type option,
+senf::term::BaseTelnetProtocol::sendOptionParameters(option_type option,
std::string const & data)
{
transmit(CMD_IAC);
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:
}
}
-prefix_ void senf::console::detail::BaseTelnetProtocol::handleNormalChar(char c)
+prefix_ void senf::term::BaseTelnetProtocol::handleNormalChar(char c)
{
switch (c) {
case '\r':
}
}
-prefix_ void senf::console::detail::BaseTelnetProtocol::handleCommand(char c)
+prefix_ void senf::term::BaseTelnetProtocol::handleCommand(char c)
{
switch (c) {
case CMD_SE:
}
}
-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':
}
}
-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;
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:
}
}
-prefix_ void senf::console::detail::BaseTelnetProtocol::processCommand()
+prefix_ void senf::term::BaseTelnetProtocol::processCommand()
{
switch (command_) {
case CMD_NONE:
}
}
-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();
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();
outputEvent_.disable();
}
-prefix_ void senf::console::detail::BaseTelnetProtocol::timeout()
+prefix_ void senf::term::BaseTelnetProtocol::timeout()
{
if (pendingRequests_ > 0u) {
pendingRequests_ = 0u;
}
}
-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())
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) {
}
}
-prefix_ void senf::console::detail::BaseTelnetProtocol::response(OptInfo & info, bool enabled)
+prefix_ void senf::term::BaseTelnetProtocol::response(OptInfo & info, bool enabled)
{
bool decrementCount (false);
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_;
}
///////////////////////////////////////////////////////////////////////////
-// 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)
}
}
-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;
///////////////////////////////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);
}
///////////////////////////////cti.p///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
-// senf::console::detail::BaseTelnetProtocol
+// senf::term::BaseTelnetProtocol
template <class Handler>
-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));
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
-namespace console {
-namespace detail {
+namespace term {
/** \brief Telnet server
\see
- <a href="http://tools.ietf.org/html/rfc854>RFC 854</a> The Telnet protocol \n
- <a href="http://tools.ietf.org/html/rfc854>RFC 855</a> Telnet option specifications
+ <a href="http://tools.ietf.org/html/rfc854">RFC 854</a> The Telnet protocol \n
+ <a href="http://tools.ietf.org/html/rfc854">RFC 855</a> Telnet option specifications
\todo SYNCH handling
*/
void decrementRequestCounter();
bool requestsPending();
- private:
-
#ifndef DOXYGEN
private:
#endif
}
-}}}
+}}
///////////////////////////////hh.e////////////////////////////////////////
#include "Telnet.cci"
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2009
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// 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 <senf/Utils/membind.hh>
+
+//#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<senf::term::KeyParser::keycode_t, std::string::size_type> 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"
+
+\f
+// 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:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2009
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// 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 <senf/Scheduler/TimerEvent.hh>
+#include <senf/Scheduler/ClockService.hh>
+#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
+
+\f
+// 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:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2009
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// 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 <fstream>
+#include <iomanip>
+#include <boost/filesystem/operations.hpp>
+#include <senf/config.hh>
+#include <senf/Utils/hexdump.hh>
+#include <unistd.h>
+#include <string.h>
+
+//#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<char*>(static_cast<void*>(&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<char*>(static_cast<void*>(&v)), sizeof(v));
+ *i = v;
+ }
+
+ typedef std::vector<number_t> OffsetVec;
+ OffsetVec offsets;
+ offsets.resize (h.nStrings);
+ for (OffsetVec::iterator i (offsets.begin()); i != offsets.end(); ++i) {
+ number_t v;
+ is.read(static_cast<char*>(static_cast<void*>(&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::keycode_t, std::string::size_type>
+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<std::string>(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"
+
+\f
+// 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:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2009
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// 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 <string>
+#include <vector>
+#include <map>
+#include <iostream>
+#include <boost/cstdint.hpp>
+#include <boost/array.hpp>
+#include <senf/Utils/Exception.hh>
+
+//#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<bool> BoolVec;
+ typedef std::vector<number_t> NumberVec;
+ typedef std::vector<string_t> StringVec;
+ typedef std::vector<char> 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<keycode_t, size_type> lookup(std::string const & key) const;
+ static std::string describe(keycode_t key);
+
+ void dump(std::ostream & os) const;
+
+ private:
+ typedef std::map<std::string, KeyCode> Keytable;
+
+ Keytable table_;
+ };
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+//#include "Terminfo.cci"
+//#include "Terminfo.ct"
+//#include "Terminfo.cti"
+#endif
+
+\f
+// 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:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2009
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// 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 <boost/test/test_tools.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+namespace {
+ typedef std::pair<senf::term::KeyParser::keycode_t, senf::term::KeyParser::size_type> 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_
+
+\f
+// 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:
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2006
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// 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 <boost/test/test_tools.hpp>
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
-BOOST_AUTO_UNIT_TEST(telnet)
-{}
///////////////////////////////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"
+// comment-column: 40
// End:
// Custom includes
#include <boost/bind.hpp>
-#include "Telnet.hh"
+#include "TelnetTerminal.hh"
#include "../../Scheduler/Scheduler.hh"
#include "../Logger.hh"
#include "../../Socket/Protocols/INet.hh"
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()
virtual void v_setupComplete()
{
+ TelnetTerminal::v_setupComplete();
SENF_LOG(("Terminal type is '" << terminalType() << "', window size is "
<< width() << "x" << height()));
}
#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()) {
ascii_ += ' ';
}
os_ << ' ' << std::hex << std::setw(2) << std::setfill('0')
- << ch;
+ << unsigned(ch);
ascii_ += (ch >= ' ' && ch < 126) ? ch : '.';
++ offset_;
}
HexDumper(std::ostream & os, unsigned block_size);
~HexDumper();
- void operator()(unsigned ch);
+ void operator()(unsigned char ch);
private:
std::ostream & os_;