Merge branch 'master' into plugins

Conflicts:
	src/core.py
This commit is contained in:
Florent Le Coz 2011-11-07 01:02:03 +01:00
commit 8911f85a42
4 changed files with 50 additions and 50 deletions

View file

@ -51,6 +51,7 @@ from text_buffer import TextBuffer
from keyboard import read_char from keyboard import read_char
from theming import get_theme from theming import get_theme
from fifo import Fifo from fifo import Fifo
from windows import g_lock
# http://xmpp.org/extensions/xep-0045.html#errorstatus # http://xmpp.org/extensions/xep-0045.html#errorstatus
ERROR_AND_STATUS_CODES = { ERROR_AND_STATUS_CODES = {
@ -73,8 +74,6 @@ possible_show = {'available':None,
'xa':'xa' 'xa':'xa'
} }
resize_lock = threading.Lock()
Status = collections.namedtuple('Status', 'show message') Status = collections.namedtuple('Status', 'show message')
class Core(object): class Core(object):
@ -208,18 +207,21 @@ class Core(object):
'Just press Ctrl-n.' \ 'Just press Ctrl-n.' \
)) ))
self.refresh_window() self.refresh_window()
def resize_global_information_win(self): def resize_global_information_win(self):
""" """
Resize the global_information_win only once at each resize. Resize the global_information_win only once at each resize.
""" """
self.information_win.resize(self.information_win_size, tabs.Tab.width, with g_lock:
tabs.Tab.height - 2 - self.information_win_size, 0) self.information_win.resize(self.information_win_size, tabs.Tab.width,
tabs.Tab.height - 2 - self.information_win_size, 0)
def resize_global_info_bar(self): def resize_global_info_bar(self):
""" """
Resize the GlobalInfoBar only once at each resize Resize the GlobalInfoBar only once at each resize
""" """
self.tab_win.resize(1, tabs.Tab.width, tabs.Tab.height - 2, 0) with g_lock:
self.tab_win.resize(1, tabs.Tab.width, tabs.Tab.height - 2, 0)
def on_exception(self, typ, value, trace): def on_exception(self, typ, value, trace):
""" """
@ -559,7 +561,7 @@ class Core(object):
if not body: if not body:
return return
tab.add_message(body, time=None, nickname=nick_from, tab.add_message(body, time=None, nickname=nick_from,
forced_user=self.get_tab_by_name(room_from, tabs.MucTab).get_user_by_name(nick_from)) forced_user=self.get_tab_by_name(room_from, tabs.MucTab).get_user_by_name(nick_from))
conversation = self.get_tab_by_name(jid.full, tabs.PrivateTab) conversation = self.get_tab_by_name(jid.full, tabs.PrivateTab)
if conversation and conversation.remote_wants_chatstates is None: if conversation and conversation.remote_wants_chatstates is None:
if message['chat_state']: if message['chat_state']:
@ -706,7 +708,7 @@ class Core(object):
tabs.Tab.resize(self.stdscr) tabs.Tab.resize(self.stdscr)
self.resize_global_information_win() self.resize_global_information_win()
self.resize_global_info_bar() self.resize_global_info_bar()
with resize_lock: with g_lock:
for tab in self.tabs: for tab in self.tabs:
if config.get('lazy_resize', 'true') == 'true': if config.get('lazy_resize', 'true') == 'true':
tab.need_resize = True tab.need_resize = True

View file

@ -305,7 +305,7 @@ class ChatTab(Tab):
# build the list of the recent words # build the list of the recent words
char_we_dont_want = string.punctuation+' ' char_we_dont_want = string.punctuation+' '
words = list() words = list()
for msg in self.messages[:-40:-1]: for msg in self._text_buffer.messages[:-40:-1]:
if not msg: if not msg:
continue continue
txt = xhtml.clean_text(msg.txt) txt = xhtml.clean_text(msg.txt)
@ -497,7 +497,7 @@ class MucTab(ChatTab):
""" """
/clear /clear
""" """
self.messages = [] self._text_buffer.messages = []
self.text_win.rebuild_everything(self._text_buffer) self.text_win.rebuild_everything(self._text_buffer)
self.refresh() self.refresh()
self.core.doupdate() self.core.doupdate()
@ -1218,7 +1218,7 @@ class PrivateTab(ChatTab):
msg['chat_state'] = needed msg['chat_state'] = needed
self.core.events.trigger('private_say', msg) self.core.events.trigger('private_say', msg)
msg.send() msg.send()
self.core.add_message_to_text_buffer(self._text_buffer, line, None, self.core.own_nick or self.own_nick) self.core.add_message_to_text_buffer(self._text_buffer, xhtml.convert_simple_to_full_colors(line), None, self.core.own_nick or self.own_nick)
self.cancel_paused_delay() self.cancel_paused_delay()
self.text_win.refresh() self.text_win.refresh()
self.input.refresh() self.input.refresh()
@ -1580,7 +1580,6 @@ class RosterInfoTab(Tab):
self.command_add(jid.lstrip('\n')) self.command_add(jid.lstrip('\n'))
self.core.information('Contacts imported from %s' % filepath, 'Info') self.core.information('Contacts imported from %s' % filepath, 'Info')
def command_export(self, arg): def command_export(self, arg):
""" """
Export the contacts Export the contacts
@ -1864,6 +1863,7 @@ class ConversationTab(ChatTab):
self.commands['unquery'] = (self.command_unquery, _("Usage: /unquery\nUnquery: close the tab"), None) self.commands['unquery'] = (self.command_unquery, _("Usage: /unquery\nUnquery: close the tab"), None)
self.commands['close'] = (self.command_unquery, _("Usage: /close\Close: close the tab"), None) self.commands['close'] = (self.command_unquery, _("Usage: /close\Close: close the tab"), None)
self.commands['version'] = (self.command_version, _('Usage: /version\nVersion: get the software version of the current interlocutor (usually its XMPP client and Operating System)'), None) self.commands['version'] = (self.command_version, _('Usage: /version\nVersion: get the software version of the current interlocutor (usually its XMPP client and Operating System)'), None)
self.commands['info'] = (self.command_info, _('Usage: /info\nInfo: get the status of the contact.'), None)
self.resize() self.resize()
def completion(self): def completion(self):
@ -1882,12 +1882,24 @@ class ConversationTab(ChatTab):
msg['chat_state'] = needed msg['chat_state'] = needed
self.core.events.trigger('conversation_say', msg) self.core.events.trigger('conversation_say', msg)
msg.send() msg.send()
self.core.add_message_to_text_buffer(self._text_buffer, line, None, self.core.own_nick) self.core.add_message_to_text_buffer(self._text_buffer, xhtml.convert_simple_to_full_colors(line), None, self.core.own_nick)
logger.log_message(JID(self.get_name()).bare, self.core.own_nick, line) logger.log_message(JID(self.get_name()).bare, self.core.own_nick, line)
self.cancel_paused_delay() self.cancel_paused_delay()
self.text_win.refresh() self.text_win.refresh()
self.input.refresh() self.input.refresh()
def command_info(self, arg):
contact = roster.get_contact_by_jid(self.get_name())
jid = JID(self.get_name())
if jid.resource:
resource = contact.get_resource_by_fulljid(jid.full)
else:
resource = contact.get_highest_priority_resource()
if resource:
self._text_buffer.add_message("\x195}Status: %s\x193}" %resource.get_status(), None, None, None, None, None)
self.refresh()
self.core.doupdate()
def command_unquery(self, arg): def command_unquery(self, arg):
self.core.close_tab() self.core.close_tab()

View file

@ -24,7 +24,7 @@ import curses
import string import string
from config import config from config import config
from threading import Lock from threading import RLock
from contact import Contact, Resource from contact import Contact, Resource
from roster import RosterGroup, roster from roster import RosterGroup, roster
@ -46,7 +46,7 @@ allowed_color_digits = ('0', '1', '2', '3', '4', '5', '6', '7')
# first is a bool telling if this is the first line of the message. # first is a bool telling if this is the first line of the message.
Line = collections.namedtuple('Line', 'msg start_pos end_pos') Line = collections.namedtuple('Line', 'msg start_pos end_pos')
g_lock = Lock() g_lock = RLock()
LINES_NB_LIMIT = 4096 LINES_NB_LIMIT = 4096
@ -79,7 +79,8 @@ class Win(object):
""" """
Override if something has to be done on resize Override if something has to be done on resize
""" """
self._resize(height, width, y, x) with g_lock:
self._resize(height, width, y, x)
def _refresh(self): def _refresh(self):
self._win.noutrefresh() self._win.noutrefresh()
@ -255,10 +256,11 @@ class UserList(Win):
self._refresh() self._refresh()
def resize(self, height, width, y, x): def resize(self, height, width, y, x):
self._resize(height, width, y, x) with g_lock:
self._win.attron(to_curses_attr(get_theme().COLOR_VERTICAL_SEPARATOR)) self._resize(height, width, y, x)
self._win.vline(0, 0, curses.ACS_VLINE, self.height) self._win.attron(to_curses_attr(get_theme().COLOR_VERTICAL_SEPARATOR))
self._win.attroff(to_curses_attr(get_theme().COLOR_VERTICAL_SEPARATOR)) self._win.vline(0, 0, curses.ACS_VLINE, self.height)
self._win.attroff(to_curses_attr(get_theme().COLOR_VERTICAL_SEPARATOR))
class Topic(Win): class Topic(Win):
def __init__(self): def __init__(self):
@ -674,9 +676,10 @@ class TextWin(Win):
self.addstr(' ') self.addstr(' ')
def resize(self, height, width, y, x, room=None): def resize(self, height, width, y, x, room=None):
self._resize(height, width, y, x) with g_lock:
if room: self._resize(height, width, y, x)
self.rebuild_everything(room) if room:
self.rebuild_everything(room)
def rebuild_everything(self, room): def rebuild_everything(self, room):
self.built_lines = [] self.built_lines = []

View file

@ -178,6 +178,8 @@ whitespace_re = re.compile(r'\s+')
xhtml_attr_re = re.compile(r'\x19\d{0,3}\}|\x19[buaio]') xhtml_attr_re = re.compile(r'\x19\d{0,3}\}|\x19[buaio]')
xhtml_simple_attr_re = re.compile(r'\x19\d')
def get_body_from_message_stanza(message): def get_body_from_message_stanza(message):
""" """
Returns a string with xhtml markups converted to Returns a string with xhtml markups converted to
@ -342,6 +344,15 @@ def clean_text_simple(string):
pos = string.find('\x19') pos = string.find('\x19')
return string return string
def convert_simple_to_full_colors(text):
"""
takes a \x19n formatted string and returns
a \x19n} formatted one.
"""
def add_curly_bracket(match):
return match.group(0) + '}'
return re.sub(xhtml_simple_attr_re, add_curly_bracket, text)
number_to_color_names = { number_to_color_names = {
1: 'red', 1: 'red',
2: 'green', 2: 'green',
@ -394,31 +405,3 @@ def poezio_colors_to_html(string):
res += '</%s>' % (elem,) res += '</%s>' % (elem,)
res += "</p></body>" res += "</p></body>"
return res.replace('\n', '<br />') return res.replace('\n', '<br />')
def poezio_colors_to_xhtml(string):
"""
Generate a valid xhtml string from
the poezio colors in the given string
"""
res = "<body xmlns='http://www.w3.org/1999/xhtml'>"
next_attr_char = string.find('\x19')
open_elements = []
while next_attr_char != -1:
attr_char = string[next_attr_char+1].lower()
if next_attr_char != 0:
res += string[:next_attr_char]
string = string[next_attr_char+2:]
if attr_char == 'o':
# close all opened elements
for elem in open_elements:
res += '</%s>'
open_elements = []
elif attr_char == 'b':
if 'strong' not in open_elements:
res += '<strong>'
open_elements.append('strong')
elif attr_char in digits:
self._win.attron(common.curses_color_pair(int(attr_char)))
next_attr_char = string.find('\x19')