diff --git a/Utils/Termlib/AbstractTerminal.hh b/Utils/Termlib/AbstractTerminal.hh index 01d72f712d0b03a87546cfeb4f75c92730587bae..f38a4b5ba4d1d9b34f633ee43288c42abcc00716 100644 --- a/Utils/Termlib/AbstractTerminal.hh +++ b/Utils/Termlib/AbstractTerminal.hh @@ -39,7 +39,7 @@ namespace term { { struct Callbacks { virtual ~Callbacks() {} - virtual void cb_init() = 0; + virtual bool cb_init() = 0; virtual void cb_charReceived(char ch) = 0; virtual void cb_windowSizeChanged() = 0; }; diff --git a/Utils/Termlib/Editor.cc b/Utils/Termlib/Editor.cc index 002332274fc07095c80ff4523efec9695bf31acd..57e1e78adc427fb91a88f042ac35c2037282ab4f 100644 --- a/Utils/Termlib/Editor.cc +++ b/Utils/Termlib/Editor.cc @@ -130,16 +130,21 @@ prefix_ unsigned senf::term::BaseEditor::currentColumn() return column_; } -prefix_ void senf::term::BaseEditor::cb_init() +prefix_ bool senf::term::BaseEditor::cb_init() { - tifo_.load(terminal_->terminalType()); - keyParser_.load(tifo_); + try { + tifo_.load(terminal_->terminalType()); + keyParser_.load(tifo_); + } + catch (Terminfo::InvalidTerminfoException & ex) { + return false; + } typedef Terminfo::properties p; if (! (tifo_.hasProperty(p::ClrEol) && (tifo_.hasProperty(p::ParmRightCursor) || tifo_.hasProperty(p::CursorRight)) && (tifo_.hasProperty(p::ParmLeftCursor) || tifo_.hasProperty(p::CursorLeft)))) - throw Terminfo::InvalidTerminfoException(); + return false; if (tifo_.hasProperty(Terminfo::properties::KeypadXmit)) write(tifo_.getString(Terminfo::properties::KeypadXmit)); @@ -220,6 +225,8 @@ prefix_ void senf::term::LineEditor::prompt(std::string const & text) { prompt_ = text; promptWidth_ = prompt_.size(); + if (promptWidth_ > width() - 4 && width() > 4) + promptWidth_ = width() - 4; editWidth_ = width() - promptWidth_ - 3; if (enabled_) redisplay(); @@ -278,7 +285,10 @@ prefix_ void senf::term::LineEditor::forceRedisplay() return; clearLine(); setBold(); - put(prompt_); + if (prompt_.size() > promptWidth_) + put(prompt_.substr(prompt_.size()-promptWidth_)); + else + put(prompt_); put( displayPos_ > 0 ? '<' : ' ' ); if (text_.size() > displayPos_ + editWidth_) { toColumn(editWidth_ + promptWidth_ + 1); @@ -367,23 +377,27 @@ prefix_ void senf::term::LineEditor::unsetKey(keycode_t key) bindings_.erase(key); } -prefix_ void senf::term::LineEditor::cb_init() +prefix_ bool senf::term::LineEditor::cb_init() { - BaseEditor::cb_init(); - editWidth_ = width() - promptWidth_ - 3; + if (!BaseEditor::cb_init()) + return false; + prompt(prompt_); forceRedisplay(); + return true; } prefix_ void senf::term::LineEditor::cb_windowSizeChanged() { BaseEditor::cb_windowSizeChanged(); - editWidth_ = width() - promptWidth_ - 3; + prompt(prompt_); gotoChar(point_); forceRedisplay(); } prefix_ void senf::term::LineEditor::v_keyReceived(keycode_t key) { + if (! enabled_) + return; lastKey_ = key; KeyMap::iterator i (bindings_.find(key)); if (i != bindings_.end()) diff --git a/Utils/Termlib/Editor.hh b/Utils/Termlib/Editor.hh index de94ae135e676bd259c08ab27e3ddd402aabc6b2..e5cb475cdc75745ea4358adc7144b74bc265fa25 100644 --- a/Utils/Termlib/Editor.hh +++ b/Utils/Termlib/Editor.hh @@ -61,7 +61,7 @@ namespace term { unsigned width(); protected: - virtual void cb_init(); + virtual bool cb_init(); virtual void cb_windowSizeChanged(); private: @@ -131,7 +131,7 @@ namespace term { void unsetKey(keycode_t key); private: - virtual void cb_init(); + virtual bool cb_init(); virtual void cb_windowSizeChanged(); virtual void v_keyReceived(keycode_t key); diff --git a/Utils/Termlib/Telnet.cci b/Utils/Termlib/Telnet.cci index ed7d902243f3ad3dec21e6787ae94f94941e4b24..9804e995a441bd19382a4d2832dc8710cdae31f4 100644 --- a/Utils/Termlib/Telnet.cci +++ b/Utils/Termlib/Telnet.cci @@ -74,6 +74,11 @@ prefix_ unsigned senf::term::telnethandler::NAWS::height() prefix_ senf::term::BaseTelnetProtocol::~BaseTelnetProtocol() {} +prefix_ senf::term::BaseTelnetProtocol::Handle senf::term::BaseTelnetProtocol::handle() +{ + return handle_; +} + prefix_ void senf::term::BaseTelnetProtocol::incrementRequestCounter() { ++ pendingRequests_; @@ -157,6 +162,16 @@ prefix_ void senf::term::BaseTelnetProtocol::acceptPeerOption(option_type option getOption(false, option).wantState = OptInfo::ACCEPTED; } +prefix_ bool senf::term::BaseTelnetProtocol::localOption(option_type option) +{ + return getOption(true, option).enabled; +} + +prefix_ bool senf::term::BaseTelnetProtocol::peerOption(option_type option) +{ + return getOption(false, option).enabled; +} + prefix_ void senf::term::BaseTelnetProtocol::emit(char c) { v_charReceived(c); diff --git a/Utils/Termlib/Telnet.hh b/Utils/Termlib/Telnet.hh index c50f87b4d154d0606170d03591dae12bf5ccf189..4cc6af462627801f6e58dc3fcee879dd4e9b8a0b 100644 --- a/Utils/Termlib/Telnet.hh +++ b/Utils/Termlib/Telnet.hh @@ -65,6 +65,8 @@ namespace term { void write(std::string const & s); void write(char c); + Handle handle(); + void sendNOP(); void sendBRK(); void sendIP(); @@ -81,6 +83,9 @@ namespace term { void requestPeerOption(option_type option, bool enabled = true); void acceptPeerOption(option_type option, bool enabled = true); + + bool localOption(option_type option); + bool peerOption(option_type option); protected: explicit BaseTelnetProtocol(Handle handle); diff --git a/Utils/Termlib/TelnetTerminal.cc b/Utils/Termlib/TelnetTerminal.cc index 6b28a4f466be0164dd046ec13d3c0e81704b3ad6..5e08938e99af4d45606ac7f57765658454b85e9e 100644 --- a/Utils/Termlib/TelnetTerminal.cc +++ b/Utils/Termlib/TelnetTerminal.cc @@ -33,6 +33,7 @@ ///////////////////////////////cc.p//////////////////////////////////////// prefix_ senf::term::TelnetTerminal::TelnetTerminal() + : setupFailed_ (false) { requestPeerOption(telnetopt::SUPPRESS_GO_AHEAD); requestLocalOption(telnetopt::SUPPRESS_GO_AHEAD); @@ -66,7 +67,23 @@ prefix_ void senf::term::TelnetTerminal::write(char ch) prefix_ void senf::term::TelnetTerminal::v_setupComplete() { - callbacks_->cb_init(); + if (setupFailed_) + v_setupFailed(); + else if (! (width() > 0 + && ! terminalType().empty() + && localOption(telnetopt::SUPPRESS_GO_AHEAD) + && peerOption(telnetopt::SUPPRESS_GO_AHEAD) + && localOption(telnetopt::ECHO) + && callbacks_->cb_init())) { + setupFailed_ = true; + requestPeerOption(telnetopt::SUPPRESS_GO_AHEAD, false); + requestLocalOption(telnetopt::SUPPRESS_GO_AHEAD, false); + requestLocalOption(telnetopt::ECHO, false); + requestPeerOption(telnetopt::TERMINAL_TYPE, false); + requestPeerOption(telnetopt::NAWS, false); + if (! requestsPending()) + v_setupFailed(); + } } prefix_ void senf::term::TelnetTerminal::v_charReceived(char ch) diff --git a/Utils/Termlib/TelnetTerminal.hh b/Utils/Termlib/TelnetTerminal.hh index 98cab315518e7a80a05ba5b46cf59765af06a5e7..ed2be42d474be6e87c72ba325cf6d14d3be1cfd2 100644 --- a/Utils/Termlib/TelnetTerminal.hh +++ b/Utils/Termlib/TelnetTerminal.hh @@ -51,11 +51,14 @@ namespace term { virtual void write(char ch); private: + virtual void v_setupFailed() = 0; + virtual void v_setupComplete(); virtual void v_charReceived(char ch); virtual void v_windowSizeChanged(); AbstractTerminal::Callbacks * callbacks_; + bool setupFailed_; }; }} diff --git a/Utils/Termlib/Terminfo.cc b/Utils/Termlib/Terminfo.cc index 232a1886fdaa3cf429301efcf4c150e6c9e64c39..603676c8621b18e8231fdd5317d3c3507a533016 100644 --- a/Utils/Termlib/Terminfo.cc +++ b/Utils/Termlib/Terminfo.cc @@ -450,7 +450,7 @@ prefix_ void senf::term::Terminfo::load(std::istream & is) strings_.resize(offsets.size()); StringVec::iterator j (strings_.begin()); for (OffsetVec::iterator i (offsets.begin()); i != offsets.end(); ++i, ++j) - if (*i != NoValue && *i >= 0 && *i < stringPool_.size()) + if (*i != NoValue && *i >= 0 && unsigned(*i) < stringPool_.size()) *j = &(stringPool_[0]) + *i; else *j = 0; diff --git a/Utils/Termlib/telnetServer.cc b/Utils/Termlib/telnetServer.cc index 4f9ccf25bf32b771d81b32c862f7934e8a0270ab..3c5c9fdf2e0c0504d80ee16b623cf61f95df8337 100644 --- a/Utils/Termlib/telnetServer.cc +++ b/Utils/Termlib/telnetServer.cc @@ -49,7 +49,29 @@ namespace { : senf::term::BaseTelnetProtocol (handle), editor_ (*this, senf::membind(&MyTelnet::executeLine, this)) { - editor_.prompt("myTelnet$"); + editor_.prompt("myTelnet-with-an-endlesssly-long-prompt$"); + editor_.defineKey(senf::term::KeyParser::Ctrl('D'), + senf::membind(&MyTelnet::deleteCharOrExit, this)); + } + + void deleteCharOrExit(senf::term::LineEditor & editor) + { + if (editor.text().empty()) { + exit(); + } + else + senf::term::bindings::deleteChar(editor); + } + + void exit() + { + handle().facet<senf::TCPSocketProtocol>().shutdown(senf::TCPSocketProtocol::ShutRD); + } + + virtual void v_setupFailed() + { + SENF_LOG(("Terminal setup failed")); + exit(); } virtual void v_eof() diff --git a/project.el b/project.el index f34d538962f7ecdcaa876eb5307113b21db0fbcd..74eafadbaf21f408464dcdf62a593cdead44e94c 100644 --- a/project.el +++ b/project.el @@ -4,6 +4,7 @@ (save-excursion (back-to-indentation) (if (and (looking-at "namespace") + (looking-at ".*{") (not (looking-at ".*}"))) [0] '+)))