Scheduler: Implement new file descriptor event API
[senf.git] / Console / Readline.cc
index 43da447..a02e2a8 100644 (file)
 ///////////////////////////////////////////////////////////////////////////
 // senf::console::detail::ReadlineClientReader
 
-extern int readline_echoing_p;
-extern int _rl_bell_preference;
+extern "C" {
+    extern int readline_echoing_p;
+    extern int _rl_bell_preference;
+
+    void _rl_erase_entire_line();
+}
+
 
 namespace {
 
@@ -74,9 +79,13 @@ namespace {
 
     void readline_callback(char * input)
     {
-        if (senf::console::detail::ReadlineClientReader::active() && input)
-            return senf::console::detail::ReadlineClientReader::instance().callback(
-                std::string(input) );
+        if (senf::console::detail::ReadlineClientReader::active()) {
+            if (input)
+                return senf::console::detail::ReadlineClientReader::instance().callback(
+                    std::string(input) );
+            else // input == 0 -> EOF (or Ctrl-D)
+                senf::console::detail::ReadlineClientReader::instance().eof();
+        }
     }
 
     ssize_t readline_cookie_write_function(void * cookie, char const * buffer, size_t size)
@@ -95,14 +104,20 @@ namespace {
     void readline_deprep_term()
     {}
 
+    int restart_line(int count, int key)
+    {
+        rl_kill_full_line(count, key);
+        rl_crlf();
+        rl_forced_update_display();
+        return 0;
+    }
+
 }
 
 prefix_ senf::console::detail::ReadlineClientReader::ReadlineClientReader(Client & client)
     : ClientReader(client), ch_ (-1), skipChars_ (0), 
-      schedBinding_ ( client.handle(), 
-                      senf::membind(&ReadlineClientReader::charEvent, this),
-                      Scheduler::EV_READ, 
-                      false ),
+      readevent_ ( "ReadlineClientReader", senf::membind(&ReadlineClientReader::charEvent, this),
+                   client.handle(), Scheduler::EV_READ, false ),
       terminate_ (false)
 {
     if (instance_ != 0)
@@ -124,6 +139,7 @@ prefix_ senf::console::detail::ReadlineClientReader::ReadlineClientReader(Client
     rl_deprep_term_function = &readline_deprep_term;
     rl_getc_function = &readline_getc_function;
     rl_bind_key('\t', &rl_insert);
+    rl_bind_key('\x03', &restart_line);
     using_history();
     
     // Don't ask me, where I found this ...
@@ -132,6 +148,7 @@ prefix_ senf::console::detail::ReadlineClientReader::ReadlineClientReader(Client
                               0xFF, 0xFB, 0x03, // IAC WILL SGA
                               0x00 };
     handle().write(options, options+sizeof(options));
+    handle().write(std::string("(readline support enabled)\r\n"));
 
     strncpy(promptBuffer_, promptString().c_str(), 1024);
     promptBuffer_[1023] = 0;
@@ -139,7 +156,7 @@ prefix_ senf::console::detail::ReadlineClientReader::ReadlineClientReader(Client
 
     _rl_bell_preference = 0; // Set this *after* the config file has been read
 
-    schedBinding_.enable();
+    readevent_.enable();
 }
 
 prefix_ senf::console::detail::ReadlineClientReader::~ReadlineClientReader()
@@ -164,10 +181,14 @@ prefix_ void senf::console::detail::ReadlineClientReader::callback(std::string l
 }
 
 prefix_ void senf::console::detail::ReadlineClientReader::v_disablePrompt()
-{}
+{
+    _rl_erase_entire_line();
+}
 
 prefix_ void senf::console::detail::ReadlineClientReader::v_enablePrompt()
-{}
+{
+    rl_forced_update_display();
+}
 
 prefix_ void senf::console::detail::ReadlineClientReader::v_translate(std::string & data)
 {
@@ -175,18 +196,18 @@ prefix_ void senf::console::detail::ReadlineClientReader::v_translate(std::strin
     boost::replace_all(data, "\xff", "\xff\xff");
 }
 
-prefix_ void senf::console::detail::ReadlineClientReader::charEvent(Scheduler::EventId event)
+prefix_ void senf::console::detail::ReadlineClientReader::charEvent(int event)
 {
     char ch;
     if (event != Scheduler::EV_READ || handle().read(&ch, &ch+1) <= &ch) {
         stopClient();
         return;
     }
-    ch_ = ch;
+    ch_ = static_cast<unsigned char>(ch);
 
     if (skipChars_ > 0)
         --skipChars_;
-    else if (ch_ == static_cast<char>(0xff))
+    else if (ch_ == 0xff)
         skipChars_ = 2;
     else if (ch_ != 0)
         rl_callback_read_char();