source: libcaca/trunk/caca/driver_slang.c @ 539

Last change on this file since 539 was 539, checked in by Sam Hocevar, 15 years ago
  • Split caca/graphics.c into driver-specific files. Resize is currently broken, and event handling is not yet in the driver-specific files, but I will of course fix that later.
  • Property svn:keywords set to Id
File size: 10.1 KB
Line 
1/*
2 *  libcaca       ASCII-Art library
3 *  Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  This library is free software; you can redistribute it and/or
7 *  modify it under the terms of the Do What The Fuck You Want To
8 *  Public License, Version 2, as published by Sam Hocevar. See
9 *  http://sam.zoy.org/wtfpl/COPYING for more details.
10 */
11
12/** \file graphics.c
13 *  \version \$Id: driver_slang.c 539 2006-03-06 23:01:59Z sam $
14 *  \author Sam Hocevar <sam@zoy.org>
15 *  \brief Character drawing
16 *
17 *  This file contains character and string drawing functions.
18 */
19
20#include "config.h"
21
22#if defined(HAVE_INTTYPES_H) || defined(_DOXYGEN_SKIP_ME)
23#   include <inttypes.h>
24#else
25typedef unsigned int uint32_t;
26typedef unsigned char uint8_t;
27#endif
28
29#if defined(USE_SLANG)
30
31#if defined(HAVE_SLANG_SLANG_H)
32#   include <slang/slang.h>
33#else
34#   include <slang.h>
35#endif
36
37#include <stdio.h> /* BUFSIZ */
38#include <string.h>
39#include <stdlib.h>
40#if defined(HAVE_UNISTD_H)
41#   include <unistd.h>
42#endif
43#include <stdarg.h>
44
45#if defined(HAVE_SIGNAL_H)
46#   include <signal.h>
47#endif
48
49#include "caca.h"
50#include "caca_internals.h"
51#include "cucul.h"
52#include "cucul_internals.h"
53
54/*
55 * Global variables
56 */
57
58/* Tables generated by test/optipal.c */
59static int const slang_palette[2*16*16] =
60{
61     1,  0,   2,  0,   3,  0,   4,  0,   5,  0,   6,  0,   7,  0,   8,  0,
62     9,  0,  10,  0,  11,  0,  12,  0,  13,  0,  14,  0,  15,  0,   0,  8,
63     8,  7,   7,  8,  15,  7,   7, 15,  15,  9,   9, 15,   1,  9,   9,  1,
64     7,  9,   9,  7,   8,  1,   1,  8,   0,  1,  15, 10,  10, 15,   2, 10,
65    10,  2,   7, 10,  10,  7,   8,  2,   2,  8,   0,  2,  15, 11,  11, 15,
66     3, 11,  11,  3,   7, 11,  11,  7,   8,  3,   3,  8,   0,  3,  15, 12,
67    12, 15,   4, 12,  12,  4,   7, 12,  12,  7,   8,  4,   4,  8,   0,  4,
68    15, 13,  13, 15,   5, 13,  13,  5,   7, 13,  13,  7,   8,  5,   5,  8,
69     0,  5,  15, 14,  14, 15,   6, 14,  14,  6,   7, 14,  14,  7,   8,  6,
70     6,  8,   0,  6,   4,  6,   6,  4,  12, 14,  14, 12,   6,  2,   2,  6,
71    14, 10,  10, 14,   2,  3,   3,  2,  10, 11,  11, 10,   3,  1,   1,  3,
72    11,  9,   9, 11,   1,  5,   5,  1,   9, 13,  13,  9,   5,  4,   4,  5,
73    13, 12,  12, 13,   4, 14,   6, 12,  12,  6,  14,  4,   6, 10,   2, 14,
74    14,  2,  10,  6,   2, 11,   3, 10,  10,  3,  11,  2,   3,  9,   1, 11,
75    11,  1,   9,  3,   1, 13,   5,  9,   9,  5,  13,  1,   5, 12,   4, 13,
76    13,  4,  12,  5,   0,  7,   0, 15,  15,  8,   8, 15,  15,  1,   7,  1,
77     1,  6,   2,  5,   3,  4,   4,  3,   5,  2,   6,  1,   0,  0,   1,  1,
78     9,  6,  10,  5,  11,  4,  12,  3,  13,  2,  14,  1,   2,  2,   3,  3,
79     4,  4,   5,  5,   6,  6,   7,  7,  14,  9,   1, 15,   8,  9,   8,  8,
80     9,  9,   1,  7,   0,  9,   9,  8,   6,  9,  13, 10,   2, 15,   8, 10,
81     7,  2,  15,  2,   2,  7,   0, 10,  10,  8,   5, 10,  12, 11,   3, 15,
82     8, 11,   7,  3,  15,  3,   3,  7,   0, 11,  11,  8,   4, 11,  11, 12,
83     4, 15,   8, 12,   7,  4,  15,  4,   4,  7,   0, 12,  12,  8,   3, 12,
84    10, 13,   5, 15,   8, 13,   7,  5,  15,  5,   5,  7,   0, 13,  13,  8,
85     2, 13,   9, 14,   6, 15,   8, 14,   7,  6,  15,  6,   6,  7,   0, 14,
86    14,  8,   1, 14,   5,  6,   2,  4,  13, 14,  10, 12,   4,  2,   3,  6,
87    12, 10,  11, 14,   6,  3,   1,  2,  14, 11,   9, 10,   2,  1,   5,  3,
88    10,  9,  13, 11,   3,  5,   4,  1,  11, 13,  12,  9,   1,  4,   6,  5,
89     9, 12,  14, 13,   5, 14,   2, 12,  13,  6,  10,  4,   4, 10,   3, 14,
90    12,  2,  11,  6,   6, 11,   1, 10,  14,  3,   9,  2,   2,  9,   5, 11,
91    10,  1,  13,  3,   3, 13,   4,  9,  11,  5,  12,  1,   1, 12,   6, 13,
92     9,  4,  14,  5,  10, 10,  11, 11,  12, 12,  13, 13,  14, 14,  15, 15,
93};
94
95static int const slang_assoc[16*16] =
96{
97    134, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
98    28, 135, 214, 86, 219, 91, 133, 127, 26, 23, 240, 112, 245, 117, 141, 126,
99    37, 211, 142, 83, 206, 132, 78, 160, 35, 237, 32, 109, 232, 140, 104, 161,
100    46, 87, 82, 143, 131, 215, 210, 169, 44, 113, 108, 41, 139, 241, 236, 170,
101    55, 222, 203, 130, 144, 94, 75, 178, 53, 248, 229, 138, 50, 120, 101, 179,
102    64, 90, 129, 218, 95, 145, 223, 187, 62, 116, 137, 244, 121, 59, 249, 188,
103    73, 128, 79, 207, 74, 202, 146, 196, 71, 136, 105, 233, 100, 228, 68, 197,
104    122, 153, 162, 171, 180, 189, 198, 147, 16, 25, 34, 43, 52, 61, 70, 18,
105    15, 27, 36, 45, 54, 63, 72, 17, 151, 155, 164, 173, 182, 191, 200, 124,
106    154, 22, 238, 110, 243, 115, 156, 24, 150, 152, 216, 88, 221, 93, 148, 20,
107    163, 235, 31, 107, 230, 165, 102, 33, 159, 213, 250, 85, 208, 157, 80, 29,
108    172, 111, 106, 40, 174, 239, 234, 42, 168, 89, 84, 251, 166, 217, 212, 38,
109    181, 246, 227, 183, 49, 118, 99, 51, 177, 224, 205, 175, 252, 96, 77, 47,
110    190, 114, 192, 242, 119, 58, 247, 60, 186, 92, 184, 220, 97, 253, 225, 56,
111    199, 201, 103, 231, 98, 226, 67, 69, 195, 193, 81, 209, 76, 204, 254, 65,
112    123, 149, 158, 167, 176, 185, 194, 19, 125, 21, 30, 39, 48, 57, 66, 255,
113};
114
115int slang_init_graphics(caca_t *);
116int slang_end_graphics(caca_t *);
117int slang_set_window_title(caca_t *, char const *);
118unsigned int slang_get_window_width(caca_t *);
119unsigned int slang_get_window_height(caca_t *);
120void slang_display(caca_t *);
121void slang_handle_resize(caca_t *);
122
123/*
124 * Local functions
125 */
126static void slang_init_palette(void);
127
128#if defined(HAVE_SIGNAL)
129static RETSIGTYPE sigwinch_handler(int);
130static caca_t *sigwinch_kk; /* FIXME: we ought to get rid of this */
131#endif
132
133#if !defined(_DOXYGEN_SKIP_ME)
134int slang_init_graphics(caca_t *kk)
135{
136#if defined(HAVE_SIGNAL)
137    sigwinch_kk = kk;
138    signal(SIGWINCH, sigwinch_handler);
139#endif
140
141    /* Initialise slang library */
142    SLsig_block_signals();
143    SLtt_get_terminfo();
144
145    if(SLkp_init() == -1)
146    {
147        SLsig_unblock_signals();
148        return NULL;
149    }
150
151    SLang_init_tty(-1, 0, 1);
152
153    if(SLsmg_init_smg() == -1)
154    {
155        SLsig_unblock_signals();
156        return NULL;
157    }
158
159    SLsig_unblock_signals();
160
161    SLsmg_cls();
162    SLtt_set_cursor_visibility(0);
163    SLkp_define_keysym("\e[M", 1001);
164    SLtt_set_mouse_mode(1, 0);
165    SLsmg_refresh();
166
167    /* Disable scrolling so that hashmap scrolling optimization code
168     * does not cause ugly refreshes due to slow terminals */
169    SLtt_Term_Cannot_Scroll = 1;
170
171    slang_init_palette();
172
173    /* Disable alt charset support so that we get a chance to have all
174     * 256 colour pairs */
175    SLtt_Has_Alt_Charset = 0;
176
177    cucul_set_size(kk->qq, SLtt_Screen_Cols, SLtt_Screen_Rows);
178
179    return 0;
180}
181
182int slang_end_graphics(caca_t *kk)
183{
184    SLtt_set_mouse_mode(0, 0);
185    SLtt_set_cursor_visibility(1);
186    SLang_reset_tty();
187    SLsmg_reset_smg();
188
189    return 0;
190}
191#endif /* _DOXYGEN_SKIP_ME */
192
193int slang_set_window_title(caca_t *kk, char const *title)
194{
195    return 0;
196}
197
198unsigned int slang_get_window_width(caca_t *kk)
199{
200    /* Fallback to a 6x10 font */
201    return kk->qq->width * 6;
202}
203
204unsigned int slang_get_window_height(caca_t *kk)
205{
206    /* Fallback to a 6x10 font */
207    return kk->qq->height * 10;
208}
209
210void slang_display(caca_t *kk)
211{
212    int x, y;
213    uint8_t *attr = kk->qq->attr;
214    uint32_t *chars = kk->qq->chars;
215    for(y = 0; y < (int)kk->qq->height; y++)
216    {
217        SLsmg_gotorc(y, 0);
218        for(x = kk->qq->width; x--; )
219        {
220#if defined(OPTIMISE_SLANG_PALETTE)
221            /* If foreground == background, just don't use this colour
222             * pair, and print a space instead of the real character. */
223            uint8_t fgcolor = *attr & 0xf;
224            uint8_t bgcolor = *attr >> 4;
225            if(fgcolor != bgcolor)
226            {
227                SLsmg_set_color(slang_assoc[*attr++]);
228                SLsmg_write_char(*chars++ & 0x7f);
229            }
230            else
231            {
232                if(fgcolor == CUCUL_COLOR_BLACK)
233                    fgcolor = CUCUL_COLOR_WHITE;
234                else if(fgcolor == CUCUL_COLOR_WHITE
235                         || fgcolor <= CUCUL_COLOR_LIGHTGRAY)
236                    fgcolor = CUCUL_COLOR_BLACK;
237                else
238                    fgcolor = CUCUL_COLOR_WHITE;
239                SLsmg_set_color(slang_assoc[fgcolor + 16 * bgcolor]);
240                SLsmg_write_char(' ');
241                chars++;
242                attr++;
243            }
244#else
245            SLsmg_set_color(*attr++);
246            SLsmg_write_char(*chars++ & 0x7f);
247#endif
248        }
249    }
250    SLsmg_refresh();
251}
252
253/*
254 * XXX: following functions are local
255 */
256
257void slang_handle_resize(caca_t *kk)
258{
259    unsigned int new_width, new_height;
260
261    new_width = kk->qq->width;
262    new_height = kk->qq->height;
263
264    SLtt_get_screen_size();
265    new_width = SLtt_Screen_Cols;
266    new_height = SLtt_Screen_Rows;
267
268    if(new_width != kk->qq->width || new_height != kk->qq->height)
269        SLsmg_reinit_smg();
270}
271
272static void slang_init_palette(void)
273{
274    /* See SLang ref., 5.4.4. */
275    static char *slang_colors[16] =
276    {
277        /* Standard colours */
278        "black",
279        "blue",
280        "green",
281        "cyan",
282        "red",
283        "magenta",
284        "brown",
285        "lightgray",
286        /* Bright colours */
287        "gray",
288        "brightblue",
289        "brightgreen",
290        "brightcyan",
291        "brightred",
292        "brightmagenta",
293        "yellow",
294        "white",
295    };
296
297#if defined(OPTIMISE_SLANG_PALETTE)
298    int i;
299
300    for(i = 0; i < 16 * 16; i++)
301        SLtt_set_color(i, NULL, slang_colors[slang_palette[i * 2]],
302                                slang_colors[slang_palette[i * 2 + 1]]);
303#else
304    int fg, bg;
305
306    for(bg = 0; bg < 16; bg++)
307        for(fg = 0; fg < 16; fg++)
308        {
309            int i = fg + 16 * bg;
310            SLtt_set_color(i, NULL, slang_colors[fg], slang_colors[bg]);
311        }
312#endif
313}
314
315#if defined(HAVE_SIGNAL)
316static RETSIGTYPE sigwinch_handler(int sig)
317{
318    sigwinch_kk->resize_event = 1;
319
320    signal(SIGWINCH, sigwinch_handler);;
321}
322#endif
323
324/*
325 * Driver initialisation
326 */
327
328void slang_init_driver(caca_t *kk)
329{
330    kk->driver.driver = CACA_DRIVER_SLANG;
331
332    kk->driver.init_graphics = slang_init_graphics;
333    kk->driver.end_graphics = slang_end_graphics;
334    kk->driver.set_window_title = slang_set_window_title;
335    kk->driver.get_window_width = slang_get_window_width;
336    kk->driver.get_window_height = slang_get_window_height;
337    kk->driver.display = slang_display;
338    kk->driver.handle_resize = slang_handle_resize;
339}
340
341#endif /* USE_SLANG */
342
Note: See TracBrowser for help on using the repository browser.