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

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

Starting refactoring to get rid of libcucul. The initial reason for the
split is rendered moot by the plugin system: when enabled, binaries do
not link directly with libX11 or libGL. I hope this is a step towards
more consisteny and clarity.

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