Skip to content
Snippets Groups Projects
Commit 7554c469 authored by g0dil's avatar g0dil
Browse files

Utils/Termlib: Fix handling of very narrow windows

Utils/Termlib: Implement terminal setup failure handling
parent 3e91611e
No related branches found
No related tags found
No related merge requests found
......@@ -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;
};
......
......@@ -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())
......
......@@ -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);
......
......@@ -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);
......
......@@ -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);
......
......@@ -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)
......
......@@ -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_;
};
}}
......
......@@ -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;
......
......@@ -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()
......
......@@ -4,6 +4,7 @@
(save-excursion
(back-to-indentation)
(if (and (looking-at "namespace")
(looking-at ".*{")
(not (looking-at ".*}")))
[0] '+)))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment