--- /dev/null
+#!/usr/bin/env python3
+import curses
+
+
+
+class CursesScreen:
+
+ def wrap_loop(self, loop):
+ curses.wrapper(self.start_loop, loop)
+
+ def safe_addstr(self, y, x, line, attr=0):
+ if y < self.size.y - 1 or x + len(line) < self.size.x:
+ self.stdscr.addstr(y, x, line, attr)
+ else: # workaround to <https://stackoverflow.com/q/7063128>
+ cut_i = self.size.x - x - 1
+ cut = line[:cut_i]
+ last_char = line[cut_i]
+ self.stdscr.addstr(y, self.size.x - 2, last_char, attr)
+ self.stdscr.insstr(y, self.size.x - 2, ' ')
+ self.stdscr.addstr(y, x, cut, attr)
+
+ def reset_size(self):
+ from plomrogue.mapping import YX
+ self.size = YX(*self.stdscr.getmaxyx())
+ self.size = self.size - YX(self.size.y % 4, 0)
+ self.size = self.size - YX(0, self.size.x % 4)
+
+ def start_loop(self, stdscr, loop):
+ self.stdscr = stdscr
+ curses.curs_set(0) # hide cursor
+ stdscr.timeout(10)
+ loop()
+
+
+
+def msg_into_lines_of_width(msg, width):
+ chunk = ''
+ lines = []
+ x = 0
+ for i in range(len(msg)):
+ if x >= width or msg[i] == "\n":
+ lines += [chunk]
+ chunk = ''
+ x = 0
+ if msg[i] == "\n":
+ x -= 1
+ if msg[i] != "\n":
+ chunk += msg[i]
+ x += 1
+ lines += [chunk]
+ return lines
from plomrogue.misc import quote
from plomrogue.errors import ArgError
from plomrogue_client.socket import ClientSocket
+from plomrogue_client.tui import msg_into_lines_of_width, CursesScreen
self.ascii_draw_stage = 0
self.full_ascii_draw = ''
self.offset = YX(0,0)
- curses.wrapper(self.loop)
+ self.screen = CursesScreen()
+ self.screen.wrap_loop(self.loop)
def update_on_connect(self):
self.socket.send('TASKS')
info += ')'
return info
- def loop(self, stdscr):
+ def loop(self):
def safe_addstr(y, x, line):
- if y < self.size.y - 1 or x + len(line) < self.size.x:
- stdscr.addstr(y, x, line, curses.color_pair(1))
- else: # workaround to <https://stackoverflow.com/q/7063128>
- cut_i = self.size.x - x - 1
- cut = line[:cut_i]
- last_char = line[cut_i]
- stdscr.addstr(y, self.size.x - 2, last_char, curses.color_pair(1))
- stdscr.insstr(y, self.size.x - 2, ' ')
- stdscr.addstr(y, x, cut, curses.color_pair(1))
+ self.screen.safe_addstr(y, x, line, curses.color_pair(1))
def handle_input(msg):
command, args = self.parser.parse(msg)
def task_action_on(action):
return action_tasks[action] in self.game.tasks
- def msg_into_lines_of_width(msg, width):
- chunk = ''
- lines = []
- x = 0
- for i in range(len(msg)):
- if x >= width or msg[i] == "\n":
- lines += [chunk]
- chunk = ''
- x = 0
- if msg[i] == "\n":
- x -= 1
- if msg[i] != "\n":
- chunk += msg[i]
- x += 1
- lines += [chunk]
- return lines
-
def reset_screen_size():
- self.size = YX(*stdscr.getmaxyx())
- self.size = self.size - YX(self.size.y % 4, 0)
- self.size = self.size - YX(0, self.size.x % 4)
- self.left_window_width = min(52, int(self.size.x / 2))
- self.right_window_width = self.size.x - self.left_window_width
+ self.screen.reset_size()
+ self.left_window_width = min(52, int(self.screen.size.x / 2))
+ self.right_window_width = self.screen.size.x - self.left_window_width
def recalc_input_lines():
if not self.mode.has_input_prompt:
lines += msg_into_lines_of_width(line, self.right_window_width)
lines.reverse()
height_header = 2
- max_y = self.size.y - len(self.input_lines)
+ max_y = self.screen.size.y - len(self.input_lines)
for i in range(len(lines)):
if (i >= max_y - height_header):
break
height_header = 2
for i in range(len(lines)):
y = height_header + i
- if y >= self.size.y - len(self.input_lines):
+ if y >= self.screen.size.y - len(self.input_lines):
break
safe_addstr(y, self.left_window_width, lines[i])
def draw_input():
- y = self.size.y - len(self.input_lines)
+ y = self.screen.size.y - len(self.input_lines)
for i in range(len(self.input_lines)):
safe_addstr(y, self.left_window_width, self.input_lines[i])
y += 1
else:
for line in map_lines_split:
self.map_lines += [''.join(line)]
- window_center = YX(int(self.size.y / 2),
+ window_center = YX(int(self.screen.size.y / 2),
int(self.left_window_width / 2))
center = self.game.player.position
if self.mode.shows_info or self.mode.name == 'control_tile_draw':
term_x = max(0, -self.offset.x)
map_y = max(0, self.offset.y)
map_x = max(0, self.offset.x)
- while term_y < self.size.y and map_y < len(self.map_lines):
+ while term_y < self.screen.size.y and map_y < len(self.map_lines):
to_draw = self.map_lines[map_y][map_x:self.left_window_width + self.offset.x]
safe_addstr(term_y, term_x, to_draw)
term_y += 1
players = [t for t in self.game.things if t.type_ == 'Player']
players.sort(key=lambda t: len(t.name))
players.reverse()
- shrink_offset = max(0, (self.size.y - self.left_window_width // 2) // 2)
+ shrink_offset = max(0, (self.screen.size.y - self.left_window_width // 2) // 2)
y = 0
for t in players:
offset_y = y - shrink_offset
name = name[:max_len - 1] + '…'
safe_addstr(y, 0, '@%s:%s' % (t.thing_char, name))
y += 1
- if y >= self.size.y:
+ if y >= self.screen.size.y:
break
def draw_face_popup():
safe_addstr(end_y, start_x, '| ' + body_part[12:18] + ' |')
if hasattr(t, 'face'):
- draw_body_part(t.face, self.size.y - 3)
+ draw_body_part(t.face, self.screen.size.y - 3)
if hasattr(t, 'hat'):
- draw_body_part(t.hat, self.size.y - 6)
- safe_addstr(self.size.y - 2, start_x, '----------')
+ draw_body_part(t.hat, self.screen.size.y - 6)
+ safe_addstr(self.screen.size.y - 2, start_x, '----------')
name = t.name[:]
if len(name) > 7:
name = name[:6 - 1] + '…'
- safe_addstr(self.size.y - 1, start_x,
+ safe_addstr(self.screen.size.y - 1, start_x,
'@%s:%s' % (t.thing_char, name))
def draw_help():
content += '[%s] – %s\n' % (key, action_descriptions[action])
content += '\n'
content += self.mode.list_available_modes(self)
- for i in range(self.size.y):
+ for i in range(self.screen.size.y):
safe_addstr(i,
self.left_window_width * (not self.mode.has_input_prompt),
' ' * self.left_window_width)
for line in content.split('\n'):
lines += msg_into_lines_of_width(line, self.right_window_width)
for i in range(len(lines)):
- if i >= self.size.y:
+ if i >= self.screen.size.y:
break
safe_addstr(i,
self.left_window_width * (not self.mode.has_input_prompt),
lines[i])
def draw_screen():
- stdscr.clear()
- stdscr.bkgd(' ', curses.color_pair(1))
+ self.screen.stdscr.clear()
+ self.screen.stdscr.bkgd(' ', curses.color_pair(1))
recalc_input_lines()
if self.mode.has_input_prompt:
draw_input()
'dance': 'DANCE',
}
- curses.curs_set(0) # hide cursor
curses.start_color()
self.set_default_colors()
curses.init_pair(1, 7, 0)
self.log_msg('@ unfortunately, your terminal does not seem to '
'support re-definition of colors; you might miss out '
'on some color effects')
- stdscr.timeout(10)
reset_screen_size()
self.explorer = YX(0, 0)
self.input_ = ''
for msg in self.socket.get_message():
handle_input(msg)
try:
- key = stdscr.getkey()
+ key = self.screen.stdscr.getkey()
self.do_refresh = True
except curses.error:
continue
self.restore_input_values()
elif self.mode.has_input_prompt and key != '\n': # Return key
self.input_ += key
- max_length = self.right_window_width * self.size.y - len(input_prompt) - 1
+ max_length = self.right_window_width * self.screen.size.y - len(input_prompt) - 1
if len(self.input_) > max_length:
self.input_ = self.input_[:max_length]
elif key == self.keys['help'] and not self.mode.is_single_char_entry: