/
termboxmodule.pyx
261 lines (223 loc) · 5.23 KB
/
termboxmodule.pyx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
"""Termbox library python binding.
This is a binding module for termbox library.
"""
include "termboxconfig.pyx"
cdef extern from "stdint.h":
ctypedef unsigned int uint32_t
ctypedef unsigned short uint16_t
ctypedef signed int int32_t
cdef extern from "../termbox.h":
struct tb_event:
uint16_t type
uint32_t ch
uint16_t key
uint16_t mod
int32_t w
int32_t h
int tb_init()
void tb_shutdown()
void tb_present()
void tb_clear()
void tb_change_cell(int x, int y, uint32_t ch, uint16_t fg, uint16_t bg)
int tb_width()
int tb_height()
void tb_set_cursor(int x, int y)
void tb_select_input_mode(int mode)
int tb_peek_event(tb_event *event, int timeout) nogil
int tb_poll_event(tb_event *event) nogil
class TermboxException(Exception):
def __init__(self, msg):
self.msg = msg
def __str__(self):
return self.msg
import threading
__instance = None
# keys ----------------------------------
KEY_F1 = (0xFFFF-0)
KEY_F2 = (0xFFFF-1)
KEY_F3 = (0xFFFF-2)
KEY_F4 = (0xFFFF-3)
KEY_F5 = (0xFFFF-4)
KEY_F6 = (0xFFFF-5)
KEY_F7 = (0xFFFF-6)
KEY_F8 = (0xFFFF-7)
KEY_F9 = (0xFFFF-8)
KEY_F10 = (0xFFFF-9)
KEY_F11 = (0xFFFF-10)
KEY_F12 = (0xFFFF-11)
KEY_INSERT = (0xFFFF-12)
KEY_DELETE = (0xFFFF-13)
KEY_HOME = (0xFFFF-14)
KEY_END = (0xFFFF-15)
KEY_PGUP = (0xFFFF-16)
KEY_PGDN = (0xFFFF-17)
KEY_ARROW_UP = (0xFFFF-18)
KEY_ARROW_DOWN = (0xFFFF-19)
KEY_ARROW_LEFT = (0xFFFF-20)
KEY_ARROW_RIGHT = (0xFFFF-21)
KEY_CTRL_TILDE = 0x00
KEY_CTRL_2 = 0x00
KEY_CTRL_A = 0x01
KEY_CTRL_B = 0x02
KEY_CTRL_C = 0x03
KEY_CTRL_D = 0x04
KEY_CTRL_E = 0x05
KEY_CTRL_F = 0x06
KEY_CTRL_G = 0x07
KEY_BACKSPACE = 0x08
KEY_CTRL_H = 0x08
KEY_TAB = 0x09
KEY_CTRL_I = 0x09
KEY_CTRL_J = 0x0A
KEY_CTRL_K = 0x0B
KEY_CTRL_L = 0x0C
KEY_ENTER = 0x0D
KEY_CTRL_M = 0x0D
KEY_CTRL_N = 0x0E
KEY_CTRL_O = 0x0F
KEY_CTRL_P = 0x10
KEY_CTRL_Q = 0x11
KEY_CTRL_R = 0x12
KEY_CTRL_S = 0x13
KEY_CTRL_T = 0x14
KEY_CTRL_U = 0x15
KEY_CTRL_V = 0x16
KEY_CTRL_W = 0x17
KEY_CTRL_X = 0x18
KEY_CTRL_Y = 0x19
KEY_CTRL_Z = 0x1A
KEY_ESC = 0x1B
KEY_CTRL_LSQ_BRACKET = 0x1B
KEY_CTRL_3 = 0x1B
KEY_CTRL_4 = 0x1C
KEY_CTRL_BACKSLASH = 0x1C
KEY_CTRL_5 = 0x1D
KEY_CTRL_RSQ_BRACKET = 0x1D
KEY_CTRL_6 = 0x1E
KEY_CTRL_7 = 0x1F
KEY_CTRL_SLASH = 0x1F
KEY_CTRL_UNDERSCORE = 0x1F
KEY_SPACE = 0x20
KEY_BACKSPACE2 = 0x7F
KEY_CTRL_8 = 0x7F
MOD_ALT = 0x01
# attributes ----------------------
BLACK = 0x00
RED = 0x01
GREEN = 0x02
YELLOW = 0x03
BLUE = 0x04
MAGENTA = 0x05
CYAN = 0x06
WHITE = 0x07
BOLD = 0x10
UNDERLINE = 0x20
# misc ----------------------------
HIDE_CURSOR = -1
INPUT_ESC = 1
INPUT_ALT = 2
EVENT_KEY = 1
EVENT_RESIZE = 2
cdef class Termbox:
cdef int created
cdef object _poll_lock
def __cinit__(self):
cdef int ret
global __instance
self.created = 0
self._poll_lock = threading.Lock()
if __instance:
raise TermboxException("It is possible to create only one instance of Termbox")
ret = tb_init()
ret = 1
if ret < 0:
raise TermboxException("Failed to init Termbox")
__instance = self
self.created = 1
def __dealloc__(self):
self.close()
def __del__(self):
self.close()
def __exit__(self, *args):#t, value, traceback):
self.close()
def __enter__(self):
return self
def close(self):
global __instance
if self.created:
tb_shutdown()
self.created = 0
__instance = None
def present(self):
"""Sync state of the internal cell buffer with the terminal.
"""
tb_present()
pass
def change_cell(self, int x, int y, int ch, uint16_t fg, uint16_t bg):
"""Change cell in position (x;y).
"""
tb_change_cell(x, y, ch, fg, bg)
def width(self):
"""Returns height of the terminal screen.
"""
return int(tb_width())
def height(self):
"""Return width of the terminal screen.
"""
return int(tb_height())
def clear(self):
"""Clear the internal cell buffer.
"""
tb_clear()
def set_cursor(self, int x, int y):
"""Set cursor position to (x;y).
Set both arguments to HIDE_CURSOR or use 'hide_cursor' function to hide it.
"""
tb_set_cursor(x, y)
def hide_cursor(self):
"""Hide cursor.
"""
tb_set_cursor(-1, -1)
def select_input_mode(self, int mode):
"""Select preferred input mode: INPUT_ESC or INPUT_ALT.
"""
tb_select_input_mode(mode)
def peek_event(self, int timeout=0):
"""Wait for an event up to 'timeout' milliseconds and return it.
Returns None if there was no event and timeout is expired.
Returns a tuple otherwise: (type, unicode character, key, mod, width, height).
"""
cdef tb_event e
cdef int result
with self._poll_lock:
with nogil:
result = tb_peek_event(&e, timeout)
assert(result >= 0)
if result == 0:
return None
if e.ch:
IF PY_MAJOR_VERSION == 3:
uch = chr(e.ch)
ELIF PY_MAJOR_VERSION == 2:
uch = unichr(e.ch)
else:
uch = None
return (e.type, uch, e.key, e.mod, e.w, e.h)
def poll_event(self):
"""Wait for an event and return it.
Returns a tuple: (type, unicode character, key, mod, width, height).
"""
cdef tb_event e
cdef int result
with self._poll_lock:
with nogil:
result = tb_poll_event(&e)
assert(result >= 0)
if e.ch:
IF PY_MAJOR_VERSION == 3:
uch = chr(e.ch)
ELIF PY_MAJOR_VERSION == 2:
uch = unichr(e.ch)
else:
uch = None
return (e.type, uch, e.key, e.mod, e.w, e.h)