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

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