source: libcaca/trunk/caca/driver_ncurses.c @ 2056

Last change on this file since 2056 was 2056, checked in by Sam Hocevar, 12 years ago
  • Introduce cucul_get_canvas_chars() and cucul_get_canvas_attrs() to avoid direct cv->chars and cv->attrs access by display drivers.
  • Property svn:keywords set to Id
File size: 20.4 KB
Line 
1/*
2 *  libcaca       Colour ASCII-Art library
3 *  Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
4 *                2007 Ben Wiley Sittler <bsittler@gmail.com>
5 *                All Rights Reserved
6 *
7 *  $Id: driver_ncurses.c 2056 2007-11-25 14:12:01Z sam $
8 *
9 *  This library is free software. It comes without any warranty, to
10 *  the extent permitted by applicable law. You can redistribute it
11 *  and/or modify it under the terms of the Do What The Fuck You Want
12 *  To Public License, Version 2, as published by Sam Hocevar. See
13 *  http://sam.zoy.org/wtfpl/COPYING for more details.
14 */
15
16/*
17 *  This file contains the libcaca Ncurses input and output driver
18 */
19
20#include "config.h"
21#include "common.h"
22
23#if defined USE_NCURSES
24
25#if defined HAVE_NCURSESW_NCURSES_H
26#   include <ncursesw/ncurses.h>
27#elif defined HAVE_NCURSES_NCURSES_H
28#   include <ncurses/ncurses.h>
29#elif defined HAVE_NCURSES_H
30#   include <ncurses.h>
31#else
32#   include <curses.h>
33#endif
34
35#include <stdlib.h>
36#include <string.h>
37
38#if defined HAVE_UNISTD_H
39#   include <unistd.h>
40#endif
41#if defined HAVE_SIGNAL_H
42#   include <signal.h>
43#endif
44#if defined HAVE_SYS_IOCTL_H
45#   include <sys/ioctl.h>
46#endif
47#if defined HAVE_LOCALE_H
48#   include <locale.h>
49#endif
50#if defined HAVE_TERMIOS_H
51#   include <termios.h>
52#endif
53
54#include "cucul.h"
55#include "caca.h"
56#include "caca_internals.h"
57
58/*
59 * Emulation for missing ACS_* in older curses
60 */
61
62#ifndef ACS_BLOCK
63#define ACS_BLOCK '#'
64#endif
65
66#ifndef ACS_BOARD
67#define ACS_BOARD '#'
68#endif
69
70#ifndef ACS_BTEE
71#define ACS_BTEE '+'
72#endif
73
74#ifndef ACS_BULLET
75#define ACS_BULLET '.'
76#endif
77
78#ifndef ACS_CKBOARD
79#define ACS_CKBOARD ':'
80#endif
81
82#ifndef ACS_DARROW
83#define ACS_DARROW 'v'
84#endif
85
86#ifndef ACS_DEGREE
87#define ACS_DEGREE '\''
88#endif
89
90#ifndef ACS_DIAMOND
91#define ACS_DIAMOND '+'
92#endif
93
94#ifndef ACS_GEQUAL
95#define ACS_GEQUAL '>'
96#endif
97
98#ifndef ACS_HLINE
99#define ACS_HLINE '-'
100#endif
101
102#ifndef ACS_LANTERN
103#define ACS_LANTERN '#'
104#endif
105
106#ifndef ACS_LARROW
107#define ACS_LARROW '<'
108#endif
109
110#ifndef ACS_LEQUAL
111#define ACS_LEQUAL '<'
112#endif
113
114#ifndef ACS_LLCORNER
115#define ACS_LLCORNER '+'
116#endif
117
118#ifndef ACS_LRCORNER
119#define ACS_LRCORNER '+'
120#endif
121
122#ifndef ACS_LTEE
123#define ACS_LTEE '+'
124#endif
125
126#ifndef ACS_NEQUAL
127#define ACS_NEQUAL '!'
128#endif
129
130#ifndef ACS_PI
131#define ACS_PI '*'
132#endif
133
134#ifndef ACS_STERLING
135#define ACS_STERLING 'f'
136#endif
137
138#ifndef ACS_PLMINUS
139#define ACS_PLMINUS '#'
140#endif
141
142#ifndef ACS_PLUS
143#define ACS_PLUS '+'
144#endif
145
146#ifndef ACS_RARROW
147#define ACS_RARROW '>'
148#endif
149
150#ifndef ACS_RTEE
151#define ACS_RTEE '+'
152#endif
153
154#ifndef ACS_S1
155#define ACS_S1 '-'
156#endif
157
158#ifndef ACS_S3
159#define ACS_S3 '-'
160#endif
161
162#ifndef ACS_S7
163#define ACS_S7 '-'
164#endif
165
166#ifndef ACS_S9
167#define ACS_S9 '-'
168#endif
169
170#ifndef ACS_TTEE
171#define ACS_TTEE '+'
172#endif
173
174#ifndef ACS_UARROW
175#define ACS_UARROW '^'
176#endif
177
178#ifndef ACS_ULCORNER
179#define ACS_ULCORNER '+'
180#endif
181
182#ifndef ACS_URCORNER
183#define ACS_URCORNER '+'
184#endif
185
186#ifndef ACS_VLINE
187#define ACS_VLINE '|'
188#endif
189
190/*
191 * Local functions
192 */
193
194#if defined HAVE_SIGNAL
195static RETSIGTYPE sigwinch_handler(int);
196static caca_display_t *sigwinch_d; /* FIXME: we ought to get rid of this */
197#endif
198#if defined HAVE_GETENV && defined HAVE_PUTENV
199static void ncurses_check_terminal(void);
200#endif
201static void ncurses_write_utf32(uint32_t);
202
203struct driver_private
204{
205    int attr[16*16];
206    mmask_t oldmask;
207};
208
209static int ncurses_init_graphics(caca_display_t *dp)
210{
211    static int curses_colors[] =
212    {
213        /* Standard curses colours */
214        COLOR_BLACK,
215        COLOR_BLUE,
216        COLOR_GREEN,
217        COLOR_CYAN,
218        COLOR_RED,
219        COLOR_MAGENTA,
220        COLOR_YELLOW,
221        COLOR_WHITE,
222        /* Extra values for xterm-16color */
223        COLOR_BLACK + 8,
224        COLOR_BLUE + 8,
225        COLOR_GREEN + 8,
226        COLOR_CYAN + 8,
227        COLOR_RED + 8,
228        COLOR_MAGENTA + 8,
229        COLOR_YELLOW + 8,
230        COLOR_WHITE + 8
231    };
232
233    mmask_t newmask;
234    int fg, bg, max;
235
236    dp->drv.p = malloc(sizeof(struct driver_private));
237
238#if defined HAVE_GETENV && defined HAVE_PUTENV
239    ncurses_check_terminal();
240#endif
241
242#if defined HAVE_SIGNAL
243    sigwinch_d = dp;
244    signal(SIGWINCH, sigwinch_handler);
245#endif
246
247#if defined HAVE_LOCALE_H
248    setlocale(LC_ALL, "");
249#endif
250
251    _caca_set_term_title("caca for ncurses");
252
253    initscr();
254    keypad(stdscr, TRUE);
255    nonl();
256    raw();
257    noecho();
258    nodelay(stdscr, TRUE);
259    curs_set(0);
260
261    /* Activate mouse */
262    newmask = REPORT_MOUSE_POSITION | ALL_MOUSE_EVENTS;
263    mousemask(newmask, &dp->drv.p->oldmask);
264    mouseinterval(-1); /* No click emulation */
265
266    /* Set the escape delay to a ridiculously low value */
267    ESCDELAY = 10;
268
269    /* Activate colour */
270    start_color();
271
272    /* If COLORS == 16, it means the terminal supports full bright colours
273     * using setab and setaf (will use \e[90m \e[91m etc. for colours >= 8),
274     * we can build 16*16 colour pairs.
275     * If COLORS == 8, it means the terminal does not know about bright
276     * colours and we need to get them through A_BOLD and A_BLINK (\e[1m
277     * and \e[5m). We can only build 8*8 colour pairs. */
278    max = COLORS >= 16 ? 16 : 8;
279
280    for(bg = 0; bg < max; bg++)
281        for(fg = 0; fg < max; fg++)
282        {
283            /* Use ((max + 7 - fg) % max) instead of fg so that colour 0
284             * is light gray on black. Some terminals don't like this
285             * colour pair to be redefined. */
286            int col = ((max + 7 - fg) % max) + max * bg;
287            init_pair(col, curses_colors[fg], curses_colors[bg]);
288            dp->drv.p->attr[fg + 16 * bg] = COLOR_PAIR(col);
289
290            if(max == 8)
291            {
292                /* Bright fg on simple bg */
293                dp->drv.p->attr[fg + 8 + 16 * bg] = A_BOLD | COLOR_PAIR(col);
294                /* Simple fg on bright bg */
295                dp->drv.p->attr[fg + 16 * (bg + 8)] = A_BLINK
296                                                    | COLOR_PAIR(col);
297                /* Bright fg on bright bg */
298                dp->drv.p->attr[fg + 8 + 16 * (bg + 8)] = A_BLINK | A_BOLD
299                                                        | COLOR_PAIR(col);
300            }
301        }
302
303    dp->resize.allow = 1;
304    cucul_set_canvas_size(dp->cv, COLS, LINES);
305    dp->resize.allow = 0;
306
307    return 0;
308}
309
310static int ncurses_end_graphics(caca_display_t *dp)
311{
312    _caca_set_term_title("");
313    mousemask(dp->drv.p->oldmask, NULL);
314    curs_set(1);
315    noraw();
316    endwin();
317
318    free(dp->drv.p);
319
320    return 0;
321}
322
323static int ncurses_set_display_title(caca_display_t *dp, char const *title)
324{
325    _caca_set_term_title(title);
326
327    return 0;
328}
329
330static unsigned int ncurses_get_display_width(caca_display_t const *dp)
331{
332    /* Fallback to a 6x10 font */
333    return cucul_get_canvas_width(dp->cv) * 6;
334}
335
336static unsigned int ncurses_get_display_height(caca_display_t const *dp)
337{
338    /* Fallback to a 6x10 font */
339    return cucul_get_canvas_height(dp->cv) * 10;
340}
341
342static void ncurses_display(caca_display_t *dp)
343{
344    uint32_t const *cvchars = (uint32_t const *)cucul_get_canvas_chars(dp->cv);
345    uint32_t const *cvattrs = (uint32_t const *)cucul_get_canvas_attrs(dp->cv);
346    unsigned int width = cucul_get_canvas_width(dp->cv);
347    unsigned int height = cucul_get_canvas_height(dp->cv);
348    int x, y;
349
350    for(y = 0; y < (int)height; y++)
351    {
352        move(y, 0);
353        for(x = width; x--; )
354        {
355            attrset(dp->drv.p->attr[cucul_attr_to_ansi(*cvattrs++)]);
356            ncurses_write_utf32(*cvchars++);
357        }
358    }
359   
360    x = cucul_get_cursor_x(dp->cv);
361    y = cucul_get_cursor_y(dp->cv);
362    move(y, x);
363
364    refresh();
365}
366
367static void ncurses_handle_resize(caca_display_t *dp)
368{
369    struct winsize size;
370
371#if defined HAVE_SYS_IOCTL_H
372    if(ioctl(fileno(stdout), TIOCGWINSZ, &size) == 0)
373    {
374        dp->resize.w = size.ws_col;
375        dp->resize.h = size.ws_row;
376#if defined HAVE_RESIZE_TERM
377        resize_term(dp->resize.h, dp->resize.w);
378#else
379        resizeterm(dp->resize.h, dp->resize.w);
380#endif
381        wrefresh(curscr);
382        return;
383    }
384#endif
385
386    /* Fallback */
387    dp->resize.w = cucul_get_canvas_width(dp->cv);
388    dp->resize.h = cucul_get_canvas_height(dp->cv);
389}
390
391static int ncurses_get_event(caca_display_t *dp, caca_privevent_t *ev)
392{
393    int intkey;
394
395    intkey = getch();
396    if(intkey == ERR)
397    {
398        ev->type = CACA_EVENT_NONE;
399        return 0;
400    }
401
402    if(intkey < 0x7f)
403    {
404        ev->type = CACA_EVENT_KEY_PRESS;
405        ev->data.key.ch = intkey;
406        ev->data.key.utf32 = intkey;
407        ev->data.key.utf8[0] = intkey;
408        ev->data.key.utf8[1] = '\0';
409        return 1;
410    }
411
412    /* If the key was UTF-8, parse the whole sequence */
413    if(intkey >= 0x80 && intkey < 0x100)
414    {
415        int keys[7]; /* Necessary for ungetch(); */
416        char utf8[7];
417        uint32_t utf32;
418        unsigned int i, bytes = 0;
419
420        keys[0] = intkey;
421        utf8[0] = intkey;
422
423        for(i = 1; i < 6; i++)
424        {
425            keys[i] = getch();
426            utf8[i] = (unsigned char)keys[i];
427        }
428
429        utf8[i] = '\0';
430        utf32 = cucul_utf8_to_utf32(utf8, &bytes);
431
432        while(i > bytes)
433            ungetch(keys[--i]);
434
435        if(bytes)
436        {
437            ev->type = CACA_EVENT_KEY_PRESS;
438            ev->data.key.ch = 0;
439            ev->data.key.utf32 = utf32;
440            strcpy(ev->data.key.utf8, utf8);
441            return 1;
442        }
443    }
444
445    if(intkey == KEY_MOUSE)
446    {
447        MEVENT mevent;
448        getmouse(&mevent);
449
450        switch(mevent.bstate)
451        {
452#define PRESS(x) ev->data.mouse.button = x; \
453                 ev->type = CACA_EVENT_MOUSE_PRESS; _push_event(dp, ev)
454#define RELEASE(x) ev->data.mouse.button = x; \
455                   ev->type = CACA_EVENT_MOUSE_RELEASE; _push_event(dp, ev)
456#define CLICK(x) PRESS(x); RELEASE(x)
457            case BUTTON1_PRESSED: PRESS(1); break;
458            case BUTTON1_RELEASED: RELEASE(1); break;
459            case BUTTON1_CLICKED: CLICK(1); break;
460            case BUTTON1_DOUBLE_CLICKED: CLICK(1); CLICK(1); break;
461            case BUTTON1_TRIPLE_CLICKED: CLICK(1); CLICK(1); CLICK(1); break;
462            case BUTTON1_RESERVED_EVENT: break;
463
464            case BUTTON2_PRESSED: PRESS(2); break;
465            case BUTTON2_RELEASED: RELEASE(2); break;
466            case BUTTON2_CLICKED: CLICK(2); break;
467            case BUTTON2_DOUBLE_CLICKED: CLICK(2); CLICK(2); break;
468            case BUTTON2_TRIPLE_CLICKED: CLICK(2); CLICK(2); CLICK(2); break;
469            case BUTTON2_RESERVED_EVENT: break;
470
471            case BUTTON3_PRESSED: PRESS(3); break;
472            case BUTTON3_RELEASED: RELEASE(3); break;
473            case BUTTON3_CLICKED: CLICK(3); break;
474            case BUTTON3_DOUBLE_CLICKED: CLICK(3); CLICK(3); break;
475            case BUTTON3_TRIPLE_CLICKED: CLICK(3); CLICK(3); CLICK(3); break;
476            case BUTTON3_RESERVED_EVENT: break;
477
478            case BUTTON4_PRESSED: PRESS(4); break;
479            case BUTTON4_RELEASED: RELEASE(4); break;
480            case BUTTON4_CLICKED: CLICK(4); break;
481            case BUTTON4_DOUBLE_CLICKED: CLICK(4); CLICK(4); break;
482            case BUTTON4_TRIPLE_CLICKED: CLICK(4); CLICK(4); CLICK(4); break;
483            case BUTTON4_RESERVED_EVENT: break;
484
485            default:
486                break;
487#undef PRESS
488#undef RELEASE
489#undef CLICK
490        }
491
492        if(dp->mouse.x == (unsigned int)mevent.x &&
493           dp->mouse.y == (unsigned int)mevent.y)
494            return _pop_event(dp, ev);
495
496        dp->mouse.x = mevent.x;
497        dp->mouse.y = mevent.y;
498
499        ev->type = CACA_EVENT_MOUSE_MOTION;
500        ev->data.mouse.x = dp->mouse.x;
501        ev->data.mouse.y = dp->mouse.y;
502        return 1;
503    }
504
505    switch(intkey)
506    {
507        case KEY_UP: ev->data.key.ch = CACA_KEY_UP; break;
508        case KEY_DOWN: ev->data.key.ch = CACA_KEY_DOWN; break;
509        case KEY_LEFT: ev->data.key.ch = CACA_KEY_LEFT; break;
510        case KEY_RIGHT: ev->data.key.ch = CACA_KEY_RIGHT; break;
511
512        case KEY_IC: ev->data.key.ch = CACA_KEY_INSERT; break;
513        case KEY_DC: ev->data.key.ch = CACA_KEY_DELETE; break;
514        case 0x7f:
515        case KEY_BACKSPACE: ev->data.key.ch = CACA_KEY_BACKSPACE; break;
516        case KEY_HOME: ev->data.key.ch = CACA_KEY_HOME; break;
517        case KEY_END: ev->data.key.ch = CACA_KEY_END; break;
518        case KEY_PPAGE: ev->data.key.ch = CACA_KEY_PAGEUP; break;
519        case KEY_NPAGE: ev->data.key.ch = CACA_KEY_PAGEDOWN; break;
520
521        case KEY_F(1): ev->data.key.ch = CACA_KEY_F1; break;
522        case KEY_F(2): ev->data.key.ch = CACA_KEY_F2; break;
523        case KEY_F(3): ev->data.key.ch = CACA_KEY_F3; break;
524        case KEY_F(4): ev->data.key.ch = CACA_KEY_F4; break;
525        case KEY_F(5): ev->data.key.ch = CACA_KEY_F5; break;
526        case KEY_F(6): ev->data.key.ch = CACA_KEY_F6; break;
527        case KEY_F(7): ev->data.key.ch = CACA_KEY_F7; break;
528        case KEY_F(8): ev->data.key.ch = CACA_KEY_F8; break;
529        case KEY_F(9): ev->data.key.ch = CACA_KEY_F9; break;
530        case KEY_F(10): ev->data.key.ch = CACA_KEY_F10; break;
531        case KEY_F(11): ev->data.key.ch = CACA_KEY_F11; break;
532        case KEY_F(12): ev->data.key.ch = CACA_KEY_F12; break;
533
534        default:
535            /* Unknown key */
536            ev->type = CACA_EVENT_NONE; return 0;
537    }
538
539    ev->type = CACA_EVENT_KEY_PRESS;
540    ev->data.key.utf32 = 0;
541    ev->data.key.utf8[0] = '\0';
542    return 1;
543}
544
545static void ncurses_set_cursor(caca_display_t *dp, int flags)
546{
547    curs_set(flags ? 2 : 0);
548}
549
550/*
551 * XXX: following functions are local
552 */
553
554#if defined HAVE_SIGNAL
555static RETSIGTYPE sigwinch_handler(int sig)
556{
557    sigwinch_d->resize.resized = 1;
558
559    signal(SIGWINCH, sigwinch_handler);
560}
561#endif
562
563#if defined HAVE_GETENV && defined HAVE_PUTENV
564static void ncurses_check_terminal(void)
565{
566    char *term, *colorterm;
567
568    term = getenv("TERM");
569    colorterm = getenv("COLORTERM");
570
571    if(!term || strcmp(term, "xterm"))
572        return;
573
574    /* If we are using gnome-terminal, it's really a 16 colour terminal.
575     * Ditto if we are using xfce4-terminal, or Konsole. */
576    if((colorterm && (!strcmp(colorterm, "gnome-terminal")
577                       || !strcmp(colorterm, "Terminal")))
578         || getenv("KONSOLE_DCOP_SESSION"))
579    {
580        SCREEN *screen;
581        screen = newterm("xterm-16color", stdout, stdin);
582        if(screen == NULL)
583            return;
584        endwin();
585        (void)putenv("TERM=xterm-16color");
586        return;
587    }
588}
589#endif
590
591static void ncurses_write_utf32(uint32_t ch)
592{
593#if defined HAVE_NCURSESW_NCURSES_H
594    char buf[10];
595    int bytes;
596#endif
597
598    if(ch == CUCUL_MAGIC_FULLWIDTH)
599        return;
600
601#if defined HAVE_NCURSESW_NCURSES_H
602    bytes = cucul_utf32_to_utf8(buf, ch);
603    buf[bytes] = '\0';
604    addstr(buf);
605#else
606    if(ch < 0x80)
607    {
608        addch(ch);
609    }
610    else
611    {
612        chtype cch;
613        chtype cch2;
614
615        cch = '?';
616        cch2 = ' ';
617        if ((ch > 0x0000ff00) && (ch < 0x0000ff5f))
618        {
619            cch = ch - 0x0000ff00 + ' ';
620        }
621        switch (ch)
622        {
623        case 0x000000a0: /* <nbsp> */
624        case 0x00003000: /*   */
625            cch = ' ';
626            break;
627        case 0x000000a3: /* £ */
628            cch = ACS_STERLING;
629            break;
630        case 0x000000b0: /* ° */
631            cch = ACS_DEGREE;
632            break;
633        case 0x000000b1: /* ± */
634            cch = ACS_PLMINUS;
635            break;
636        case 0x000000b7: /* · */
637        case 0x00002219: /* ∙ */
638        case 0x000030fb: /* ・ */
639            cch = ACS_BULLET;
640            break;
641        case 0x000003c0: /* π */
642            cch = ACS_PI;
643            break;
644        case 0x00002018: /* ‘ */
645        case 0x00002019: /* ’ */
646            cch = '\'';
647            break;
648        case 0x0000201c: /* “ */
649        case 0x0000201d: /* ” */
650            cch = '"';
651            break;
652        case 0x00002190: /* ← */
653            cch = ACS_LARROW;
654            break;
655        case 0x00002191: /* ↑ */
656            cch = ACS_UARROW;
657            break;
658        case 0x00002192: /* → */
659            cch = ACS_RARROW;
660            break;
661        case 0x00002193: /* ↓ */
662            cch = ACS_DARROW;
663            break;
664        case 0x00002260: /* ≠ */
665            cch = ACS_NEQUAL;
666            break;
667        case 0x00002261: /* ≡ */
668            cch = '=';
669            break;
670        case 0x00002264: /* ≤ */
671            cch = ACS_LEQUAL;
672            break;
673        case 0x00002265: /* ≥ */
674            cch = ACS_GEQUAL;
675            break;
676        case 0x000023ba: /* ⎺ */
677            cch = ACS_S1;
678            cch2 = cch;
679            break;
680        case 0x000023bb: /* ⎻ */
681            cch = ACS_S3;
682            cch2 = cch;
683            break;
684        case 0x000023bc: /* ⎼ */
685            cch = ACS_S7;
686            cch2 = cch;
687            break;
688        case 0x000023bd: /* ⎽ */
689            cch = ACS_S9;
690            cch2 = cch;
691            break;
692        case 0x00002500: /* ─ */
693        case 0x00002550: /* ═ */
694            cch = ACS_HLINE;
695            cch2 = cch;
696            break;
697        case 0x00002502: /* │ */
698        case 0x00002551: /* ║ */
699            cch = ACS_VLINE;
700            break;
701        case 0x0000250c: /* ┌ */
702        case 0x00002552: /* ╒ */
703        case 0x00002553: /* ╓ */
704        case 0x00002554: /* ╔ */
705            cch = ACS_ULCORNER;
706            cch2 = ACS_HLINE;
707            break;
708        case 0x00002510: /* ┐ */
709        case 0x00002555: /* ╕ */
710        case 0x00002556: /* ╖ */
711        case 0x00002557: /* ╗ */
712            cch = ACS_URCORNER;
713            break;
714        case 0x00002514: /* └ */
715        case 0x00002558: /* ╘ */
716        case 0x00002559: /* ╙ */
717        case 0x0000255a: /* ╚ */
718            cch = ACS_LLCORNER;
719            cch2 = ACS_HLINE;
720            break;
721        case 0x00002518: /* ┘ */
722        case 0x0000255b: /* ╛ */
723        case 0x0000255c: /* ╜ */
724        case 0x0000255d: /* ╝ */
725            cch = ACS_LRCORNER;
726            break;
727        case 0x0000251c: /* ├ */
728        case 0x0000255e: /* ╞ */
729        case 0x0000255f: /* ╟ */
730        case 0x00002560: /* ╠ */
731            cch = ACS_LTEE;
732            cch2 = ACS_HLINE;
733            break;
734        case 0x00002524: /* ┤ */
735        case 0x00002561: /* ╡ */
736        case 0x00002562: /* ╢ */
737        case 0x00002563: /* ╣ */
738            cch = ACS_RTEE;
739            break;
740        case 0x0000252c: /* ┬ */
741        case 0x00002564: /* ╤ */
742        case 0x00002565: /* ╥ */
743        case 0x00002566: /* ╦ */
744            cch = ACS_TTEE;
745            cch2 = ACS_HLINE;
746            break;
747        case 0x00002534: /* ┴ */
748        case 0x00002567: /* ╧ */
749        case 0x00002568: /* ╨ */
750        case 0x00002569: /* ╩ */
751            cch = ACS_BTEE;
752            cch2 = ACS_HLINE;
753            break;
754        case 0x0000253c: /* ┼ */
755        case 0x0000256a: /* ╪ */
756        case 0x0000256b: /* ╫ */
757        case 0x0000256c: /* ╬ */
758            cch = ACS_PLUS;
759            cch2 = ACS_HLINE;
760            break;
761        case 0x00002591: /* ░ */
762            cch = ACS_BOARD;
763            cch2 = cch;
764            break;
765        case 0x00002592: /* ▒ */
766        case 0x00002593: /* ▓ */
767            cch = ACS_CKBOARD;
768            cch2 = cch;
769            break;
770        case 0x00002580: /* ▀ */
771        case 0x00002584: /* ▄ */
772        case 0x00002588: /* █ */
773        case 0x0000258c: /* ▌ */
774        case 0x00002590: /* ▐ */
775        case 0x000025a0: /* ■ */
776        case 0x000025ac: /* ▬ */
777        case 0x000025ae: /* ▮ */
778            cch = ACS_BLOCK;
779            cch2 = cch;
780            break;
781        case 0x000025c6: /* ◆ */
782        case 0x00002666: /* ♦ */
783            cch = ACS_DIAMOND;
784            break;
785        case 0x00002022: /* • */
786        case 0x000025cb: /* ○ */
787        case 0x000025cf: /* ● */
788        case 0x00002603: /* ☃ */
789        case 0x0000263c: /* ☼ */
790            cch = ACS_LANTERN;
791            break;
792        case 0x0000301c: /* 〜 */
793            cch = '~';
794            break;
795        }
796        addch(cch);
797        if(cucul_utf32_is_fullwidth(ch))
798        {
799            addch(cch2);
800        }
801    }
802#endif
803}
804
805/*
806 * Driver initialisation
807 */
808
809int ncurses_install(caca_display_t *dp)
810{
811    dp->drv.driver = CACA_DRIVER_NCURSES;
812
813    dp->drv.init_graphics = ncurses_init_graphics;
814    dp->drv.end_graphics = ncurses_end_graphics;
815    dp->drv.set_display_title = ncurses_set_display_title;
816    dp->drv.get_display_width = ncurses_get_display_width;
817    dp->drv.get_display_height = ncurses_get_display_height;
818    dp->drv.display = ncurses_display;
819    dp->drv.handle_resize = ncurses_handle_resize;
820    dp->drv.get_event = ncurses_get_event;
821    dp->drv.set_mouse = NULL;
822    dp->drv.set_cursor = ncurses_set_cursor;
823
824    return 0;
825}
826
827#endif /* USE_NCURSES */
828
Note: See TracBrowser for help on using the repository browser.