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)

This commit is contained in:
Florent Le Coz 2011-05-29 00:35:11 +02:00
parent 3af88ff8d6
commit 8d3053bd93
2 changed files with 68 additions and 51 deletions

View file

@ -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):
"""

View file

@ -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, thats 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