summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/default_config.cfg2
-rw-r--r--src/core.py4
-rw-r--r--src/data_forms.py1
-rw-r--r--src/room.py6
-rw-r--r--src/tabs.py20
-rw-r--r--src/windows.py9
-rw-r--r--src/xhtml.py200
7 files changed, 146 insertions, 96 deletions
diff --git a/data/default_config.cfg b/data/default_config.cfg
index 5e9f35d6..0c16ef97 100644
--- a/data/default_config.cfg
+++ b/data/default_config.cfg
@@ -47,7 +47,7 @@ completion = normal
# a SPACE will always be added after that
after_completion = ,
-# a list of words (separated by a semicolon (:)) that will be
+# a list of words (separated by a colon (:)) that will be
# highlighted if said by someone on a room
highlight_on =
diff --git a/src/core.py b/src/core.py
index 92a644be..96531e5f 100644
--- a/src/core.py
+++ b/src/core.py
@@ -884,6 +884,10 @@ class Core(object):
self.command_win('%s' % tab.nb)
return
for tab in self.tabs:
+ if tab.get_color_state() == theme.COLOR_TAB_DISCONNECTED:
+ self.command_win('%s' % tab.nb)
+ return
+ for tab in self.tabs:
if isinstance(tab, tabs.ChatTab) and not tab.input.is_empty():
self.command_win('%s' % tab.nb)
return
diff --git a/src/data_forms.py b/src/data_forms.py
index dc532b87..176c4669 100644
--- a/src/data_forms.py
+++ b/src/data_forms.py
@@ -63,6 +63,7 @@ class DataFormsTab(Tab):
self.form_win.on_input(key)
def resize(self):
+ self.need_resize = False
self.topic_win.resize(1, self.width, 0, 0)
self.tab_win.resize(1, self.width, self.height-2, 0)
self.form_win.resize(self.height-4, self.width, 1, 0)
diff --git a/src/room.py b/src/room.py
index 58b96adb..83b00e62 100644
--- a/src/room.py
+++ b/src/room.py
@@ -99,9 +99,10 @@ class Room(TextBuffer):
in the room anymore
"""
self.log_message(txt, time, nickname)
+ special_message = False
if txt.startswith('/me '):
txt = "\x192* \x195" + nickname + ' ' + txt[4:]
- nickname = None
+ special_message = True
user = self.get_user_by_name(nickname) if nickname is not None else None
if user:
user.set_last_talked(datetime.now())
@@ -119,6 +120,9 @@ class Room(TextBuffer):
highlight = self.do_highlight(txt, time, nickname)
if highlight:
nick_color = highlight
+ if special_message:
+ txt = '\x195%s' % (txt,)
+ nickname = None
time = time or datetime.now()
message = Message(txt='%s\x19o'%(txt.replace('\t', ' '),), nick_color=nick_color,
time=time, str_time=time.strftime("%Y-%m-%d %H:%M:%S")\
diff --git a/src/tabs.py b/src/tabs.py
index 6c819138..3a93f541 100644
--- a/src/tabs.py
+++ b/src/tabs.py
@@ -680,6 +680,7 @@ class MucTab(ChatTab):
"""
if not self.visible:
return
+ self.need_resize = False
text_width = (self.width//10)*9
self.topic_win.resize(1, self.width, 0, 0)
self.v_separator.resize(self.height-3, 1, 1, 9*(self.width//10))
@@ -1035,6 +1036,7 @@ class PrivateTab(ChatTab):
def resize(self):
if self.core.information_win_size >= self.height-3 or not self.visible:
return
+ self.need_resize = False
self.text_win.resize(self.height-3-self.core.information_win_size, self.width, 0, 0)
self.text_win.rebuild_everything(self._room)
self.info_header.resize(1, self.width, self.height-3-self.core.information_win_size, 0)
@@ -1123,22 +1125,24 @@ class PrivateTab(ChatTab):
"""
The user left the associated MUC
"""
+ self.deactivate()
if not status_message:
self.get_room().add_message(_('\x191%(spec)s \x193%(nick)s\x195 has left the room') % {'nick':from_nick.replace('"', '\\"'), 'spec':theme.CHAR_QUIT.replace('"', '\\"')})
else:
self.get_room().add_message(_('\x191%(spec)s \x193%(nick)s\x195 has left the room (%(status)s)"') % {'nick':from_nick.replace('"', '\\"'), 'spec':theme.CHAR_QUIT, 'status': status_message.replace('"', '\\"')})
- self.deactivate()
- self.refresh()
- self.core.doupdate()
+ if self.core.current_tab() is self:
+ self.refresh()
+ self.core.doupdate()
def user_rejoined(self, nick):
"""
The user (or at least someone with the same nick) came back in the MUC
"""
- self.get_room().add_message('\x194%(spec)s \x193%(nick)s\x195 joined the room' % {'nick':nick, 'spec':theme.CHAR_JOIN})
self.activate()
- self.refresh()
- self.core.doupdate()
+ self.get_room().add_message('\x194%(spec)s \x193%(nick)s\x195 joined the room' % {'nick':nick, 'spec':theme.CHAR_JOIN})
+ if self.core.current_tab() is self:
+ self.refresh()
+ self.core.doupdate()
def activate(self):
self.on = True
@@ -1184,6 +1188,7 @@ class RosterInfoTab(Tab):
def resize(self):
if not self.visible:
return
+ self.need_resize = False
roster_width = self.width//2
info_width = self.width-roster_width-1
self.v_separator.resize(self.height-2, 1, 0, roster_width)
@@ -1540,6 +1545,7 @@ class ConversationTab(ChatTab):
def resize(self):
if self.core.information_win_size >= self.height-3 or not self.visible:
return
+ self.need_resize = False
self.text_win.resize(self.height-4-self.core.information_win_size, self.width, 1, 0)
self.text_win.rebuild_everything(self._room)
self.upper_bar.resize(1, self.width, 0, 0)
@@ -1657,6 +1663,7 @@ class MucListTab(Tab):
def resize(self):
if not self.visible:
return
+ self.need_resize = False
self.upper_message.resize(1, self.width, 0, 0)
column_size = {'node-part': (self.width-5)//4,
'name': (self.width-5)//4*3,
@@ -1791,6 +1798,7 @@ class SimpleTextTab(Tab):
def resize(self):
if not self.visible:
return
+ self.need_resize = False
self.text_win.resize(self.height-2, self.width, 0, 0)
self.input.resize(1, self.width, self.height-1, 0)
diff --git a/src/windows.py b/src/windows.py
index 74d3b398..ef11107a 100644
--- a/src/windows.py
+++ b/src/windows.py
@@ -588,9 +588,7 @@ class TextWin(Win):
with g_lock:
self._win.erase()
for y, line in enumerate(lines):
- if line is None:
- self.write_line_separator()
- else:
+ if line:
msg = line.msg
if line.start_pos == 0:
if msg.nick_color:
@@ -606,8 +604,9 @@ class TextWin(Win):
self._win.attrset(0)
for y, line in enumerate(lines):
if not line:
- continue
- self.write_text(y, (3 if line.msg.nickname else 1) + len(line.msg.str_time)+len(truncate_nick(line.msg.nickname) or ''), line.msg.txt[line.start_pos:line.end_pos])
+ self.write_line_separator()
+ else:
+ self.write_text(y, (3 if line.msg.nickname else 1) + len(line.msg.str_time)+len(truncate_nick(line.msg.nickname) or ''), line.msg.txt[line.start_pos:line.end_pos])
if y != self.height-1:
self.addstr('\n')
self._win.attrset(0)
diff --git a/src/xhtml.py b/src/xhtml.py
index f8272e4f..8f629e3b 100644
--- a/src/xhtml.py
+++ b/src/xhtml.py
@@ -38,51 +38,126 @@ def get_body_from_message_stanza(message):
if config.get('enable_xhtml_im', 'true') == 'true':
xhtml_body = message['xhtml_im']
if xhtml_body:
- xhtml_body = convert_links_to_plaintext(xhtml_body)
- try:
- shell_body = xhtml_code_to_shell_colors(xhtml_body)
- except OSError:
- log.debug('html parsing failed')
- else:
- return shell_colors_to_poezio_colors(shell_body)
+ return xhtml_to_poezio_colors(xhtml_body)
return message['body']
-def convert_links_to_plaintext(text):
- """
- Replace
- <a href='URL'>click</a>
- by
- <url> (click)
- in plain text
- """
+
+def xhtml_to_poezio_colors(text):
+ def parse_css(css):
+ def get_color(string):
+ if value == 'black':
+ return 0
+ if value == 'red':
+ return 1
+ if value == 'green':
+ return 2
+ if value == 'yellow':
+ return 3
+ if value == 'blue':
+ return 4
+ if value == 'magenta':
+ return 5
+ if value == 'cyan':
+ return 6
+ if value == 'white':
+ return 7
+ if value == 'default':
+ return 8
+ shell = ''
+ rules = css.split(';')
+ for rule in rules:
+ key, value = rule.split(':', 1)
+ key = key.strip()
+ value = value.strip()
+ log.debug(value)
+ if key == 'background-color':
+ pass#shell += '\x191'
+ elif key == 'color':
+ shell += '\x19%d' % get_color(value)
+ elif key == 'font-style':
+ shell += '\x19i'
+ elif key == 'font-weight':
+ shell += '\x19b'
+ elif key == 'margin-left':
+ shell += ' '
+ elif key == 'text-align':
+ pass
+ elif key == 'text-decoration':
+ if value == 'underline':
+ shell += '\x19u'
+ elif value == 'blink':
+ shell += '\x19a'
+ return shell
+
log.debug(text)
- xml = ElementTree(ET.fromstring(text))
- for parent in xml.getiterator():
- previous_child = None
- for child in parent:
- if child.tag == '{http://www.w3.org/1999/xhtml}a':
- if child.attrib['href'] != child.text:
- if child.text is None and 'title' in child.attrib:
- link_text = '\n%s (%s)' % (child.attrib['href'], child.attrib['title'])
- else:
- link_text = '\n%s (%s)' % (child.attrib['href'], child.text)
- else:
- link_text = child.text
- if previous_child is not None:
- if previous_child.tail is None:
- previous_child.tail = link_text
- else:
- previous_child.tail += link_text
- else:
- if parent.text is None:
- parent.text = link_text
- else:
- parent.text += link_text
- parent.remove(child)
- previous_child = child
- if version_info.minor <= 1:
- return ET.tostring(xml.getroot())
- return ET.tostring(xml.getroot(), encoding=str)
+ xml = ET.fromstring(text)
+ message = ''
+ for elem in xml.iter():
+ if elem.tag == '{http://www.w3.org/1999/xhtml}a':
+ if 'href' in elem.attrib and elem.attrib['href'] != elem.text:
+ message += '\x19u%s\x19o (%s)' % (elem.attrib['href'], elem.text)
+ else:
+ message += '\x19u' + elem.text + '\x19o'
+ elif elem.tag == '{http://www.w3.org/1999/xhtml}blockquote':
+ message += '“'
+ elif elem.tag == '{http://www.w3.org/1999/xhtml}body':
+ pass
+ elif elem.tag == '{http://www.w3.org/1999/xhtml}br':
+ message += '\n'
+ elif elem.tag == '{http://www.w3.org/1999/xhtml}cite':
+ message += '\x19u'
+ elif elem.tag == '{http://www.w3.org/1999/xhtml}em':
+ message += '\x19i'
+ elif elem.tag == '{http://www.w3.org/1999/xhtml}img' and 'src' in elem.attrib:
+ if elem.attrib['alt']:
+ message += '%s (%s)' % (elem.attrib['src'], elem.attrib['alt'])
+ else:
+ message += elem.attrib['src']
+ elif elem.tag == '{http://www.w3.org/1999/xhtml}li':
+ pass
+ elif elem.tag == '{http://www.w3.org/1999/xhtml}ol':
+ pass
+ elif elem.tag == '{http://www.w3.org/1999/xhtml}p':
+ pass
+ elif elem.tag == '{http://www.w3.org/1999/xhtml}span':
+ pass
+ elif elem.tag == '{http://www.w3.org/1999/xhtml}strong':
+ message += '\x19b'
+ elif elem.tag == '{http://www.w3.org/1999/xhtml}ul':
+ pass
+
+ if ('style' in elem.attrib and elem.tag != '{http://www.w3.org/1999/xhtml}br'
+ and elem.tag != '{http://www.w3.org/1999/xhtml}em'
+ and elem.tag != '{http://www.w3.org/1999/xhtml}strong'):
+ message += parse_css(elem.attrib['style'])
+
+ if (elem.text and elem.tag != '{http://www.w3.org/1999/xhtml}a'
+ and elem.tag != '{http://www.w3.org/1999/xhtml}br'
+ and elem.tag != '{http://www.w3.org/1999/xhtml}img'):
+ message += elem.text
+
+ if ('style' in elem.attrib and elem.tag != '{http://www.w3.org/1999/xhtml}br'
+ and elem.tag != '{http://www.w3.org/1999/xhtml}em'
+ and elem.tag != '{http://www.w3.org/1999/xhtml}strong'):
+ message += '\x19o'
+
+ if elem.tag == '{http://www.w3.org/1999/xhtml}blockquote':
+ message += '”'
+ elif elem.tag == '{http://www.w3.org/1999/xhtml}cite':
+ message += '\x19o'
+ elif elem.tag == '{http://www.w3.org/1999/xhtml}em':
+ message += '\x19o'
+ elif elem.tag == '{http://www.w3.org/1999/xhtml}strong' or elem.tag == '{http://www.w3.org/1999/xhtml}b':
+ message += '\x19o'
+ elif elem.tag == '{http://www.w3.org/1999/xhtml}u':
+ message += '\x19o'
+
+ if 'title' in elem.attrib:
+ message += ' [' + elem.attrib['title'] + ']'
+
+ if elem.tail:
+ message += elem.tail
+ return message
def clean_text(string):
@@ -148,47 +223,6 @@ def poezio_colors_to_html(string):
res += "</p></body>"
return res.replace('\n', '<br />')
-def shell_colors_to_poezio_colors(string):
- """
- 'shell colors' means something like:
-
- Bonjour ^[[0;32msalut^[[0m
-
- The current understanding of this syntax is:
- n = 0: reset all attributes to defaults
- n = 1: activate bold
- n >= 30 and n <= 37: set the foreground to n-30
-
- """
- def repl(matchobj):
- exp = matchobj.group(0)[2:-1]
- numbers = [int(nb) for nb in exp.split(';')]
- res = ''
- for num in numbers:
- if num == 0:
- res += '\x19o'
- elif num == 1:
- res += '\x19b'
- elif num >= 31 and num <= 37:
- res += '\x19%d' % ((num-30)%7,)
- return res
- def remove_elinks_indent(string):
- lines = string.split('\n')
- for i, line in enumerate(lines):
- lines[i] = re.sub(' ', '', line, 1)
- return '\n'.join(lines)
- res = shell_colors_re.sub(repl, string).strip()
- res = remove_elinks_indent(res)
- return res
-
-def xhtml_code_to_shell_colors(string):
- """
- Use a console browser to parse the xhtml and
- make it return a shell-colored string
- """
- process = subprocess.Popen(["elinks", "-dump", "-dump-color-mode", "2"], stdout=subprocess.PIPE, stdin=subprocess.PIPE)
- result = process.communicate(input=string.encode('utf-8'))[0]
- return result.decode('utf-8').strip()
def poezio_colors_to_xhtml(string):
"""