summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorent Le Coz <louiz@louiz.org>2011-05-29 00:35:11 +0200
committerFlorent Le Coz <louiz@louiz.org>2011-05-29 00:35:11 +0200
commit8d3053bd93db2e976f49a3a32038712083d411a7 (patch)
tree8f65efeb61a6676fef0e6ca9d8469985b0b068c0
parent3af88ff8d620791e4d4969e913b46fe34857f9c3 (diff)
downloadpoezio-8d3053bd93db2e976f49a3a32038712083d411a7.tar.gz
poezio-8d3053bd93db2e976f49a3a32038712083d411a7.tar.bz2
poezio-8d3053bd93db2e976f49a3a32038712083d411a7.tar.xz
poezio-8d3053bd93db2e976f49a3a32038712083d411a7.zip
fixes #2164. Restore multiline messages on paste of big text. That’s now faster and works ~100% of the time (no more message cut in two part for no reason, I think)
-rw-r--r--src/core.py40
-rw-r--r--src/keyboard.py79
2 files changed, 68 insertions, 51 deletions
diff --git a/src/core.py b/src/core.py
index 14cb4857..f4cca7e3 100644
--- a/src/core.py
+++ b/src/core.py
@@ -670,23 +670,31 @@ class Core(object):
"""
# curses.ungetch(0) # FIXME
while self.running:
- char = self.read_keyboard()
+ char_list = self.read_keyboard()
# Special case for M-x where x is a number
- if char.startswith('M-') and len(char) == 3:
- try:
- nb = int(char[2])
- except ValueError:
- pass
- else:
- if self.current_tab().nb == nb:
- self.go_to_previous_tab()
+ if len(char_list) == 1:
+ char = char_list[0]
+ if char.startswith('M-') and len(char) == 3:
+ try:
+ nb = int(char[2])
+ except ValueError:
+ pass
else:
- self.command_win('%d' % nb)
- # search for keyboard shortcut
- if char in self.key_func:
- self.key_func[char]()
+ if self.current_tab().nb == nb:
+ self.go_to_previous_tab()
+ else:
+ self.command_win('%d' % nb)
+ # search for keyboard shortcut
+ if char in self.key_func:
+ self.key_func[char]()
+ else:
+ res = self.do_command(char)
+ if res:
+ self.refresh_window()
else:
- self.do_command(char)
+ for char in char_list:
+ self.do_command(char)
+ self.refresh_window()
self.doupdate()
def current_tab(self):
@@ -1419,9 +1427,7 @@ class Core(object):
def do_command(self, key):
if not key:
return
- res = self.current_tab().on_input(key)
- if res:
- self.refresh_window()
+ return self.current_tab().on_input(key)
def on_roster_enter_key(self, roster_row):
"""
diff --git a/src/keyboard.py b/src/keyboard.py
index 27edca5f..f3dd14db 100644
--- a/src/keyboard.py
+++ b/src/keyboard.py
@@ -24,8 +24,6 @@ shortcut, like ^A, M-a or KEY_RESIZE)
import time
-last_timeout = time.time()
-
def get_next_byte(s):
"""
Read the next byte of the utf-8 char
@@ -41,44 +39,57 @@ def get_next_byte(s):
return (None, c)
return (ord(c), c.encode('latin-1')) # returns a number and a bytes object
-def read_char(s):
+def read_char(s, timeout=1000):
"""
Read one utf-8 char
see http://en.wikipedia.org/wiki/UTF-8#Description
"""
- global last_timeout
- s.timeout(1000)
+ s.timeout(timeout) # The timeout for timed events to be checked every second
+ ret_list = []
+ # The list of all chars. For example if you paste a text, the list the chars pasted
+ # so that they can be handled at once.
(first, char) = get_next_byte(s)
- if first is None and char is None:
- last_timeout = time.time()
- return None
- if not isinstance(first, int): # Keyboard special, like KEY_HOME etc
- return char
- if first == 127 or first == 8:
- return "KEY_BACKSPACE"
- if first < 127: # ASCII char on one byte
- if first <= 26: # transform Ctrl+* keys
- char = chr(first + 64)
- # if char == 'M' and time.time() - last_char_time < 0.0005:
- # char = 'J'
- return "^"+char
- if first == 27:
- second = read_char(s)
- res = 'M-%s' % (second,)
- return res
- if 194 <= first:
- (code, c) = get_next_byte(s) # 2 bytes char
- char += c
- if 224 <= first:
- (code, c) = get_next_byte(s) # 3 bytes char
- char += c
- if 240 <= first:
- (code, c) = get_next_byte(s) # 4 bytes char
- char += c
- try:
- return char.decode('utf-8') # return all the concatened byte objets, decoded
- except UnicodeDecodeError:
+ while first is not None or char is not None:
+ if not isinstance(first, int): # Keyboard special, like KEY_HOME etc
+ return [char]
+ if first == 127 or first == 8:
+ return ["KEY_BACKSPACE"]
+ s.timeout(0) # we are now getting the missing utf-8 bytes to get a whole char
+ if first < 127: # ASCII char on one byte
+ if first <= 26: # transform Ctrl+* keys
+ char = chr(first + 64)
+ ret_list.append("^"+char)
+ (first, char) = get_next_byte(s)
+ continue
+ if first == 27:
+ second = read_char(s, 0)
+ res = 'M-%s' % (second[0],)
+ ret_list.append(res)
+ (first, char) = get_next_byte(s)
+ continue
+ if 194 <= first:
+ (code, c) = get_next_byte(s) # 2 bytes char
+ char += c
+ if 224 <= first:
+ (code, c) = get_next_byte(s) # 3 bytes char
+ char += c
+ if 240 <= first:
+ (code, c) = get_next_byte(s) # 4 bytes char
+ char += c
+ try:
+ ret_list.append(char.decode('utf-8')) # return all the concatened byte objets, decoded
+ except UnicodeDecodeError:
+ return None
+ # s.timeout(1) # timeout to detect a paste of many chars
+ (first, char) = get_next_byte(s)
+ if not ret_list:
+ # nothing at all was read, that’s a timed event timeout
return None
+ if len(ret_list) != 1:
+ if ret_list[-1] == '^M':
+ ret_list.pop(-1)
+ return [char if char != '^M' else '^J' for char in ret_list]
+ return ret_list
if __name__ == '__main__':
import curses