1# Copyright (c) 2009, Tomohiro Kusumi 2# All rights reserved. 3# 4# Redistribution and use in source and binary forms, with or without 5# modification, are permitted provided that the following conditions are met: 6# 7# 1. Redistributions of source code must retain the above copyright notice, this 8# list of conditions and the following disclaimer. 9# 2. Redistributions in binary form must reproduce the above copyright notice, 10# this list of conditions and the following disclaimer in the documentation 11# and/or other materials provided with the distribution. 12# 13# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 24import os 25import sys 26 27from . import log 28from . import setting 29from . import terminal 30from . import util 31 32if not setting.use_stdout: 33 from . import ncurses as _screen 34else: 35 from . import stdout as _screen 36 37Error = _screen.Error 38 39_std = None 40_size = util.Pair() 41_signaled = False 42_soft_resize = False 43 44# no .get() wrapper, out of range input is error 45chr_repr = {} 46buf_attr = {} 47 48A_NONE = _screen.A_NONE 49A_BOLD = _screen.A_BOLD 50A_REVERSE = _screen.A_REVERSE # unused 51A_STANDOUT = _screen.A_STANDOUT 52A_UNDERLINE = _screen.A_UNDERLINE 53A_COLOR_FB = _screen.A_NONE 54A_COLOR_CURRENT = _screen.A_NONE 55A_COLOR_ZERO = _screen.A_NONE 56A_COLOR_FF = _screen.A_NONE 57A_COLOR_PRINT = _screen.A_NONE 58A_COLOR_DEFAULT = _screen.A_NONE 59A_COLOR_VISUAL = _screen.A_NONE 60 61BUTTON1_CLICKED = _screen.BUTTON1_CLICKED 62BUTTON1_PRESSED = _screen.BUTTON1_PRESSED 63BUTTON1_RELEASED = _screen.BUTTON1_RELEASED 64BUTTON1_DOUBLE_CLICKED = _screen.BUTTON1_DOUBLE_CLICKED 65BUTTON1_TRIPLE_CLICKED = _screen.BUTTON1_TRIPLE_CLICKED 66REPORT_MOUSE_POSITION = _screen.REPORT_MOUSE_POSITION 67 68def init(): 69 global _std, A_COLOR_FB, A_COLOR_CURRENT, A_COLOR_ZERO, A_COLOR_FF, \ 70 A_COLOR_PRINT, A_COLOR_DEFAULT, A_COLOR_VISUAL 71 if update_size() == -1: 72 return -1 73 if _std: 74 return -1 75 _std, A_COLOR_FB, A_COLOR_CURRENT, A_COLOR_ZERO, A_COLOR_FF, \ 76 A_COLOR_PRINT, A_COLOR_DEFAULT, A_COLOR_VISUAL = _screen.init() 77 _std.keypad(1) 78 _std.bkgd(' ', A_COLOR_FB) 79 _std.refresh() 80 81 this = sys.modules[__name__] 82 l = [] 83 for x in ("NONE", "BOLD", "REVERSE", "STANDOUT", "UNDERLINE", "COLOR_FB", 84 "COLOR_CURRENT", "COLOR_ZERO", "COLOR_FF", "COLOR_PRINT", 85 "COLOR_DEFAULT", "COLOR_VISUAL"): 86 l.append("A_{0}=0x{1:X}".format(x, getattr(this, "A_" + x))) 87 log.debug("screen: {0}".format(l)) 88 89 chr_repr.clear() 90 for x in util.get_xrange(0, 256): 91 chr_repr[x] = chr(x) if util.isprint(x) else '.' 92 93 buf_attr.clear() 94 for x in util.get_xrange(0, 256): 95 if setting.has_buffer_attr(): 96 if x == 0: 97 _ = A_COLOR_ZERO 98 elif x == 0xff: 99 _ = A_COLOR_FF 100 elif util.isprint(x): 101 _ = A_COLOR_PRINT 102 else: 103 _ = A_COLOR_DEFAULT 104 else: 105 _ = A_NONE 106 buf_attr[x] = _ 107 log.debug("buf_attr: {0}".format(set(sorted(buf_attr.values())))) 108 109def cleanup(): 110 global _std 111 clear_size() 112 if _std: 113 _std.keypad(0) 114 _std = None 115 _screen.cleanup() # must always cleanup regardless of _std 116 117def clear_refresh(): 118 _std.clear() # erase contents 119 _std.refresh() # refresh screen 120 121# XXX adhoc way to find if in stream 122def __test_stream(): 123 return os.path.isfile(setting.get_stream_path()) 124 125def doupdate(): 126 _screen.doupdate() 127 128def flash(): 129 # ignore flash if in stream (too slow depending on stream size) 130 if not __test_stream(): 131 _screen.flash() 132 133def get_size_y(): 134 return _size.y 135 136def get_size_x(): 137 return _size.x 138 139def update_size(): 140 y, x = terminal.get_size() 141 y = __override_size(y, setting.terminal_height) 142 x = __override_size(x, setting.terminal_width) 143 if y > 0 and x > 0: 144 _size.set(y, x) 145 else: 146 clear_size() 147 return -1 148 149def __override_size(term_size, cfg_size): 150 if cfg_size <= 0: 151 return term_size 152 if term_size == -1: 153 return cfg_size 154 assert term_size > 0, term_size 155 assert cfg_size > 0, cfg_size 156 if cfg_size > term_size: 157 return term_size 158 else: 159 return cfg_size 160 161def clear_size(): 162 _size.set(0, 0) 163 164def sti(): 165 global _signaled 166 _signaled = True 167 168def cli(): 169 global _signaled 170 _signaled = False 171 172def test_signal(): 173 ret = _signaled 174 if ret: 175 cli() 176 return ret 177 178def set_soft_resize(): 179 global _soft_resize 180 _soft_resize = True 181 182def clear_soft_resize(): 183 global _soft_resize 184 _soft_resize = False 185 186def test_soft_resize(): 187 return _soft_resize 188 189def has_chgat(): 190 return _screen.has_chgat() 191 192def use_alt_chgat(): 193 return setting.use_alt_chgat or not has_chgat() 194 195def has_color(): 196 return _screen.has_color() 197 198def use_color(): 199 return _screen.use_color() 200 201def iter_color_name(): 202 for s in _screen.iter_color_name(): 203 yield s 204 205def getmouse(): 206 return _screen.getmouse() 207 208def get_mouse_event_name(bstate): 209 return _screen.get_mouse_event_name(bstate) 210 211def alloc_all(ref=None): 212 return alloc(get_size_y(), get_size_x(), 0, 0, ref) 213 214def alloc(leny, lenx, begy, begx, ref=None): 215 scr = _screen.newwin(leny, lenx, begy, begx, ref) 216 scr.scrollok(0) 217 scr.idlok(0) 218 scr.keypad(1) 219 scr.bkgd(' ', A_COLOR_FB) 220 return scr 221