From: g0dil Date: Wed, 7 Jan 2009 15:23:31 +0000 (+0000) Subject: Utils/Termlib: Fix handling of very narrow windows X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=27d5a4aaebd8abb6c6bb842af3c170063b206f0f;p=senf.git Utils/Termlib: Fix handling of very narrow windows Utils/Termlib: Implement terminal setup failure handling git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1044 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Utils/Termlib/AbstractTerminal.hh b/Utils/Termlib/AbstractTerminal.hh index 01d72f7..f38a4b5 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 0023322..57e1e78 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 de94ae1..e5cb475 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 ed7d902..9804e99 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 c50f87b..4cc6af4 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 6b28a4f..5e08938 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 98cab31..ed2be42 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 232a188..603676c 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 4f9ccf2..3c5c9fd 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().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 f34d538..74eafad 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] '+)))