source: libcaca/trunk/caca/driver/ncurses.c @ 4369

Last change on this file since 4369 was 4369, checked in by Sam Hocevar, 11 years ago

Add the copyright unit test and update copyright information everywhere.

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