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

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

Rename caca_get_cursor_x() and caca_get_cursor_y() to caca_wherex() and
caca_wherey(), in order to match the old <conio.h> naming scheme.

  • Property svn:keywords set to Id
File size: 21.2 KB
Line 
1/*
2 *  libcaca       Colour ASCII-Art library
3 *  Copyright (c) 2002-2009 Sam Hocevar <sam@hocevar.net>
4 *                2007 Ben Wiley Sittler <bsittler@gmail.com>
5 *                All Rights Reserved
6 *
7 *  $Id: ncurses.c 3587 2009-07-26 23:26:15Z 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    caca_add_dirty_rect(dp->cv, 0, 0, dp->cv->width, dp->cv->height);
304    dp->resize.allow = 1;
305    caca_set_canvas_size(dp->cv, COLS, LINES);
306    dp->resize.allow = 0;
307
308    return 0;
309}
310
311static int ncurses_end_graphics(caca_display_t *dp)
312{
313    _caca_set_term_title("");
314    mousemask(dp->drv.p->oldmask, NULL);
315    curs_set(1);
316    noraw();
317    endwin();
318
319#if defined HAVE_GETENV && defined HAVE_PUTENV
320    ncurses_uninstall_terminal(dp);
321#endif
322
323    free(dp->drv.p);
324
325    return 0;
326}
327
328static int ncurses_set_display_title(caca_display_t *dp, char const *title)
329{
330    _caca_set_term_title(title);
331
332    return 0;
333}
334
335static int ncurses_get_display_width(caca_display_t const *dp)
336{
337    /* Fallback to a 6x10 font */
338    return caca_get_canvas_width(dp->cv) * 6;
339}
340
341static int ncurses_get_display_height(caca_display_t const *dp)
342{
343    /* Fallback to a 6x10 font */
344    return caca_get_canvas_height(dp->cv) * 10;
345}
346
347static void ncurses_display(caca_display_t *dp)
348{
349    int x, y, i;
350
351    for(i = 0; i < caca_get_dirty_rect_count(dp->cv); i++)
352    {
353        uint32_t const *cvchars, *cvattrs;
354        int dx, dy, dw, dh;
355
356        caca_get_dirty_rect(dp->cv, i, &dx, &dy, &dw, &dh);
357
358        cvchars = (uint32_t const *)caca_get_canvas_chars(dp->cv)
359                    + dx + dy * dp->cv->width;
360        cvattrs = (uint32_t const *)caca_get_canvas_attrs(dp->cv)
361                    + dx + dy * dp->cv->width;
362
363        for(y = dy; y < dy + dh; y++)
364        {
365            move(y, dx);
366            for(x = dx; x < dx + dw; x++)
367            {
368                /* FIXME: this emits a "value computed is unused" warning */
369                attrset(dp->drv.p->attr[caca_attr_to_ansi(*cvattrs++)]);
370                ncurses_write_utf32(*cvchars++);
371            }
372
373            cvchars += dp->cv->width - dw;
374            cvattrs += dp->cv->width - dw;
375        }
376    }
377
378    x = caca_wherex(dp->cv);
379    y = caca_wherey(dp->cv);
380    move(y, x);
381
382    refresh();
383}
384
385static void ncurses_handle_resize(caca_display_t *dp)
386{
387    struct winsize size;
388
389#if defined HAVE_SYS_IOCTL_H
390    if(ioctl(fileno(stdout), TIOCGWINSZ, &size) == 0)
391    {
392        dp->resize.w = size.ws_col;
393        dp->resize.h = size.ws_row;
394#if defined HAVE_RESIZE_TERM
395        resize_term(dp->resize.h, dp->resize.w);
396#else
397        resizeterm(dp->resize.h, dp->resize.w);
398#endif
399        wrefresh(curscr);
400        return;
401    }
402#endif
403
404    /* Fallback */
405    dp->resize.w = caca_get_canvas_width(dp->cv);
406    dp->resize.h = caca_get_canvas_height(dp->cv);
407}
408
409static int ncurses_get_event(caca_display_t *dp, caca_privevent_t *ev)
410{
411    int intkey;
412
413    intkey = getch();
414    if(intkey == ERR)
415    {
416        ev->type = CACA_EVENT_NONE;
417        return 0;
418    }
419
420    if(intkey < 0x7f)
421    {
422        ev->type = CACA_EVENT_KEY_PRESS;
423        ev->data.key.ch = intkey;
424        ev->data.key.utf32 = intkey;
425        ev->data.key.utf8[0] = intkey;
426        ev->data.key.utf8[1] = '\0';
427        return 1;
428    }
429
430    /* If the key was UTF-8, parse the whole sequence */
431    if(intkey >= 0x80 && intkey < 0x100)
432    {
433        int keys[7]; /* Necessary for ungetch(); */
434        char utf8[7];
435        uint32_t utf32;
436        size_t i, bytes = 0;
437
438        keys[0] = intkey;
439        utf8[0] = intkey;
440
441        for(i = 1; i < 6; i++)
442        {
443            keys[i] = getch();
444            utf8[i] = (unsigned char)keys[i];
445        }
446
447        utf8[i] = '\0';
448        utf32 = caca_utf8_to_utf32(utf8, &bytes);
449
450        while(i > bytes)
451            ungetch(keys[--i]);
452
453        if(bytes)
454        {
455            ev->type = CACA_EVENT_KEY_PRESS;
456            ev->data.key.ch = 0;
457            ev->data.key.utf32 = utf32;
458            strcpy(ev->data.key.utf8, utf8);
459            return 1;
460        }
461    }
462
463    if(intkey == KEY_MOUSE)
464    {
465        MEVENT mevent;
466        getmouse(&mevent);
467
468        switch(mevent.bstate)
469        {
470#define PRESS(x) ev->data.mouse.button = x; \
471                 ev->type = CACA_EVENT_MOUSE_PRESS; _push_event(dp, ev)
472#define RELEASE(x) ev->data.mouse.button = x; \
473                   ev->type = CACA_EVENT_MOUSE_RELEASE; _push_event(dp, ev)
474#define CLICK(x) PRESS(x); RELEASE(x)
475            case BUTTON1_PRESSED: PRESS(1); break;
476            case BUTTON1_RELEASED: RELEASE(1); break;
477            case BUTTON1_CLICKED: CLICK(1); break;
478            case BUTTON1_DOUBLE_CLICKED: CLICK(1); CLICK(1); break;
479            case BUTTON1_TRIPLE_CLICKED: CLICK(1); CLICK(1); CLICK(1); break;
480            case BUTTON1_RESERVED_EVENT: break;
481
482            case BUTTON2_PRESSED: PRESS(2); break;
483            case BUTTON2_RELEASED: RELEASE(2); break;
484            case BUTTON2_CLICKED: CLICK(2); break;
485            case BUTTON2_DOUBLE_CLICKED: CLICK(2); CLICK(2); break;
486            case BUTTON2_TRIPLE_CLICKED: CLICK(2); CLICK(2); CLICK(2); break;
487            case BUTTON2_RESERVED_EVENT: break;
488
489            case BUTTON3_PRESSED: PRESS(3); break;
490            case BUTTON3_RELEASED: RELEASE(3); break;
491            case BUTTON3_CLICKED: CLICK(3); break;
492            case BUTTON3_DOUBLE_CLICKED: CLICK(3); CLICK(3); break;
493            case BUTTON3_TRIPLE_CLICKED: CLICK(3); CLICK(3); CLICK(3); break;
494            case BUTTON3_RESERVED_EVENT: break;
495
496            case BUTTON4_PRESSED: PRESS(4); break;
497            case BUTTON4_RELEASED: RELEASE(4); break;
498            case BUTTON4_CLICKED: CLICK(4); break;
499            case BUTTON4_DOUBLE_CLICKED: CLICK(4); CLICK(4); break;
500            case BUTTON4_TRIPLE_CLICKED: CLICK(4); CLICK(4); CLICK(4); break;
501            case BUTTON4_RESERVED_EVENT: break;
502
503            default:
504                break;
505#undef PRESS
506#undef RELEASE
507#undef CLICK
508        }
509
510        if(dp->mouse.x == mevent.x && dp->mouse.y == mevent.y)
511            return _pop_event(dp, ev);
512
513        dp->mouse.x = mevent.x;
514        dp->mouse.y = mevent.y;
515
516        ev->type = CACA_EVENT_MOUSE_MOTION;
517        ev->data.mouse.x = dp->mouse.x;
518        ev->data.mouse.y = dp->mouse.y;
519        return 1;
520    }
521
522    switch(intkey)
523    {
524        case KEY_UP: ev->data.key.ch = CACA_KEY_UP; break;
525        case KEY_DOWN: ev->data.key.ch = CACA_KEY_DOWN; break;
526        case KEY_LEFT: ev->data.key.ch = CACA_KEY_LEFT; break;
527        case KEY_RIGHT: ev->data.key.ch = CACA_KEY_RIGHT; break;
528
529        case KEY_IC: ev->data.key.ch = CACA_KEY_INSERT; break;
530        case KEY_DC: ev->data.key.ch = CACA_KEY_DELETE; break;
531        case 0x7f:
532        case KEY_BACKSPACE: ev->data.key.ch = CACA_KEY_BACKSPACE; break;
533        case KEY_HOME: ev->data.key.ch = CACA_KEY_HOME; break;
534        case KEY_END: ev->data.key.ch = CACA_KEY_END; break;
535        case KEY_PPAGE: ev->data.key.ch = CACA_KEY_PAGEUP; break;
536        case KEY_NPAGE: ev->data.key.ch = CACA_KEY_PAGEDOWN; break;
537
538        case KEY_F(1): ev->data.key.ch = CACA_KEY_F1; break;
539        case KEY_F(2): ev->data.key.ch = CACA_KEY_F2; break;
540        case KEY_F(3): ev->data.key.ch = CACA_KEY_F3; break;
541        case KEY_F(4): ev->data.key.ch = CACA_KEY_F4; break;
542        case KEY_F(5): ev->data.key.ch = CACA_KEY_F5; break;
543        case KEY_F(6): ev->data.key.ch = CACA_KEY_F6; break;
544        case KEY_F(7): ev->data.key.ch = CACA_KEY_F7; break;
545        case KEY_F(8): ev->data.key.ch = CACA_KEY_F8; break;
546        case KEY_F(9): ev->data.key.ch = CACA_KEY_F9; break;
547        case KEY_F(10): ev->data.key.ch = CACA_KEY_F10; break;
548        case KEY_F(11): ev->data.key.ch = CACA_KEY_F11; break;
549        case KEY_F(12): ev->data.key.ch = CACA_KEY_F12; break;
550
551        default:
552            /* Unknown key */
553            ev->type = CACA_EVENT_NONE; return 0;
554    }
555
556    ev->type = CACA_EVENT_KEY_PRESS;
557    ev->data.key.utf32 = 0;
558    ev->data.key.utf8[0] = '\0';
559    return 1;
560}
561
562static void ncurses_set_cursor(caca_display_t *dp, int flags)
563{
564    curs_set(flags ? 2 : 0);
565}
566
567/*
568 * XXX: following functions are local
569 */
570
571#if defined HAVE_SIGNAL
572static RETSIGTYPE sigwinch_handler(int sig)
573{
574    sigwinch_d->resize.resized = 1;
575
576    signal(SIGWINCH, sigwinch_handler);
577}
578#endif
579
580#if defined HAVE_GETENV && defined HAVE_PUTENV
581static void ncurses_install_terminal(caca_display_t *dp)
582{
583    char *term, *colorterm;
584
585    dp->drv.p->term = NULL;
586
587    term = getenv("TERM");
588    colorterm = getenv("COLORTERM");
589
590    if(!term || strcmp(term, "xterm"))
591        return;
592
593    /* If we are using gnome-terminal, it's really a 16 colour terminal.
594     * Ditto if we are using xfce4-terminal, or Konsole. */
595    if((colorterm && (!strcmp(colorterm, "gnome-terminal")
596                       || !strcmp(colorterm, "Terminal")))
597         || getenv("KONSOLE_DCOP_SESSION"))
598    {
599        SCREEN *screen;
600        screen = newterm("xterm-16color", stdout, stdin);
601        if(screen == NULL)
602            return;
603        endwin();
604        (void)putenv("TERM=xterm-16color");
605        dp->drv.p->term = strdup(term);
606        return;
607    }
608}
609
610static void ncurses_uninstall_terminal(caca_display_t *dp)
611{
612    /* Needs to be persistent because we use putenv() */
613    static char termenv[1024];
614
615    if(!dp->drv.p->term)
616        return;
617
618    snprintf(termenv, 1023, "TERM=%s", dp->drv.p->term);
619    free(dp->drv.p->term);
620    (void)putenv(termenv);
621}
622#endif
623
624static void ncurses_write_utf32(uint32_t ch)
625{
626#if defined HAVE_NCURSESW_NCURSES_H
627    char buf[10];
628    int bytes;
629#endif
630
631    if(ch == CACA_MAGIC_FULLWIDTH)
632        return;
633
634#if defined HAVE_NCURSESW_NCURSES_H
635    bytes = caca_utf32_to_utf8(buf, ch);
636    buf[bytes] = '\0';
637    addstr(buf);
638#else
639    if(ch < 0x80)
640    {
641        addch(ch);
642    }
643    else
644    {
645        chtype cch;
646        chtype cch2;
647
648        cch = '?';
649        cch2 = ' ';
650        if ((ch > 0x0000ff00) && (ch < 0x0000ff5f))
651        {
652            cch = ch - 0x0000ff00 + ' ';
653        }
654        switch (ch)
655        {
656        case 0x000000a0: /* <nbsp> */
657        case 0x00003000: /*   */
658            cch = ' ';
659            break;
660        case 0x000000a3: /* £ */
661            cch = ACS_STERLING;
662            break;
663        case 0x000000b0: /* ° */
664            cch = ACS_DEGREE;
665            break;
666        case 0x000000b1: /* ± */
667            cch = ACS_PLMINUS;
668            break;
669        case 0x000000b7: /* · */
670        case 0x00002219: /* ∙ */
671        case 0x000030fb: /* ・ */
672            cch = ACS_BULLET;
673            break;
674        case 0x000003c0: /* π */
675            cch = ACS_PI;
676            break;
677        case 0x00002018: /* ‘ */
678        case 0x00002019: /* ’ */
679            cch = '\'';
680            break;
681        case 0x0000201c: /* “ */
682        case 0x0000201d: /* ” */
683            cch = '"';
684            break;
685        case 0x00002190: /* ← */
686            cch = ACS_LARROW;
687            break;
688        case 0x00002191: /* ↑ */
689            cch = ACS_UARROW;
690            break;
691        case 0x00002192: /* → */
692            cch = ACS_RARROW;
693            break;
694        case 0x00002193: /* ↓ */
695            cch = ACS_DARROW;
696            break;
697        case 0x00002260: /* ≠ */
698            cch = ACS_NEQUAL;
699            break;
700        case 0x00002261: /* ≡ */
701            cch = '=';
702            break;
703        case 0x00002264: /* ≤ */
704            cch = ACS_LEQUAL;
705            break;
706        case 0x00002265: /* ≥ */
707            cch = ACS_GEQUAL;
708            break;
709        case 0x000023ba: /* ⎺ */
710            cch = ACS_S1;
711            cch2 = cch;
712            break;
713        case 0x000023bb: /* ⎻ */
714            cch = ACS_S3;
715            cch2 = cch;
716            break;
717        case 0x000023bc: /* ⎼ */
718            cch = ACS_S7;
719            cch2 = cch;
720            break;
721        case 0x000023bd: /* ⎽ */
722            cch = ACS_S9;
723            cch2 = cch;
724            break;
725        case 0x00002500: /* ─ */
726        case 0x00002550: /* ═ */
727            cch = ACS_HLINE;
728            cch2 = cch;
729            break;
730        case 0x00002502: /* │ */
731        case 0x00002551: /* ║ */
732            cch = ACS_VLINE;
733            break;
734        case 0x0000250c: /* ┌ */
735        case 0x00002552: /* ╒ */
736        case 0x00002553: /* ╓ */
737        case 0x00002554: /* ╔ */
738            cch = ACS_ULCORNER;
739            cch2 = ACS_HLINE;
740            break;
741        case 0x00002510: /* ┐ */
742        case 0x00002555: /* ╕ */
743        case 0x00002556: /* ╖ */
744        case 0x00002557: /* ╗ */
745            cch = ACS_URCORNER;
746            break;
747        case 0x00002514: /* └ */
748        case 0x00002558: /* ╘ */
749        case 0x00002559: /* ╙ */
750        case 0x0000255a: /* ╚ */
751            cch = ACS_LLCORNER;
752            cch2 = ACS_HLINE;
753            break;
754        case 0x00002518: /* ┘ */
755        case 0x0000255b: /* ╛ */
756        case 0x0000255c: /* ╜ */
757        case 0x0000255d: /* ╝ */
758            cch = ACS_LRCORNER;
759            break;
760        case 0x0000251c: /* ├ */
761        case 0x0000255e: /* ╞ */
762        case 0x0000255f: /* ╟ */
763        case 0x00002560: /* ╠ */
764            cch = ACS_LTEE;
765            cch2 = ACS_HLINE;
766            break;
767        case 0x00002524: /* ┤ */
768        case 0x00002561: /* ╡ */
769        case 0x00002562: /* ╢ */
770        case 0x00002563: /* ╣ */
771            cch = ACS_RTEE;
772            break;
773        case 0x0000252c: /* ┬ */
774        case 0x00002564: /* ╤ */
775        case 0x00002565: /* ╥ */
776        case 0x00002566: /* ╦ */
777            cch = ACS_TTEE;
778            cch2 = ACS_HLINE;
779            break;
780        case 0x00002534: /* ┴ */
781        case 0x00002567: /* ╧ */
782        case 0x00002568: /* ╨ */
783        case 0x00002569: /* ╩ */
784            cch = ACS_BTEE;
785            cch2 = ACS_HLINE;
786            break;
787        case 0x0000253c: /* ┼ */
788        case 0x0000256a: /* ╪ */
789        case 0x0000256b: /* ╫ */
790        case 0x0000256c: /* ╬ */
791            cch = ACS_PLUS;
792            cch2 = ACS_HLINE;
793            break;
794        case 0x00002591: /* ░ */
795            cch = ACS_BOARD;
796            cch2 = cch;
797            break;
798        case 0x00002592: /* ▒ */
799        case 0x00002593: /* ▓ */
800            cch = ACS_CKBOARD;
801            cch2 = cch;
802            break;
803        case 0x00002580: /* ▀ */
804        case 0x00002584: /* ▄ */
805        case 0x00002588: /* █ */
806        case 0x0000258c: /* ▌ */
807        case 0x00002590: /* ▐ */
808        case 0x000025a0: /* ■ */
809        case 0x000025ac: /* ▬ */
810        case 0x000025ae: /* ▮ */
811            cch = ACS_BLOCK;
812            cch2 = cch;
813            break;
814        case 0x000025c6: /* ◆ */
815        case 0x00002666: /* ♦ */
816            cch = ACS_DIAMOND;
817            break;
818        case 0x00002022: /* • */
819        case 0x000025cb: /* ○ */
820        case 0x000025cf: /* ● */
821        case 0x00002603: /* ☃ */
822        case 0x0000263c: /* ☼ */
823            cch = ACS_LANTERN;
824            break;
825        case 0x0000301c: /* 〜 */
826            cch = '~';
827            break;
828        }
829        addch(cch);
830        if(caca_utf32_is_fullwidth(ch))
831        {
832            addch(cch2);
833        }
834    }
835#endif
836}
837
838/*
839 * Driver initialisation
840 */
841
842int ncurses_install(caca_display_t *dp)
843{
844    dp->drv.id = CACA_DRIVER_NCURSES;
845    dp->drv.driver = "ncurses";
846
847    dp->drv.init_graphics = ncurses_init_graphics;
848    dp->drv.end_graphics = ncurses_end_graphics;
849    dp->drv.set_display_title = ncurses_set_display_title;
850    dp->drv.get_display_width = ncurses_get_display_width;
851    dp->drv.get_display_height = ncurses_get_display_height;
852    dp->drv.display = ncurses_display;
853    dp->drv.handle_resize = ncurses_handle_resize;
854    dp->drv.get_event = ncurses_get_event;
855    dp->drv.set_mouse = NULL;
856    dp->drv.set_cursor = ncurses_set_cursor;
857
858    return 0;
859}
860
861#endif /* USE_NCURSES */
862
Note: See TracBrowser for help on using the repository browser.