1# -*- coding: utf-8 -*-
2#
3# libcaca       Colour ASCII-Art library
4#               Python language bindings
5# Copyright (c) 2010 Alex Foulon <alxf@lavabit.com>
6#               All Rights Reserved
7#
8# This library is free software. It comes without any warranty, to
9# the extent permitted by applicable law. You can redistribute it
10# and/or modify it under the terms of the Do What the Fuck You Want
11# to Public License, Version 2, as published by Sam Hocevar. See
12# http://www.wtfpl.net/ for more details.
13#
14
15""" Libcaca Python bindings """
16
17import ctypes
18
19from caca import _lib, _PYTHON3, _bytes_to_str
20
21#color constants
22COLOR_BLACK = 0x00
23COLOR_BLUE = 0x01
24COLOR_GREEN = 0x02
25COLOR_CYAN = 0x03
26COLOR_RED = 0x04
27COLOR_MAGENTA = 0x05
28COLOR_BROWN = 0x06
29COLOR_LIGHTGRAY = 0x07
30COLOR_DARKGRAY = 0x08
31COLOR_LIGHTBLUE = 0x09
32COLOR_LIGHTGREEN = 0x0a
33COLOR_LIGHTCYAN = 0x0b
34COLOR_LIGHTRED = 0x0c
35COLOR_LIGHTMAGENTA = 0x0d
36COLOR_YELLOW = 0x0e
37COLOR_WHITE = 0x0f
38COLOR_DEFAULT = 0x10
39COLOR_TRANSPARENT = 0x20
40
41#styles constants
42STYLE_BOLD = 0x01
43STYLE_ITALICS = 0x02
44STYLE_UNDERLINE = 0x04
45STYLE_BLINK = 0x08
46
47#key constants
48EVENT_NONE = 0x0000
49EVENT_KEY_PRESS = 0x0001
50EVENT_KEY_RELEASE = 0x0002
51EVENT_MOUSE_PRESS = 0x0004
52EVENT_MOUSE_RELEASE = 0x0008
53EVENT_MOUSE_MOTION = 0x0010
54EVENT_RESIZE = 0x0020
55EVENT_QUIT = 0x0040
56EVENT_ANY = 0xffff
57
58#event constants
59KEY_UNKNOWN = 0x00
60KEY_CTRL_A = 0x01
61KEY_CTRL_B = 0x02
62KEY_CTRL_C = 0x03
63KEY_CTRL_D = 0x04
64KEY_CTRL_E = 0x05
65KEY_CTRL_F = 0x06
66KEY_CTRL_G = 0x07
67KEY_BACKSPACE = 0x08
68KEY_TAB = 0x09
69KEY_CTRL_J = 0x0a
70KEY_CTRL_K = 0x0b
71KEY_CTRL_L = 0x0c
72KEY_RETURN = 0x0d
73KEY_CTRL_N = 0x0e
74KEY_CTRL_O = 0x0f
75KEY_CTRL_P = 0x10
76KEY_CTRL_Q = 0x11
77KEY_CTRL_R = 0x12
78KEY_PAUSE = 0x13
79KEY_CTRL_T = 0x14
80KEY_CTRL_U = 0x15
81KEY_CTRL_V = 0x16
82KEY_CTRL_W = 0x17
83KEY_CTRL_X = 0x18
84KEY_CTRL_Y = 0x19
85KEY_CTRL_Z = 0x1a
86KEY_ESCAPE = 0x1b
87KEY_DELETE = 0x7f
88KEY_UP = 0x111
89KEY_DOWN = 0x112
90KEY_LEFT = 0x113
91KEY_RIGHT = 0x114
92KEY_INSERT = 0x115
93KEY_HOME = 0x116
94KEY_END = 0x117
95KEY_PAGEUP = 0x118
96KEY_PAGEDOWN = 0x119
97KEY_F1 = 0x11a
98KEY_F2 = 0x11b
99KEY_F3 = 0x11c
100KEY_F4 = 0x11d
101KEY_F5 = 0x11e
102KEY_F6 = 0x11f
103KEY_F7 = 0x120
104KEY_F8 = 0x121
105KEY_F9 = 0x122
106KEY_F10 = 0x123
107KEY_F11 = 0x124
108KEY_F12 = 0x125
109KEY_F13 = 0x126
110KEY_F14 = 0x127
111KEY_F15 = 0x128
112
113
114def get_version():
115    """ Return string with libcaca version information.
116    """
117    _lib.caca_get_version.restype = ctypes.c_char_p
118
119    if _PYTHON3:
120        return _bytes_to_str(_lib.caca_get_version())
121    else:
122        return _lib.caca_get_version()
123
124def get_display_driver_list():
125    """ Return a list of available drivers as tuple (name, description).
126    """
127    tmplst = []
128    retlst = []
129
130    _lib.caca_get_display_driver_list.restype = ctypes.POINTER(ctypes.c_char_p)
131
132    for item in _lib.caca_get_display_driver_list():
133        if item is not None and item != "":
134            if _PYTHON3:
135                tmplst.append(_bytes_to_str(item))
136            else:
137                tmplst.append(item)
138        else:
139            #memory error occured otherwise
140            break
141
142    for i in range(0, len(tmplst)):
143        if i % 2 == 0:
144            retlst.append((tmplst[i], tmplst[i+1]))
145
146    del tmplst
147    return retlst
148
149def get_export_list():
150    """ Return list of available export formats as tuple (name, description).
151    """
152    tmplst = []
153    retlst = []
154
155    _lib.caca_get_export_list.restype = ctypes.POINTER(ctypes.c_char_p)
156
157    for item in _lib.caca_get_export_list():
158        if item is not None and item != "":
159            if _PYTHON3:
160                tmplst.append(_bytes_to_str(item))
161            else:
162                tmplst.append(item)
163        else:
164            #memory error occured otherwise
165            break
166
167    for i in range(0, len(tmplst)):
168        if i % 2 == 0:
169            retlst.append((tmplst[i], tmplst[i+1]))
170
171    del tmplst
172    return retlst
173
174def get_import_list():
175    """ Return list of available import formats as tuple (name, description).
176    """
177    tmplst = []
178    retlst = []
179
180    _lib.caca_get_import_list.restype = ctypes.POINTER(ctypes.c_char_p)
181
182    autodetect = False
183    for item in _lib.caca_get_import_list():
184        if item is not None:
185            if item == "":
186                if not autodetect:
187                    if _PYTHON3:
188                        tmplst.append(_bytes_to_str("\"\""))
189                    else:
190                        tmplst.append("\"\"")
191                    autodetect = True
192                else:
193                    #memory error occured otherwise
194                    break
195            else:
196                if _PYTHON3:
197                    tmplst.append(_bytes_to_str(item))
198                else:
199                    tmplst.append(item)
200        else:
201            #memory error occured otherwise
202            break
203
204    for i in range(0, len(tmplst)):
205        if i % 2 == 0:
206            retlst.append((tmplst[i], tmplst[i+1]))
207
208    del tmplst
209    return retlst
210
211def get_font_list():
212    """ Return a list of available fonts.
213    """
214    fl = []
215
216    _lib.caca_get_font_list.restype = ctypes.POINTER(ctypes.c_char_p)
217
218    for item in _lib.caca_get_font_list():
219        if item is not None and item != "":
220            if _PYTHON3:
221                fl.append(_bytes_to_str(item))
222            else:
223                fl.append(item)
224        else:
225            #memory error occured otherwise
226            break
227
228    return fl
229
230def rand(range_min, range_max):
231    """ Generate a random integer within a range.
232
233        range_min   -- the lower bound of the integer range
234        range_max   __ the upper bound of the integer range
235    """
236    _lib.caca_rand.argtypes = [ctypes.c_int, ctypes.c_int]
237    _lib.caca_rand.restype  = ctypes.c_int
238
239    return _lib.caca_rand(range_min, range_max)
240
241def attr_to_ansi(attr):
242    """ Get DOS ANSI information from attribute.
243
244        attr    -- the requested attribute value
245    """
246    _lib.caca_attr_to_ansi.argtypes = [ctypes.c_uint32]
247    _lib.caca_attr_to_ansi.restype  = ctypes.c_uint8
248
249    return _lib.caca_attr_to_ansi(attr)
250
251def attr_to_ansi_fg(attr):
252    """ Get ANSI foreground information from attribute.
253
254        attr    -- the requested attribute value
255    """
256    _lib.caca_attr_to_ansi_fg.argtypes = [ctypes.c_uint32]
257    _lib.caca_attr_to_ansi_fg.restype  = ctypes.c_uint8
258
259    return _lib.caca_attr_to_ansi_fg(attr)
260
261def attr_to_ansi_bg(attr):
262    """ Get ANSI background information from attribute.
263
264        attr    -- the requested attribute value
265    """
266    _lib.caca_attr_to_ansi_bg.argtypes = [ctypes.c_uint32]
267    _lib.caca_attr_to_ansi_bg.restype  = ctypes.c_uint8
268
269    return _lib.caca_attr_to_ansi_bg(attr)
270
271def attr_to_rgb12_fg(attr):
272    """ Get 12-bit RGB foreground information from attribute.
273
274        attr    -- the requested attribute value
275    """
276    _lib.caca_attr_to_rgb12_fg.argtypes = [ctypes.c_uint32]
277    _lib.caca_attr_to_rgb12_fg.restype  = ctypes.c_uint16
278
279    return _lib.caca_attr_to_rgb12_fg(attr)
280
281def attr_to_rgb12_bg(attr):
282    """ Get 12-bit RGB background information from attribute.
283
284        attr    -- the requested attribute value
285    """
286    _lib.caca_attr_to_rgb12_bg.argtypes = [ctypes.c_uint32]
287    _lib.caca_attr_to_rgb12_bg.restype  = ctypes.c_uint16
288
289    return _lib.caca_attr_to_rgb12_bg(attr)
290
291def utf8_to_utf32(ch):
292    """ Convert a UTF-8 character to UTF-32.
293
294        ch  -- the character to convert
295    """
296    _lib.caca_utf8_to_utf32.argtypes = [ctypes.c_char_p,
297            ctypes.POINTER(ctypes.c_size_t)
298        ]
299    _lib.caca_utf8_to_utf32.restype  = ctypes.c_uint32
300
301    return _lib.caca_utf8_to_utf32(ch, ctypes.c_ulong(0))
302
303def utf32_to_utf8(ch):
304    """ Convert a UTF-32 character to UTF-8.
305
306        ch  -- the character to convert
307    """
308    _lib.caca_utf32_to_utf8.argtypes = [ctypes.c_char_p, ctypes.c_uint32]
309    _lib.caca_utf32_to_utf8.restype  = ctypes.c_int
310
311    buf = ctypes.c_buffer(7)
312    _lib.caca_utf32_to_utf8(buf, ch)
313
314    if _PYTHON3:
315        return _bytes_to_str(buf.raw).replace('\x00', '')
316    else:
317        return buf.raw.replace('\x00', '')
318
319def utf32_to_cp437(ch):
320    """ Convert a UTF-32 character to CP437.
321
322        ch  -- the character to convert
323    """
324    _lib.caca_utf32_to_cp437.argtypes = [ctypes.c_uint32]
325    _lib.caca_utf32_to_cp437.restype  = ctypes.c_uint8
326
327    return _lib.caca_utf32_to_cp437(ch)
328
329def cp437_to_utf32(ch):
330    """ Convert a CP437 character to UTF-32.
331
332        ch  -- the character to convert
333    """
334    _lib.caca_cp437_to_utf8.argtypes = [ctypes.c_uint8]
335    _lib.caca_cp437_to_utf8.restype  = ctypes.c_uint32
336
337    return _lib.caca_cp437_to_utf8(ch)
338
339def utf32_to_ascii(ch):
340    """ Convert a UTF-32 character to ASCII.
341
342        ch  -- the character to convert
343    """
344    _lib.caca_utf32_to_ascii.argtypes = [ctypes.c_uint32]
345    _lib.caca_utf32_to_ascii.restype  = ctypes.c_uint8
346
347    return _lib.caca_utf32_to_ascii(ch)
348
349def utf32_is_fullwidth(ch):
350    """ Tell whether a UTF-32 character is fullwidth.
351
352        ch  -- the UTF-32 character
353    """
354    _lib.caca_utf32_is_fullwidth.argtypes = [ctypes.c_uint32]
355    _lib.caca_utf32_is_fullwidth.restype  = ctypes.c_int
356
357    return _lib.caca_utf32_is_fullwidth(ch)
358
359