summaryrefslogtreecommitdiff
path: root/src/windows
diff options
context:
space:
mode:
Diffstat (limited to 'src/windows')
-rw-r--r--src/windows/__init__.py3
-rw-r--r--src/windows/base_wins.py5
-rw-r--r--src/windows/data_forms.py169
-rw-r--r--src/windows/info_bar.py148
-rw-r--r--src/windows/info_wins.py108
-rw-r--r--src/windows/input_placeholders.py33
-rw-r--r--src/windows/inputs.py51
-rw-r--r--src/windows/list.py77
-rw-r--r--src/windows/misc.py17
-rw-r--r--src/windows/muc.py107
-rw-r--r--src/windows/roster_win.py159
-rw-r--r--src/windows/text_win.py167
12 files changed, 507 insertions, 537 deletions
diff --git a/src/windows/__init__.py b/src/windows/__init__.py
index adb07cbe..9e165201 100644
--- a/src/windows/__init__.py
+++ b/src/windows/__init__.py
@@ -2,7 +2,8 @@
Module exporting all the Windows, which are wrappers around curses wins
used to display information on the screen
"""
-from . base_wins import Win, g_lock
+
+from . base_wins import Win
from . data_forms import FormWin
from . info_bar import GlobalInfoBar, VerticalGlobalInfoBar
from . info_wins import InfoWin, XMLInfoWin, PrivateInfoWin, MucListInfoWin, \
diff --git a/src/windows/base_wins.py b/src/windows/base_wins.py
index 44c62e91..574eee89 100644
--- a/src/windows/base_wins.py
+++ b/src/windows/base_wins.py
@@ -32,8 +32,6 @@ allowed_color_digits = ('0', '1', '2', '3', '4', '5', '6', '7')
# text_end are the position delimiting the text in this line.
Line = collections.namedtuple('Line', 'msg start_pos end_pos prepend')
-g_lock = RLock()
-
LINES_NB_LIMIT = 4096
class DummyWin(object):
@@ -69,8 +67,7 @@ class Win(object):
"""
Override if something has to be done on resize
"""
- with g_lock:
- self._resize(height, width, y, x)
+ self._resize(height, width, y, x)
def _refresh(self):
self._win.noutrefresh()
diff --git a/src/windows/data_forms.py b/src/windows/data_forms.py
index 0b27291c..d6e2cc66 100644
--- a/src/windows/data_forms.py
+++ b/src/windows/data_forms.py
@@ -6,7 +6,7 @@ does not inherit from the Win base class), as it will create the
others when needed.
"""
-from . import g_lock, Win
+from . import Win
from . inputs import Input
from theming import to_curses_attr, get_theme
@@ -61,12 +61,11 @@ class ColoredLabel(Win):
self.refresh()
def refresh(self):
- with g_lock:
- self._win.erase()
- self._win.attron(to_curses_attr(self.color))
- self.addstr(0, 0, self.text)
- self._win.attroff(to_curses_attr(self.color))
- self._refresh()
+ self._win.erase()
+ self._win.attron(to_curses_attr(self.color))
+ self.addstr(0, 0, self.text)
+ self._win.attroff(to_curses_attr(self.color))
+ self._refresh()
class DummyInput(FieldInput, Win):
@@ -100,19 +99,18 @@ class BooleanWin(FieldInput, Win):
self.refresh()
def refresh(self):
- with g_lock:
- self._win.erase()
- self._win.attron(to_curses_attr(self.color))
- self.addnstr(0, 0, ' '*(8), self.width)
- self.addstr(0, 2, "%s"%self.value)
- self.addstr(0, 8, '→')
- self.addstr(0, 0, '←')
- if self.last_key == 'KEY_RIGHT':
- self.addstr(0, 8, '')
- else:
- self.addstr(0, 0, '')
- self._win.attroff(to_curses_attr(self.color))
- self._refresh()
+ self._win.erase()
+ self._win.attron(to_curses_attr(self.color))
+ self.addnstr(0, 0, ' '*(8), self.width)
+ self.addstr(0, 2, "%s"%self.value)
+ self.addstr(0, 8, '→')
+ self.addstr(0, 0, '←')
+ if self.last_key == 'KEY_RIGHT':
+ self.addstr(0, 8, '')
+ else:
+ self.addstr(0, 0, '')
+ self._win.attroff(to_curses_attr(self.color))
+ self._refresh()
def reply(self):
self._field['label'] = ''
@@ -166,18 +164,17 @@ class TextMultiWin(FieldInput, Win):
def refresh(self):
if not self.edition_input:
- with g_lock:
- self._win.erase()
- self._win.attron(to_curses_attr(self.color))
- self.addnstr(0, 0, ' '*self.width, self.width)
- option = self.options[self.val_pos]
- self.addstr(0, self.width//2-len(option)//2, option)
- if self.val_pos > 0:
- self.addstr(0, 0, '←')
- if self.val_pos < len(self.options)-1:
- self.addstr(0, self.width-1, '→')
- self._win.attroff(to_curses_attr(self.color))
- self._refresh()
+ self._win.erase()
+ self._win.attron(to_curses_attr(self.color))
+ self.addnstr(0, 0, ' '*self.width, self.width)
+ option = self.options[self.val_pos]
+ self.addstr(0, self.width//2-len(option)//2, option)
+ if self.val_pos > 0:
+ self.addstr(0, 0, '←')
+ if self.val_pos < len(self.options)-1:
+ self.addstr(0, self.width-1, '→')
+ self._win.attroff(to_curses_attr(self.color))
+ self._refresh()
else:
self.edition_input.refresh()
@@ -219,20 +216,19 @@ class ListMultiWin(FieldInput, Win):
self.refresh()
def refresh(self):
- with g_lock:
- self._win.erase()
- self._win.attron(to_curses_attr(self.color))
- self.addnstr(0, 0, ' '*self.width, self.width)
- if self.val_pos > 0:
- self.addstr(0, 0, '←')
- if self.val_pos < len(self.options)-1:
- self.addstr(0, self.width-1, '→')
- if self.options:
- option = self.options[self.val_pos]
- self.addstr(0, self.width//2-len(option)//2, option[0]['label'])
- self.addstr(0, 2, '✔' if option[1] else '☐')
- self._win.attroff(to_curses_attr(self.color))
- self._refresh()
+ self._win.erase()
+ self._win.attron(to_curses_attr(self.color))
+ self.addnstr(0, 0, ' '*self.width, self.width)
+ if self.val_pos > 0:
+ self.addstr(0, 0, '←')
+ if self.val_pos < len(self.options)-1:
+ self.addstr(0, self.width-1, '→')
+ if self.options:
+ option = self.options[self.val_pos]
+ self.addstr(0, self.width//2-len(option)//2, option[0]['label'])
+ self.addstr(0, 2, '✔' if option[1] else '☐')
+ self._win.attroff(to_curses_attr(self.color))
+ self._refresh()
def reply(self):
self._field['label'] = ''
@@ -267,19 +263,18 @@ class ListSingleWin(FieldInput, Win):
self.refresh()
def refresh(self):
- with g_lock:
- self._win.erase()
- self._win.attron(to_curses_attr(self.color))
- self.addnstr(0, 0, ' '*self.width, self.width)
- if self.val_pos > 0:
- self.addstr(0, 0, '←')
- if self.val_pos < len(self.options)-1:
- self.addstr(0, self.width-1, '→')
- if self.options:
- option = self.options[self.val_pos]['label']
- self.addstr(0, self.width//2-len(option)//2, option)
- self._win.attroff(to_curses_attr(self.color))
- self._refresh()
+ self._win.erase()
+ self._win.attron(to_curses_attr(self.color))
+ self.addnstr(0, 0, ' '*self.width, self.width)
+ if self.val_pos > 0:
+ self.addstr(0, 0, '←')
+ if self.val_pos < len(self.options)-1:
+ self.addstr(0, self.width-1, '→')
+ if self.options:
+ option = self.options[self.val_pos]['label']
+ self.addstr(0, self.width//2-len(option)//2, option)
+ self._win.attroff(to_curses_attr(self.color))
+ self._refresh()
def reply(self):
self._field['label'] = ''
@@ -310,19 +305,18 @@ class TextPrivateWin(TextSingleWin):
TextSingleWin.__init__(self, field)
def rewrite_text(self):
- with g_lock:
- self._win.erase()
- if self.color:
- self._win.attron(to_curses_attr(self.color))
- self.addstr('*'*len(self.text[self.view_pos:self.view_pos+self.width-1]))
- if self.color:
- (y, x) = self._win.getyx()
- size = self.width-x
- self.addnstr(' '*size, size, to_curses_attr(self.color))
- self.addstr(0, self.pos, '')
- if self.color:
- self._win.attroff(to_curses_attr(self.color))
- self._refresh()
+ self._win.erase()
+ if self.color:
+ self._win.attron(to_curses_attr(self.color))
+ self.addstr('*'*len(self.text[self.view_pos:self.view_pos+self.width-1]))
+ if self.color:
+ (y, x) = self._win.getyx()
+ size = self.width-x
+ self.addnstr(' '*size, size, to_curses_attr(self.color))
+ self.addstr(0, self.pos, '')
+ if self.color:
+ self._win.attroff(to_curses_attr(self.color))
+ self._refresh()
def get_help_message(self):
return 'Edit the secret text'
@@ -346,8 +340,7 @@ class FormWin(object):
}
def __init__(self, form, height, width, y, x):
self._form = form
- with g_lock:
- self._win = Win._tab_win.derwin(height, width, y, x)
+ self._win = Win._tab_win.derwin(height, width, y, x)
self.scroll_pos = 0
self.current_input = 0
self.inputs = [] # dict list
@@ -370,8 +363,7 @@ class FormWin(object):
def resize(self, height, width, y, x):
self.height = height
self.width = width
- with g_lock:
- self._win = Win._tab_win.derwin(height, width, y, x)
+ self._win = Win._tab_win.derwin(height, width, y, x)
# Adjust the scroll position, if resizing made the window too small
# for the cursor to be visible
while self.current_input - self.scroll_pos > self.height-1:
@@ -443,19 +435,18 @@ class FormWin(object):
self.inputs[self.current_input]['input'].do_command(key)
def refresh(self):
- with g_lock:
- self._win.erase()
- y = -self.scroll_pos
- i = 0
- for name, field in self._form.getFields().items():
- if field['type'] == 'hidden':
- continue
- self.inputs[i]['label'].resize(1, self.width//2, y + 1, 0)
- self.inputs[i]['input'].resize(1, self.width//2, y+1, self.width//2)
- # TODO: display the field description
- y += 1
- i += 1
- self._win.refresh()
+ self._win.erase()
+ y = -self.scroll_pos
+ i = 0
+ for name, field in self._form.getFields().items():
+ if field['type'] == 'hidden':
+ continue
+ self.inputs[i]['label'].resize(1, self.width//2, y + 1, 0)
+ self.inputs[i]['input'].resize(1, self.width//2, y+1, self.width//2)
+ # TODO: display the field description
+ y += 1
+ i += 1
+ self._win.refresh()
for i, inp in enumerate(self.inputs):
if i < self.scroll_pos:
continue
diff --git a/src/windows/info_bar.py b/src/windows/info_bar.py
index cea4702f..e66343c5 100644
--- a/src/windows/info_bar.py
+++ b/src/windows/info_bar.py
@@ -12,7 +12,7 @@ import curses
from config import config
-from . import Win, g_lock
+from . import Win
from theming import get_theme, to_curses_attr
class GlobalInfoBar(Win):
@@ -21,46 +21,45 @@ class GlobalInfoBar(Win):
def refresh(self):
log.debug('Refresh: %s', self.__class__.__name__)
- with g_lock:
- self._win.erase()
- self.addstr(0, 0, "[", to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
+ self._win.erase()
+ self.addstr(0, 0, "[", to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
- create_gaps = config.get('create_gaps')
- show_names = config.get('show_tab_names')
- show_nums = config.get('show_tab_numbers')
- use_nicks = config.get('use_tab_nicks')
- # ignore any remaining gap tabs if the feature is not enabled
- if create_gaps:
- sorted_tabs = self.core.tabs[:]
- else:
- sorted_tabs = [tab for tab in self.core.tabs if tab]
+ create_gaps = config.get('create_gaps')
+ show_names = config.get('show_tab_names')
+ show_nums = config.get('show_tab_numbers')
+ use_nicks = config.get('use_tab_nicks')
+ # ignore any remaining gap tabs if the feature is not enabled
+ if create_gaps:
+ sorted_tabs = self.core.tabs[:]
+ else:
+ sorted_tabs = [tab for tab in self.core.tabs if tab]
- for nb, tab in enumerate(sorted_tabs):
- if not tab: continue
- color = tab.color
- if not config.get('show_inactive_tabs') and\
- color is get_theme().COLOR_TAB_NORMAL:
- continue
- try:
- if show_nums or not show_names:
- self.addstr("%s" % str(nb), to_curses_attr(color))
- if show_names:
- self.addstr(' ', to_curses_attr(color))
+ for nb, tab in enumerate(sorted_tabs):
+ if not tab: continue
+ color = tab.color
+ if not config.get('show_inactive_tabs') and\
+ color is get_theme().COLOR_TAB_NORMAL:
+ continue
+ try:
+ if show_nums or not show_names:
+ self.addstr("%s" % str(nb), to_curses_attr(color))
if show_names:
- if use_nicks:
- self.addstr("%s" % str(tab.get_nick()), to_curses_attr(color))
- else:
- self.addstr("%s" % tab.name, to_curses_attr(color))
- self.addstr("|", to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
- except: # end of line
- break
- (y, x) = self._win.getyx()
- self.addstr(y, x-1, '] ', to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
- (y, x) = self._win.getyx()
- remaining_size = self.width - x
- self.addnstr(' '*remaining_size, remaining_size,
- to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
- self._refresh()
+ self.addstr(' ', to_curses_attr(color))
+ if show_names:
+ if use_nicks:
+ self.addstr("%s" % str(tab.get_nick()), to_curses_attr(color))
+ else:
+ self.addstr("%s" % tab.name, to_curses_attr(color))
+ self.addstr("|", to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
+ except: # end of line
+ break
+ (y, x) = self._win.getyx()
+ self.addstr(y, x-1, '] ', to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
+ (y, x) = self._win.getyx()
+ remaining_size = self.width - x
+ self.addnstr(' '*remaining_size, remaining_size,
+ to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
+ self._refresh()
class VerticalGlobalInfoBar(Win):
def __init__(self, scr):
@@ -68,42 +67,39 @@ class VerticalGlobalInfoBar(Win):
self._win = scr
def refresh(self):
- with g_lock:
- height, width = self._win.getmaxyx()
- self._win.erase()
- sorted_tabs = [tab for tab in self.core.tabs if tab]
- if not config.get('show_inactive_tabs'):
- sorted_tabs = [tab for tab in sorted_tabs if\
- tab.vertical_color != get_theme().COLOR_VERTICAL_TAB_NORMAL]
- nb_tabs = len(sorted_tabs)
- use_nicks = config.get('use_tab_nicks')
- if nb_tabs >= height:
- for y, tab in enumerate(sorted_tabs):
- if tab.vertical_color == get_theme().COLOR_VERTICAL_TAB_CURRENT:
- pos = y
- break
- # center the current tab as much as possible
- if pos < height//2:
- sorted_tabs = sorted_tabs[:height]
- elif nb_tabs - pos <= height//2:
- sorted_tabs = sorted_tabs[-height:]
- else:
- sorted_tabs = sorted_tabs[pos-height//2 : pos+height//2]
+ height, width = self._win.getmaxyx()
+ self._win.erase()
+ sorted_tabs = [tab for tab in self.core.tabs if tab]
+ if not config.get('show_inactive_tabs'):
+ sorted_tabs = [tab for tab in sorted_tabs if\
+ tab.vertical_color != get_theme().COLOR_VERTICAL_TAB_NORMAL]
+ nb_tabs = len(sorted_tabs)
+ use_nicks = config.get('use_tab_nicks')
+ if nb_tabs >= height:
for y, tab in enumerate(sorted_tabs):
- color = tab.vertical_color
-
- if not config.get('vertical_tab_list_sort') != 'asc':
- y = height - y - 1
- self.addstr(y, 0, "%2d" % tab.nb,
- to_curses_attr(get_theme().COLOR_VERTICAL_TAB_NUMBER))
- self.addstr('.')
- if use_nicks:
- self.addnstr("%s" % tab.get_nick(), width - 4, to_curses_attr(color))
- else:
- self.addnstr("%s" % tab.name, width - 4, to_curses_attr(color))
- separator = to_curses_attr(get_theme().COLOR_VERTICAL_SEPARATOR)
- self._win.attron(separator)
- self._win.vline(0, width-1, curses.ACS_VLINE, height)
- self._win.attroff(separator)
- self._refresh()
-
+ if tab.vertical_color == get_theme().COLOR_VERTICAL_TAB_CURRENT:
+ pos = y
+ break
+ # center the current tab as much as possible
+ if pos < height//2:
+ sorted_tabs = sorted_tabs[:height]
+ elif nb_tabs - pos <= height//2:
+ sorted_tabs = sorted_tabs[-height:]
+ else:
+ sorted_tabs = sorted_tabs[pos-height//2 : pos+height//2]
+ for y, tab in enumerate(sorted_tabs):
+ color = tab.vertical_color
+ if not config.get('vertical_tab_list_sort') != 'asc':
+ y = height - y - 1
+ self.addstr(y, 0, "%2d" % tab.nb,
+ to_curses_attr(get_theme().COLOR_VERTICAL_TAB_NUMBER))
+ self.addstr('.')
+ if use_nicks:
+ self.addnstr("%s" % tab.get_nick(), width - 4, to_curses_attr(color))
+ else:
+ self.addnstr("%s" % tab.name, width - 4, to_curses_attr(color))
+ separator = to_curses_attr(get_theme().COLOR_VERTICAL_SEPARATOR)
+ self._win.attron(separator)
+ self._win.vline(0, width-1, curses.ACS_VLINE, height)
+ self._win.attroff(separator)
+ self._refresh()
diff --git a/src/windows/info_wins.py b/src/windows/info_wins.py
index 7c659a6c..766afb75 100644
--- a/src/windows/info_wins.py
+++ b/src/windows/info_wins.py
@@ -8,7 +8,7 @@ log = logging.getLogger(__name__)
from common import safeJID
-from . import Win, g_lock
+from . import Win
from . funcs import truncate_nick
from theming import get_theme, to_curses_attr
@@ -39,17 +39,16 @@ class XMLInfoWin(InfoWin):
def refresh(self, filter_t='', filter='', window=None):
log.debug('Refresh: %s', self.__class__.__name__)
- with g_lock:
- self._win.erase()
- bar = to_curses_attr(get_theme().COLOR_INFORMATION_BAR)
- if not filter_t:
- self.addstr('[No filter]', bar)
- else:
- info = '[%s] %s' % (filter_t, filter)
- self.addstr(info, bar)
- self.print_scroll_position(window)
- self.finish_line(get_theme().COLOR_INFORMATION_BAR)
- self._refresh()
+ self._win.erase()
+ bar = to_curses_attr(get_theme().COLOR_INFORMATION_BAR)
+ if not filter_t:
+ self.addstr('[No filter]', bar)
+ else:
+ info = '[%s] %s' % (filter_t, filter)
+ self.addstr(info, bar)
+ self.print_scroll_position(window)
+ self.finish_line(get_theme().COLOR_INFORMATION_BAR)
+ self._refresh()
class PrivateInfoWin(InfoWin):
"""
@@ -61,14 +60,13 @@ class PrivateInfoWin(InfoWin):
def refresh(self, name, window, chatstate, informations):
log.debug('Refresh: %s', self.__class__.__name__)
- with g_lock:
- self._win.erase()
- self.write_room_name(name)
- self.print_scroll_position(window)
- self.write_chatstate(chatstate)
- self.write_additional_informations(informations, name)
- self.finish_line(get_theme().COLOR_INFORMATION_BAR)
- self._refresh()
+ self._win.erase()
+ self.write_room_name(name)
+ self.print_scroll_position(window)
+ self.write_chatstate(chatstate)
+ self.write_additional_informations(informations, name)
+ self.finish_line(get_theme().COLOR_INFORMATION_BAR)
+ self._refresh()
def write_additional_informations(self, informations, jid):
"""
@@ -100,16 +98,15 @@ class MucListInfoWin(InfoWin):
def refresh(self, name=None, window=None):
log.debug('Refresh: %s', self.__class__.__name__)
- with g_lock:
- self._win.erase()
- if name:
- self.addstr(name, to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
- else:
- self.addstr(self.message, to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
- if window:
- self.print_scroll_position(window)
- self.finish_line(get_theme().COLOR_INFORMATION_BAR)
- self._refresh()
+ self._win.erase()
+ if name:
+ self.addstr(name, to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
+ else:
+ self.addstr(self.message, to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
+ if window:
+ self.print_scroll_position(window)
+ self.finish_line(get_theme().COLOR_INFORMATION_BAR)
+ self._refresh()
class ConversationInfoWin(InfoWin):
"""
@@ -138,16 +135,15 @@ class ConversationInfoWin(InfoWin):
# If contact is a Contact, then
# resource can now be a Resource: user is in the roster and online
# or resource is None: user is in the roster but offline
- with g_lock:
- self._win.erase()
- self.write_contact_jid(jid)
- self.write_contact_informations(contact)
- self.write_resource_information(resource)
- self.print_scroll_position(window)
- self.write_chatstate(chatstate)
- self.write_additional_informations(informations, jid)
- self.finish_line(get_theme().COLOR_INFORMATION_BAR)
- self._refresh()
+ self._win.erase()
+ self.write_contact_jid(jid)
+ self.write_contact_informations(contact)
+ self.write_resource_information(resource)
+ self.print_scroll_position(window)
+ self.write_chatstate(chatstate)
+ self.write_additional_informations(informations, jid)
+ self.finish_line(get_theme().COLOR_INFORMATION_BAR)
+ self._refresh()
def write_additional_informations(self, informations, jid):
"""
@@ -217,17 +213,16 @@ class MucInfoWin(InfoWin):
def refresh(self, room, window=None):
log.debug('Refresh: %s', self.__class__.__name__)
- with g_lock:
- self._win.erase()
- self.write_room_name(room)
- self.write_participants_number(room)
- self.write_own_nick(room)
- self.write_disconnected(room)
- self.write_role(room)
- if window:
- self.print_scroll_position(window)
- self.finish_line(get_theme().COLOR_INFORMATION_BAR)
- self._refresh()
+ self._win.erase()
+ self.write_room_name(room)
+ self.write_participants_number(room)
+ self.write_own_nick(room)
+ self.write_disconnected(room)
+ self.write_role(room)
+ if window:
+ self.print_scroll_position(window)
+ self.finish_line(get_theme().COLOR_INFORMATION_BAR)
+ self._refresh()
def write_room_name(self, room):
self.addstr('[', to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
@@ -289,12 +284,11 @@ class ConversationStatusMessageWin(InfoWin):
resource = contact.get_highest_priority_resource()
else:
resource = None
- with g_lock:
- self._win.erase()
- if resource:
- self.write_status_message(resource)
- self.finish_line(get_theme().COLOR_INFORMATION_BAR)
- self._refresh()
+ self._win.erase()
+ if resource:
+ self.write_status_message(resource)
+ self.finish_line(get_theme().COLOR_INFORMATION_BAR)
+ self._refresh()
def write_status_message(self, resource):
self.addstr(resource.status, to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
diff --git a/src/windows/input_placeholders.py b/src/windows/input_placeholders.py
index 6ede6b32..8bcf1524 100644
--- a/src/windows/input_placeholders.py
+++ b/src/windows/input_placeholders.py
@@ -7,7 +7,7 @@ import logging
log = logging.getLogger(__name__)
-from . import Win, g_lock
+from . import Win
from theming import get_theme, to_curses_attr
@@ -25,11 +25,10 @@ class HelpText(Win):
log.debug('Refresh: %s', self.__class__.__name__)
if txt:
self.txt = txt
- with g_lock:
- self._win.erase()
- self.addstr(0, 0, self.txt[:self.width-1], to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
- self.finish_line(get_theme().COLOR_INFORMATION_BAR)
- self._refresh()
+ self._win.erase()
+ self.addstr(0, 0, self.txt[:self.width-1], to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
+ self.finish_line(get_theme().COLOR_INFORMATION_BAR)
+ self._refresh()
def do_command(self, key, raw=False):
return False
@@ -61,11 +60,10 @@ class YesNoInput(Win):
log.debug('Refresh: %s', self.__class__.__name__)
if txt:
self.txt = txt
- with g_lock:
- self._win.erase()
- self.addstr(0, 0, self.txt[:self.width-1], to_curses_attr(get_theme().COLOR_WARNING_PROMPT))
- self.finish_line(get_theme().COLOR_WARNING_PROMPT)
- self._refresh()
+ self._win.erase()
+ self.addstr(0, 0, self.txt[:self.width-1], to_curses_attr(get_theme().COLOR_WARNING_PROMPT))
+ self.finish_line(get_theme().COLOR_WARNING_PROMPT)
+ self._refresh()
def do_command(self, key, raw=False):
if key.lower() in self.key_func:
@@ -73,11 +71,14 @@ class YesNoInput(Win):
def prompt(self):
"""Monopolizes the input while waiting for a recognized keypress"""
- cl = []
- while self.value is None:
- if len(cl) == 1 and cl[0] in self.key_func:
- self.key_func[cl[0]]()
- cl = self.core.read_keyboard()
+ def cb(key):
+ if key in self.key_func:
+ self.key_func[key]()
+ if self.value is None:
+ # We didn’t finish with this prompt, continue monopolizing
+ # it again until value is set
+ keyboard.continuation_keys_callback = cb
+ keyboard.continuation_keys_callback = cb
def on_delete(self):
return
diff --git a/src/windows/inputs.py b/src/windows/inputs.py
index 8e1673e1..d345443b 100644
--- a/src/windows/inputs.py
+++ b/src/windows/inputs.py
@@ -8,9 +8,10 @@ log = logging.getLogger(__name__)
import curses
import string
+import keyboard
import common
import poopt
-from . import Win, g_lock
+from . import Win
from . base_wins import format_chars
from . funcs import find_first_format_char
from config import config
@@ -494,25 +495,24 @@ class Input(Win):
length of text to display, and the position of the cursor.
"""
self.adjust_view_pos()
- with g_lock:
- text = self.text
- self._win.erase()
- if self.color:
- self._win.attron(to_curses_attr(self.color))
- displayed_text = text[self.view_pos:self.view_pos+self.width-1].replace('\t', '\x18')
- self._win.attrset(0)
- self.addstr_colored_lite(displayed_text)
- # Fill the rest of the line with the input color
- if self.color:
- (_, x) = self._win.getyx()
- size = self.width - x
- self.addnstr(' ' * size, size, to_curses_attr(self.color))
- self.addstr(0,
- poopt.wcswidth(displayed_text[:self.pos-self.view_pos]), '')
- if self.color:
- self._win.attroff(to_curses_attr(self.color))
- curses.curs_set(1)
- self._refresh()
+ text = self.text
+ self._win.erase()
+ if self.color:
+ self._win.attron(to_curses_attr(self.color))
+ displayed_text = text[self.view_pos:self.view_pos+self.width-1].replace('\t', '\x18')
+ self._win.attrset(0)
+ self.addstr_colored_lite(displayed_text)
+ # Fill the rest of the line with the input color
+ if self.color:
+ (_, x) = self._win.getyx()
+ size = self.width - x
+ self.addnstr(' ' * size, size, to_curses_attr(self.color))
+ self.addstr(0,
+ poopt.wcswidth(displayed_text[:self.pos-self.view_pos]), '')
+ if self.color:
+ self._win.attroff(to_curses_attr(self.color))
+ curses.curs_set(1)
+ self._refresh()
def adjust_view_pos(self):
"""
@@ -656,11 +656,12 @@ class MessageInput(HistoryInput):
"""
Read one more char (c), add the corresponding char from formats_char to the text string
"""
- attr_char = self.core.read_keyboard()[0]
- if attr_char in self.text_attributes:
- char = format_chars[self.text_attributes.index(attr_char)]
- self.do_command(char, False)
- self.rewrite_text()
+ def cb(attr_char):
+ if attr_char in self.text_attributes:
+ char = format_chars[self.text_attributes.index(attr_char)]
+ self.do_command(char, False)
+ self.rewrite_text()
+ keyboard.continuation_keys_callback = cb
def key_enter(self):
if self.history_enter():
diff --git a/src/windows/list.py b/src/windows/list.py
index 3cfb8af5..677df6ff 100644
--- a/src/windows/list.py
+++ b/src/windows/list.py
@@ -7,7 +7,7 @@ log = logging.getLogger(__name__)
import curses
-from . import Win, g_lock
+from . import Win
from theming import to_curses_attr, get_theme
@@ -86,26 +86,26 @@ class ListWin(Win):
def refresh(self):
log.debug('Refresh: %s', self.__class__.__name__)
- with g_lock:
- self._win.erase()
- lines = self.lines[self._starting_pos:self._starting_pos+self.height]
- for y, line in enumerate(lines):
- x = 0
- for col in self._columns.items():
- try:
- txt = line[col[1]] or ''
- except KeyError:
- txt = ''
- size = self._columns_sizes[col[0]]
- txt += ' ' * (size-len(txt))
- if not txt:
- continue
- if line is self.lines[self._selected_row]:
- self.addstr(y, x, txt[:size], to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
- else:
- self.addstr(y, x, txt[:size])
- x += size
- self._refresh()
+ self._win.erase()
+ lines = self.lines[self._starting_pos:self._starting_pos+self.height]
+ for y, line in enumerate(lines):
+ x = 0
+ for col in self._columns.items():
+ try:
+ txt = line[col[1]] or ''
+ except KeyError:
+ txt = ''
+ size = self._columns_sizes[col[0]]
+ txt += ' ' * (size-len(txt))
+ if not txt:
+ continue
+ if line is self.lines[self._selected_row]:
+ self.addstr(y, x, txt[:size],
+ to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
+ else:
+ self.addstr(y, x, txt[:size])
+ x += size
+ self._refresh()
def move_cursor_down(self):
"""
@@ -175,25 +175,24 @@ class ColumnHeaderWin(Win):
def refresh(self):
log.debug('Refresh: %s', self.__class__.__name__)
- with g_lock:
- self._win.erase()
- x = 0
- for col in self._columns:
- txt = col
- if col in self._column_order:
- if self._column_order_asc:
- txt += get_theme().CHAR_COLUMN_ASC
- else:
- txt += get_theme().CHAR_COLUMN_DESC
- #⇓⇑↑↓⇧⇩▲▼
- size = self._columns_sizes[col]
- txt += ' ' * (size-len(txt))
- if col in self._column_sel:
- self.addstr(0, x, txt, to_curses_attr(get_theme().COLOR_COLUMN_HEADER_SEL))
+ self._win.erase()
+ x = 0
+ for col in self._columns:
+ txt = col
+ if col in self._column_order:
+ if self._column_order_asc:
+ txt += get_theme().CHAR_COLUMN_ASC
else:
- self.addstr(0, x, txt, to_curses_attr(get_theme().COLOR_COLUMN_HEADER))
- x += size
- self._refresh()
+ txt += get_theme().CHAR_COLUMN_DESC
+ #⇓⇑↑↓⇧⇩▲▼
+ size = self._columns_sizes[col]
+ txt += ' ' * (size-len(txt))
+ if col in self._column_sel:
+ self.addstr(0, x, txt, to_curses_attr(get_theme().COLOR_COLUMN_HEADER_SEL))
+ else:
+ self.addstr(0, x, txt, to_curses_attr(get_theme().COLOR_COLUMN_HEADER))
+ x += size
+ self._refresh()
def sel_column(self, dic):
self._column_sel = dic
diff --git a/src/windows/misc.py b/src/windows/misc.py
index 0f6bce59..07c91bbd 100644
--- a/src/windows/misc.py
+++ b/src/windows/misc.py
@@ -7,7 +7,7 @@ log = logging.getLogger(__name__)
import curses
-from . import Win, g_lock
+from . import Win
from theming import get_theme, to_curses_attr
class VerticalSeparator(Win):
@@ -19,9 +19,9 @@ class VerticalSeparator(Win):
Win.__init__(self)
def rewrite_line(self):
- with g_lock:
- self._win.vline(0, 0, curses.ACS_VLINE, self.height, to_curses_attr(get_theme().COLOR_VERTICAL_SEPARATOR))
- self._refresh()
+ self._win.vline(0, 0, curses.ACS_VLINE, self.height,
+ to_curses_attr(get_theme().COLOR_VERTICAL_SEPARATOR))
+ self._refresh()
def refresh(self):
log.debug('Refresh: %s', self.__class__.__name__)
@@ -53,9 +53,8 @@ class SimpleTextWin(Win):
def refresh(self):
log.debug('Refresh: %s', self.__class__.__name__)
- with g_lock:
- self._win.erase()
- for y, line in enumerate(self.built_lines):
- self.addstr_colored(line, y, 0)
- self._refresh()
+ self._win.erase()
+ for y, line in enumerate(self.built_lines):
+ self.addstr_colored(line, y, 0)
+ self._refresh()
diff --git a/src/windows/muc.py b/src/windows/muc.py
index cd594c4c..7e3541ba 100644
--- a/src/windows/muc.py
+++ b/src/windows/muc.py
@@ -7,7 +7,7 @@ log = logging.getLogger(__name__)
import curses
-from . import Win, g_lock
+from . import Win
import poopt
from config import config
@@ -36,44 +36,43 @@ class UserList(Win):
log.debug('Refresh: %s', self.__class__.__name__)
if config.get('hide_user_list'):
return # do not refresh if this win is hidden.
- with g_lock:
- self._win.erase()
+ self._win.erase()
+ if config.get('user_list_sort').lower() == 'asc':
+ y, x = self._win.getmaxyx()
+ y -= 1
+ users = sorted(users)
+ else:
+ y = 0
+ users = sorted(users)
+
+ if len(users) < self.height:
+ self.pos = 0
+ elif self.pos >= len(users) - self.height and self.pos != 0:
+ self.pos = len(users) - self.height
+ for user in users[self.pos:]:
+ self.draw_role_affiliation(y, user)
+ self.draw_status_chatstate(y, user)
+ self.addstr(y, 2,
+ poopt.cut_by_columns(user.nick, self.width - 2),
+ to_curses_attr(user.color))
if config.get('user_list_sort').lower() == 'asc':
- y, x = self._win.getmaxyx()
y -= 1
- users = sorted(users)
else:
- y = 0
- users = sorted(users)
-
- if len(users) < self.height:
- self.pos = 0
- elif self.pos >= len(users) - self.height and self.pos != 0:
- self.pos = len(users) - self.height
- for user in users[self.pos:]:
- self.draw_role_affiliation(y, user)
- self.draw_status_chatstate(y, user)
- self.addstr(y, 2,
- poopt.cut_by_columns(user.nick, self.width - 2),
- to_curses_attr(user.color))
- if config.get('user_list_sort').lower() == 'asc':
- y -= 1
- else:
- y += 1
- if y == self.height:
- break
- # draw indicators of position in the list
- if self.pos > 0:
- if config.get('user_list_sort').lower() == 'asc':
- self.draw_plus(self.height-1)
- else:
- self.draw_plus(0)
- if self.pos + self.height < len(users):
- if config.get('user_list_sort').lower() == 'asc':
- self.draw_plus(0)
- else:
- self.draw_plus(self.height-1)
- self._refresh()
+ y += 1
+ if y == self.height:
+ break
+ # draw indicators of position in the list
+ if self.pos > 0:
+ if config.get('user_list_sort').lower() == 'asc':
+ self.draw_plus(self.height-1)
+ else:
+ self.draw_plus(0)
+ if self.pos + self.height < len(users):
+ if config.get('user_list_sort').lower() == 'asc':
+ self.draw_plus(0)
+ else:
+ self.draw_plus(self.height-1)
+ self._refresh()
def draw_role_affiliation(self, y, user):
theme = get_theme()
@@ -94,12 +93,11 @@ class UserList(Win):
self.addstr(y, 0, char, to_curses_attr(show_col))
def resize(self, height, width, y, x):
- with g_lock:
- separator = to_curses_attr(get_theme().COLOR_VERTICAL_SEPARATOR)
- self._resize(height, width, y, x)
- self._win.attron(separator)
- self._win.vline(0, 0, curses.ACS_VLINE, self.height)
- self._win.attroff(separator)
+ separator = to_curses_attr(get_theme().COLOR_VERTICAL_SEPARATOR)
+ self._resize(height, width, y, x)
+ self._win.attron(separator)
+ self._win.vline(0, 0, curses.ACS_VLINE, self.height)
+ self._win.attroff(separator)
class Topic(Win):
def __init__(self):
@@ -108,19 +106,18 @@ class Topic(Win):
def refresh(self, topic=None):
log.debug('Refresh: %s', self.__class__.__name__)
- with g_lock:
- self._win.erase()
- if topic:
- msg = topic[:self.width-1]
- else:
- msg = self._message[:self.width-1]
- self.addstr(0, 0, msg, to_curses_attr(get_theme().COLOR_TOPIC_BAR))
- (y, x) = self._win.getyx()
- remaining_size = self.width - x
- if remaining_size:
- self.addnstr(' '*remaining_size, remaining_size,
- to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
- self._refresh()
+ self._win.erase()
+ if topic:
+ msg = topic[:self.width-1]
+ else:
+ msg = self._message[:self.width-1]
+ self.addstr(0, 0, msg, to_curses_attr(get_theme().COLOR_TOPIC_BAR))
+ (y, x) = self._win.getyx()
+ remaining_size = self.width - x
+ if remaining_size:
+ self.addnstr(' '*remaining_size, remaining_size,
+ to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
+ self._refresh()
def set_message(self, message):
self._message = message
diff --git a/src/windows/roster_win.py b/src/windows/roster_win.py
index d98f27ce..6ecb6128 100644
--- a/src/windows/roster_win.py
+++ b/src/windows/roster_win.py
@@ -7,7 +7,7 @@ log = logging.getLogger(__name__)
from datetime import datetime
-from . import Win, g_lock
+from . import Win
import common
from config import config
@@ -89,39 +89,39 @@ class RosterWin(Win):
"""
Regenerates the roster cache if needed
"""
- with g_lock:
- if roster.needs_rebuild:
- log.debug('The roster has changed, rebuilding the cache…')
- # This is a search
- if roster.contact_filter:
- self.roster_cache = []
- sort = config.get('roster_sort') or 'jid:show'
- for contact in roster.get_contacts_sorted_filtered(sort):
- self.roster_cache.append(contact)
- else:
- show_offline = config.get('roster_show_offline') or roster.contact_filter
- sort = config.get('roster_sort') or 'jid:show'
- group_sort = config.get('roster_group_sort') or 'name'
- self.roster_cache = []
- # build the cache
- for group in roster.get_groups(group_sort):
- contacts_filtered = group.get_contacts(roster.contact_filter)
- if (not show_offline and group.get_nb_connected_contacts() == 0) or not contacts_filtered:
- continue # Ignore empty groups
- self.roster_cache.append(group)
- if group.folded:
- continue # ignore folded groups
- for contact in group.get_contacts(roster.contact_filter, sort):
- if not show_offline and len(contact) == 0:
- continue # ignore offline contacts
- self.roster_cache.append(contact)
- if not contact.folded(group.name):
- for resource in contact.get_resources():
- self.roster_cache.append(resource)
- roster.last_built = datetime.now()
- if self.selected_row in self.roster_cache:
- if self.pos < self.roster_len and self.roster_cache[self.pos] != self.selected_row:
- self.pos = self.roster_cache.index(self.selected_row)
+ if not roster.needs_rebuild:
+ return
+ log.debug('The roster has changed, rebuilding the cache…')
+ # This is a search
+ if roster.contact_filter:
+ self.roster_cache = []
+ sort = config.get('roster_sort', 'jid:show') or 'jid:show'
+ for contact in roster.get_contacts_sorted_filtered(sort):
+ self.roster_cache.append(contact)
+ else:
+ show_offline = config.get('roster_show_offline') or roster.contact_filter
+ sort = config.get('roster_sort') or 'jid:show'
+ group_sort = config.get('roster_group_sort') or 'name'
+ self.roster_cache = []
+ # build the cache
+ for group in roster.get_groups(group_sort):
+ contacts_filtered = group.get_contacts(roster.contact_filter)
+ if (not show_offline and group.get_nb_connected_contacts() == 0) or not contacts_filtered:
+ continue # Ignore empty groups
+ self.roster_cache.append(group)
+ if group.folded:
+ continue # ignore folded groups
+ for contact in group.get_contacts(roster.contact_filter, sort):
+ if not show_offline and len(contact) == 0:
+ continue # ignore offline contacts
+ self.roster_cache.append(contact)
+ if not contact.folded(group.name):
+ for resource in contact.get_resources():
+ self.roster_cache.append(resource)
+ roster.last_built = datetime.now()
+ if self.selected_row in self.roster_cache:
+ if self.pos < self.roster_len and self.roster_cache[self.pos] != self.selected_row:
+ self.pos = self.roster_cache.index(self.selected_row)
def refresh(self, roster):
"""
@@ -130,43 +130,42 @@ class RosterWin(Win):
"""
log.debug('Refresh: %s', self.__class__.__name__)
self.build_roster_cache(roster)
- with g_lock:
- # make sure we are within bounds
- self.move_cursor_up((self.roster_len + self.pos) if self.pos >= self.roster_len else 0)
- if not self.roster_cache:
- self.selected_row = None
- self._win.erase()
- self._win.move(0, 0)
- self.draw_roster_information(roster)
- y = 1
- group = "none"
- # scroll down if needed
- if self.start_pos+self.height <= self.pos+2:
- self.scroll_down(self.pos - self.start_pos - self.height + (self.height//2))
- # draw the roster from the cache
- roster_view = self.roster_cache[self.start_pos-1:self.start_pos+self.height]
-
- for item in roster_view:
- draw_selected = False
- if y -2 + self.start_pos == self.pos:
- draw_selected = True
- self.selected_row = item
-
- if isinstance(item, RosterGroup):
- self.draw_group(y, item, draw_selected)
- group = item.name
- elif isinstance(item, Contact):
- self.draw_contact_line(y, item, draw_selected, group)
- elif isinstance(item, Resource):
- self.draw_resource_line(y, item, draw_selected)
-
- y += 1
-
- if self.start_pos > 1:
- self.draw_plus(1)
- if self.start_pos + self.height-2 < self.roster_len:
- self.draw_plus(self.height-1)
- self._refresh()
+ # make sure we are within bounds
+ self.move_cursor_up((self.roster_len + self.pos) if self.pos >= self.roster_len else 0)
+ if not self.roster_cache:
+ self.selected_row = None
+ self._win.erase()
+ self._win.move(0, 0)
+ self.draw_roster_information(roster)
+ y = 1
+ group = "none"
+ # scroll down if needed
+ if self.start_pos+self.height <= self.pos+2:
+ self.scroll_down(self.pos - self.start_pos - self.height + (self.height//2))
+ # draw the roster from the cache
+ roster_view = self.roster_cache[self.start_pos-1:self.start_pos+self.height]
+
+ for item in roster_view:
+ draw_selected = False
+ if y -2 + self.start_pos == self.pos:
+ draw_selected = True
+ self.selected_row = item
+
+ if isinstance(item, RosterGroup):
+ self.draw_group(y, item, draw_selected)
+ group = item.name
+ elif isinstance(item, Contact):
+ self.draw_contact_line(y, item, draw_selected, group)
+ elif isinstance(item, Resource):
+ self.draw_resource_line(y, item, draw_selected)
+
+ y += 1
+
+ if self.start_pos > 1:
+ self.draw_plus(1)
+ if self.start_pos + self.height-2 < self.roster_len:
+ self.draw_plus(self.height-1)
+ self._refresh()
def draw_plus(self, y):
@@ -373,13 +372,11 @@ class ContactInfoWin(Win):
def refresh(self, selected_row):
log.debug('Refresh: %s', self.__class__.__name__)
- with g_lock:
- self._win.erase()
- if isinstance(selected_row, RosterGroup):
- self.draw_group_info(selected_row)
- elif isinstance(selected_row, Contact):
- self.draw_contact_info(selected_row)
- # elif isinstance(selected_row, Resource):
- # self.draw_contact_info(None, selected_row)
- self._refresh()
-
+ self._win.erase()
+ if isinstance(selected_row, RosterGroup):
+ self.draw_group_info(selected_row)
+ elif isinstance(selected_row, Contact):
+ self.draw_contact_info(selected_row)
+ # elif isinstance(selected_row, Resource):
+ # self.draw_contact_info(None, selected_row)
+ self._refresh()
diff --git a/src/windows/text_win.py b/src/windows/text_win.py
index f634f5a6..8a8f75ae 100644
--- a/src/windows/text_win.py
+++ b/src/windows/text_win.py
@@ -9,7 +9,7 @@ log = logging.getLogger(__name__)
import curses
from math import ceil, log10
-from . import Win, g_lock
+from . import Win
from . base_wins import FORMAT_CHAR, Line
from . funcs import truncate_nick, parse_attrs
@@ -268,74 +268,73 @@ class TextWin(Win):
else:
lines = self.built_lines[-self.height-self.pos:-self.pos]
with_timestamps = config.get("show_timestamps")
- with g_lock:
- self._win.move(0, 0)
- self._win.erase()
- for y, line in enumerate(lines):
- if line:
- msg = line.msg
- if line.start_pos == 0:
- if msg.nick_color:
- color = msg.nick_color
- elif msg.user:
- color = msg.user.color
- else:
- color = None
- if with_timestamps:
- self.write_time(msg.str_time)
- if msg.ack:
- self.write_ack()
- if msg.me:
- self._win.attron(to_curses_attr(get_theme().COLOR_ME_MESSAGE))
- self.addstr('* ')
- self.write_nickname(msg.nickname, color, msg.highlight)
- if msg.revisions:
- self._win.attron(to_curses_attr(get_theme().COLOR_REVISIONS_MESSAGE))
- self.addstr('%d' % msg.revisions)
- self._win.attrset(0)
- self.addstr(' ')
- else:
- self.write_nickname(msg.nickname, color, msg.highlight)
- if msg.revisions:
- self._win.attron(to_curses_attr(get_theme().COLOR_REVISIONS_MESSAGE))
- self.addstr('%d' % msg.revisions)
- self._win.attrset(0)
- self.addstr('> ')
- if y != self.height-1:
- self.addstr('\n')
- self._win.attrset(0)
- for y, line in enumerate(lines):
- if not line:
- self.write_line_separator(y)
- else:
- offset = 0
- # Offset for the timestamp (if any) plus a space after it
+ self._win.move(0, 0)
+ self._win.erase()
+ for y, line in enumerate(lines):
+ if line:
+ msg = line.msg
+ if line.start_pos == 0:
+ if msg.nick_color:
+ color = msg.nick_color
+ elif msg.user:
+ color = msg.user.color
+ else:
+ color = None
if with_timestamps:
- offset += len(line.msg.str_time)
- if offset:
- offset += 1
-
- # Offset for the nickname (if any)
- # plus a space and a > after it
- if line.msg.nickname:
- offset += poopt.wcswidth(
- truncate_nick(line.msg.nickname))
- if line.msg.me:
- offset += 3
- else:
- offset += 2
- offset += ceil(log10(line.msg.revisions + 1))
-
- if line.msg.ack:
- offset += 1 + poopt.wcswidth(
- get_theme().CHAR_ACK_RECEIVED)
-
- self.write_text(y, offset,
- line.prepend+line.msg.txt[line.start_pos:line.end_pos])
- if y != self.height-1:
- self.addstr('\n')
- self._win.attrset(0)
- self._refresh()
+ self.write_time(msg.str_time)
+ if msg.ack:
+ self.write_ack()
+ if msg.me:
+ self._win.attron(to_curses_attr(get_theme().COLOR_ME_MESSAGE))
+ self.addstr('* ')
+ self.write_nickname(msg.nickname, color, msg.highlight)
+ if msg.revisions:
+ self._win.attron(to_curses_attr(get_theme().COLOR_REVISIONS_MESSAGE))
+ self.addstr('%d' % msg.revisions)
+ self._win.attrset(0)
+ self.addstr(' ')
+ else:
+ self.write_nickname(msg.nickname, color, msg.highlight)
+ if msg.revisions:
+ self._win.attron(to_curses_attr(get_theme().COLOR_REVISIONS_MESSAGE))
+ self.addstr('%d' % msg.revisions)
+ self._win.attrset(0)
+ self.addstr('> ')
+ if y != self.height-1:
+ self.addstr('\n')
+ self._win.attrset(0)
+ for y, line in enumerate(lines):
+ if not line:
+ self.write_line_separator(y)
+ else:
+ offset = 0
+ # Offset for the timestamp (if any) plus a space after it
+ if with_timestamps:
+ offset += len(line.msg.str_time)
+ if offset:
+ offset += 1
+
+ # Offset for the nickname (if any)
+ # plus a space and a > after it
+ if line.msg.nickname:
+ offset += poopt.wcswidth(
+ truncate_nick(line.msg.nickname))
+ if line.msg.me:
+ offset += 3
+ else:
+ offset += 2
+ offset += ceil(log10(line.msg.revisions + 1))
+
+ if line.msg.ack:
+ offset += 1 + poopt.wcswidth(
+ get_theme().CHAR_ACK_RECEIVED)
+
+ self.write_text(y, offset,
+ line.prepend+line.msg.txt[line.start_pos:line.end_pos])
+ if y != self.height-1:
+ self.addstr('\n')
+ self._win.attrset(0)
+ self._refresh()
def write_line_separator(self, y):
char = get_theme().CHAR_NEW_TEXT_SEPARATOR
@@ -387,23 +386,21 @@ class TextWin(Win):
self.addstr(' ')
def resize(self, height, width, y, x, room=None):
- with g_lock:
- if hasattr(self, 'width'):
- old_width = self.width
- else:
- old_width = None
- self._resize(height, width, y, x)
- if room and self.width != old_width:
- self.rebuild_everything(room)
-
- # reposition the scrolling after resize
- # (see #2450)
- buf_size = len(self.built_lines)
- if buf_size - self.pos < self.height:
- self.pos = buf_size - self.height
- if self.pos < 0:
- self.pos = 0
-
+ if hasattr(self, 'width'):
+ old_width = self.width
+ else:
+ old_width = None
+ self._resize(height, width, y, x)
+ if room and self.width != old_width:
+ self.rebuild_everything(room)
+
+ # reposition the scrolling after resize
+ # (see #2450)
+ buf_size = len(self.built_lines)
+ if buf_size - self.pos < self.height:
+ self.pos = buf_size - self.height
+ if self.pos < 0:
+ self.pos = 0
def rebuild_everything(self, room):
self.built_lines = []