"Fossies" - the Fresh Open Source Software Archive 
Member "libcaca-0.99.beta20/caca/driver/ncurses.c" (19 Oct 2021, 22270 Bytes) of package /linux/privat/libcaca-0.99.beta20.tar.bz2:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /*
2 * libcaca Colour ASCII-Art library
3 * Copyright © 2002—2021 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://www.wtfpl.net/ 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
191 static void sigwinch_handler(int);
192 static caca_display_t *sigwinch_d; /* FIXME: we ought to get rid of this */
193 #endif
194 #if defined HAVE_GETENV && defined HAVE_PUTENV
195 static void ncurses_install_terminal(caca_display_t *);
196 static void ncurses_uninstall_terminal(caca_display_t *);
197 #endif
198 static void ncurses_write_utf32(uint32_t);
199
200 struct driver_private
201 {
202 int attr[16*16];
203 mmask_t oldmask;
204 char *term;
205 };
206
207 static 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 #if defined HAVE_LOCALE_H
232 char const *old_locale;
233 #endif
234 mmask_t newmask;
235 int fg, bg, max;
236
237 dp->drv.p = malloc(sizeof(struct driver_private));
238
239 #if defined HAVE_GETENV && defined HAVE_PUTENV
240 ncurses_install_terminal(dp);
241 #endif
242
243 #if defined HAVE_SIGNAL
244 sigwinch_d = dp;
245 signal(SIGWINCH, sigwinch_handler);
246 #endif
247
248 _caca_set_term_title("caca for ncurses");
249
250 #if defined HAVE_LOCALE_H
251 old_locale = setlocale(LC_CTYPE, "");
252 #endif
253 initscr();
254 #if defined HAVE_LOCALE_H
255 setlocale(LC_CTYPE, old_locale);
256 #endif
257
258 keypad(stdscr, TRUE);
259 nonl();
260 raw();
261 noecho();
262 nodelay(stdscr, TRUE);
263 curs_set(0);
264
265 /* Activate mouse */
266 newmask = REPORT_MOUSE_POSITION | ALL_MOUSE_EVENTS;
267 mousemask(newmask, &dp->drv.p->oldmask);
268 mouseinterval(-1); /* No click emulation */
269
270 /* Set the escape delay to a ridiculously low value */
271 #if defined set_escdelay
272 set_escdelay(10);
273 #else
274 ESCDELAY = 10;
275 #endif
276
277 /* Activate colour */
278 start_color();
279
280 /* If COLORS == 16, it means the terminal supports full bright colours
281 * using setab and setaf (will use \e[90m \e[91m etc. for colours >= 8),
282 * we can build 16*16 colour pairs.
283 * If COLORS == 8, it means the terminal does not know about bright
284 * colours and we need to get them through A_BOLD and A_BLINK (\e[1m
285 * and \e[5m). We can only build 8*8 colour pairs. */
286 max = COLORS >= 16 ? 16 : 8;
287
288 for(bg = 0; bg < max; bg++)
289 for(fg = 0; fg < max; fg++)
290 {
291 /* Use ((max + 7 - fg) % max) instead of fg so that colour 0
292 * is light gray on black. Some terminals don't like this
293 * colour pair to be redefined. */
294 int col = ((max + 7 - fg) % max) + max * bg;
295 init_pair(col, curses_colors[fg], curses_colors[bg]);
296 dp->drv.p->attr[fg + 16 * bg] = COLOR_PAIR(col);
297
298 if(max == 8)
299 {
300 /* Bright fg on simple bg */
301 dp->drv.p->attr[fg + 8 + 16 * bg] = A_BOLD | COLOR_PAIR(col);
302 /* Simple fg on bright bg */
303 dp->drv.p->attr[fg + 16 * (bg + 8)] = A_BLINK
304 | COLOR_PAIR(col);
305 /* Bright fg on bright bg */
306 dp->drv.p->attr[fg + 8 + 16 * (bg + 8)] = A_BLINK | A_BOLD
307 | COLOR_PAIR(col);
308 }
309 }
310
311 caca_add_dirty_rect(dp->cv, 0, 0, dp->cv->width, dp->cv->height);
312 dp->resize.allow = 1;
313 caca_set_canvas_size(dp->cv, COLS, LINES);
314 dp->resize.allow = 0;
315
316 return 0;
317 }
318
319 static int ncurses_end_graphics(caca_display_t *dp)
320 {
321 _caca_set_term_title("");
322 mousemask(dp->drv.p->oldmask, NULL);
323 curs_set(1);
324 noraw();
325 endwin();
326
327 #if defined HAVE_GETENV && defined HAVE_PUTENV
328 ncurses_uninstall_terminal(dp);
329 #endif
330
331 free(dp->drv.p);
332
333 return 0;
334 }
335
336 static int ncurses_set_display_title(caca_display_t *dp, char const *title)
337 {
338 _caca_set_term_title(title);
339
340 return 0;
341 }
342
343 static int ncurses_get_display_width(caca_display_t const *dp)
344 {
345 /* Fallback to a 6x10 font */
346 return caca_get_canvas_width(dp->cv) * 6;
347 }
348
349 static int ncurses_get_display_height(caca_display_t const *dp)
350 {
351 /* Fallback to a 6x10 font */
352 return caca_get_canvas_height(dp->cv) * 10;
353 }
354
355 static void ncurses_display(caca_display_t *dp)
356 {
357 int x, y, i;
358
359 for(i = 0; i < caca_get_dirty_rect_count(dp->cv); i++)
360 {
361 uint32_t const *cvchars, *cvattrs;
362 int dx, dy, dw, dh;
363
364 caca_get_dirty_rect(dp->cv, i, &dx, &dy, &dw, &dh);
365
366 cvchars = caca_get_canvas_chars(dp->cv) + dx + dy * dp->cv->width;
367 cvattrs = caca_get_canvas_attrs(dp->cv) + dx + dy * dp->cv->width;
368
369 for(y = dy; y < dy + dh; y++)
370 {
371 move(y, dx);
372 for(x = dx; x < dx + dw; x++)
373 {
374 uint32_t attr = *cvattrs++;
375
376 (void)attrset(dp->drv.p->attr[caca_attr_to_ansi(attr)]);
377 if(attr & CACA_BOLD)
378 attron(A_BOLD);
379 if(attr & CACA_BLINK)
380 attron(A_BLINK);
381 if(attr & CACA_UNDERLINE)
382 attron(A_UNDERLINE);
383
384 ncurses_write_utf32(*cvchars++);
385 }
386
387 cvchars += dp->cv->width - dw;
388 cvattrs += dp->cv->width - dw;
389 }
390 }
391
392 x = caca_wherex(dp->cv);
393 y = caca_wherey(dp->cv);
394 move(y, x);
395
396 refresh();
397 }
398
399 static void ncurses_handle_resize(caca_display_t *dp)
400 {
401 struct winsize size;
402
403 #if defined HAVE_SYS_IOCTL_H
404 if(ioctl(fileno(stdout), TIOCGWINSZ, &size) == 0)
405 {
406 dp->resize.w = size.ws_col;
407 dp->resize.h = size.ws_row;
408 #if defined HAVE_RESIZE_TERM
409 resize_term(dp->resize.h, dp->resize.w);
410 #else
411 resizeterm(dp->resize.h, dp->resize.w);
412 #endif
413 wrefresh(curscr);
414 return;
415 }
416 #endif
417
418 /* Fallback */
419 dp->resize.w = caca_get_canvas_width(dp->cv);
420 dp->resize.h = caca_get_canvas_height(dp->cv);
421 }
422
423 static int ncurses_get_event(caca_display_t *dp, caca_privevent_t *ev)
424 {
425 int intkey;
426
427 intkey = getch();
428 if(intkey == ERR)
429 {
430 ev->type = CACA_EVENT_NONE;
431 return 0;
432 }
433
434 if(intkey < 0x7f)
435 {
436 ev->type = CACA_EVENT_KEY_PRESS;
437 ev->data.key.ch = intkey;
438 ev->data.key.utf32 = intkey;
439 ev->data.key.utf8[0] = intkey;
440 ev->data.key.utf8[1] = '\0';
441 return 1;
442 }
443
444 /* If the key was UTF-8, parse the whole sequence */
445 if(intkey >= 0x80 && intkey < 0x100)
446 {
447 int keys[7]; /* Necessary for ungetch(); */
448 char utf8[7];
449 uint32_t utf32;
450 size_t i, bytes = 0;
451
452 keys[0] = intkey;
453 utf8[0] = intkey;
454
455 for(i = 1; i < 6; i++)
456 {
457 keys[i] = getch();
458 utf8[i] = (unsigned char)keys[i];
459 }
460
461 utf8[i] = '\0';
462 utf32 = caca_utf8_to_utf32(utf8, &bytes);
463
464 while(i > bytes)
465 ungetch(keys[--i]);
466
467 if(bytes)
468 {
469 ev->type = CACA_EVENT_KEY_PRESS;
470 ev->data.key.ch = 0;
471 ev->data.key.utf32 = utf32;
472 strcpy(ev->data.key.utf8, utf8);
473 return 1;
474 }
475 }
476
477 if(intkey == KEY_MOUSE)
478 {
479 MEVENT mevent;
480 getmouse(&mevent);
481
482 switch(mevent.bstate)
483 {
484 #define PRESS(x) ev->data.mouse.button = x; \
485 ev->type = CACA_EVENT_MOUSE_PRESS; _push_event(dp, ev)
486 #define RELEASE(x) ev->data.mouse.button = x; \
487 ev->type = CACA_EVENT_MOUSE_RELEASE; _push_event(dp, ev)
488 #define CLICK(x) PRESS(x); RELEASE(x)
489 case BUTTON1_PRESSED: PRESS(1); break;
490 case BUTTON1_RELEASED: RELEASE(1); break;
491 case BUTTON1_CLICKED: CLICK(1); break;
492 case BUTTON1_DOUBLE_CLICKED: CLICK(1); CLICK(1); break;
493 case BUTTON1_TRIPLE_CLICKED: CLICK(1); CLICK(1); CLICK(1); break;
494 #if defined BUTTON1_RESERVED_EVENT
495 case BUTTON1_RESERVED_EVENT: break;
496 #endif
497
498 case BUTTON2_PRESSED: PRESS(2); break;
499 case BUTTON2_RELEASED: RELEASE(2); break;
500 case BUTTON2_CLICKED: CLICK(2); break;
501 case BUTTON2_DOUBLE_CLICKED: CLICK(2); CLICK(2); break;
502 case BUTTON2_TRIPLE_CLICKED: CLICK(2); CLICK(2); CLICK(2); break;
503 #if defined BUTTON2_RESERVED_EVENT
504 case BUTTON2_RESERVED_EVENT: break;
505 #endif
506
507 case BUTTON3_PRESSED: PRESS(3); break;
508 case BUTTON3_RELEASED: RELEASE(3); break;
509 case BUTTON3_CLICKED: CLICK(3); break;
510 case BUTTON3_DOUBLE_CLICKED: CLICK(3); CLICK(3); break;
511 case BUTTON3_TRIPLE_CLICKED: CLICK(3); CLICK(3); CLICK(3); break;
512 #if defined BUTTON3_RESERVED_EVENT
513 case BUTTON3_RESERVED_EVENT: break;
514 #endif
515
516 case BUTTON4_PRESSED: PRESS(4); break;
517 case BUTTON4_RELEASED: RELEASE(4); break;
518 case BUTTON4_CLICKED: CLICK(4); break;
519 case BUTTON4_DOUBLE_CLICKED: CLICK(4); CLICK(4); break;
520 case BUTTON4_TRIPLE_CLICKED: CLICK(4); CLICK(4); CLICK(4); break;
521 #if defined BUTTON4_RESERVED_EVENT
522 case BUTTON4_RESERVED_EVENT: break;
523 #endif
524
525 default:
526 break;
527 #undef PRESS
528 #undef RELEASE
529 #undef CLICK
530 }
531
532 if(dp->mouse.x == mevent.x && dp->mouse.y == mevent.y)
533 return _pop_event(dp, ev);
534
535 dp->mouse.x = mevent.x;
536 dp->mouse.y = mevent.y;
537
538 ev->type = CACA_EVENT_MOUSE_MOTION;
539 ev->data.mouse.x = dp->mouse.x;
540 ev->data.mouse.y = dp->mouse.y;
541 return 1;
542 }
543
544 switch(intkey)
545 {
546 case KEY_UP: ev->data.key.ch = CACA_KEY_UP; break;
547 case KEY_DOWN: ev->data.key.ch = CACA_KEY_DOWN; break;
548 case KEY_LEFT: ev->data.key.ch = CACA_KEY_LEFT; break;
549 case KEY_RIGHT: ev->data.key.ch = CACA_KEY_RIGHT; break;
550
551 case KEY_IC: ev->data.key.ch = CACA_KEY_INSERT; break;
552 case KEY_DC: ev->data.key.ch = CACA_KEY_DELETE; break;
553 case 0x7f:
554 case KEY_BACKSPACE: ev->data.key.ch = CACA_KEY_BACKSPACE; break;
555 case KEY_HOME: ev->data.key.ch = CACA_KEY_HOME; break;
556 case KEY_END: ev->data.key.ch = CACA_KEY_END; break;
557 case KEY_PPAGE: ev->data.key.ch = CACA_KEY_PAGEUP; break;
558 case KEY_NPAGE: ev->data.key.ch = CACA_KEY_PAGEDOWN; break;
559
560 case KEY_F(1): ev->data.key.ch = CACA_KEY_F1; break;
561 case KEY_F(2): ev->data.key.ch = CACA_KEY_F2; break;
562 case KEY_F(3): ev->data.key.ch = CACA_KEY_F3; break;
563 case KEY_F(4): ev->data.key.ch = CACA_KEY_F4; break;
564 case KEY_F(5): ev->data.key.ch = CACA_KEY_F5; break;
565 case KEY_F(6): ev->data.key.ch = CACA_KEY_F6; break;
566 case KEY_F(7): ev->data.key.ch = CACA_KEY_F7; break;
567 case KEY_F(8): ev->data.key.ch = CACA_KEY_F8; break;
568 case KEY_F(9): ev->data.key.ch = CACA_KEY_F9; break;
569 case KEY_F(10): ev->data.key.ch = CACA_KEY_F10; break;
570 case KEY_F(11): ev->data.key.ch = CACA_KEY_F11; break;
571 case KEY_F(12): ev->data.key.ch = CACA_KEY_F12; break;
572
573 default:
574 /* Unknown key */
575 ev->type = CACA_EVENT_NONE; return 0;
576 }
577
578 ev->type = CACA_EVENT_KEY_PRESS;
579 ev->data.key.utf32 = 0;
580 ev->data.key.utf8[0] = '\0';
581 return 1;
582 }
583
584 static void ncurses_set_cursor(caca_display_t *dp, int flags)
585 {
586 if (!flags)
587 curs_set(0);
588 else if (curs_set(2) == ERR)
589 curs_set(1);
590 }
591
592 /*
593 * XXX: following functions are local
594 */
595
596 #if defined HAVE_SIGNAL
597 static void sigwinch_handler(int sig)
598 {
599 sigwinch_d->resize.resized = 1;
600
601 signal(SIGWINCH, sigwinch_handler);
602 }
603 #endif
604
605 #if defined HAVE_GETENV && defined HAVE_PUTENV
606 static void ncurses_install_terminal(caca_display_t *dp)
607 {
608 char *term, *colorterm;
609
610 dp->drv.p->term = NULL;
611
612 term = getenv("TERM");
613 colorterm = getenv("COLORTERM");
614
615 if(!term || strcmp(term, "xterm"))
616 return;
617
618 /* If we are using gnome-terminal, it's really a 16 colour terminal.
619 * Ditto if we are using xfce4-terminal, or Konsole. */
620 if((colorterm && (!strcmp(colorterm, "gnome-terminal")
621 || !strcmp(colorterm, "Terminal")))
622 || getenv("KONSOLE_DCOP_SESSION"))
623 {
624 SCREEN *screen;
625 screen = newterm("xterm-16color", stdout, stdin);
626 if(screen == NULL)
627 return;
628 endwin();
629 (void)putenv("TERM=xterm-16color");
630 dp->drv.p->term = strdup(term);
631 return;
632 }
633 }
634
635 static void ncurses_uninstall_terminal(caca_display_t *dp)
636 {
637 /* Needs to be persistent because we use putenv() */
638 static char termenv[1024];
639
640 if(!dp->drv.p->term)
641 return;
642
643 snprintf(termenv, 1023, "TERM=%s", dp->drv.p->term);
644 free(dp->drv.p->term);
645 (void)putenv(termenv);
646 }
647 #endif
648
649 static void ncurses_write_utf32(uint32_t ch)
650 {
651 #if defined HAVE_NCURSESW_NCURSES_H
652 char buf[10];
653 int bytes;
654 #endif
655
656 if(ch == CACA_MAGIC_FULLWIDTH)
657 return;
658
659 #if defined HAVE_NCURSESW_NCURSES_H
660 bytes = caca_utf32_to_utf8(buf, ch);
661 buf[bytes] = '\0';
662 addstr(buf);
663 #else
664 if(ch < 0x80)
665 {
666 addch(ch);
667 }
668 else
669 {
670 chtype cch;
671 chtype cch2;
672
673 cch = '?';
674 cch2 = ' ';
675 if ((ch > 0x0000ff00) && (ch < 0x0000ff5f))
676 {
677 cch = ch - 0x0000ff00 + ' ';
678 }
679 switch (ch)
680 {
681 case 0x000000a0: /* <nbsp> */
682 case 0x00003000: /* */
683 cch = ' ';
684 break;
685 case 0x000000a3: /* £ */
686 cch = ACS_STERLING;
687 break;
688 case 0x000000b0: /* ° */
689 cch = ACS_DEGREE;
690 break;
691 case 0x000000b1: /* ± */
692 cch = ACS_PLMINUS;
693 break;
694 case 0x000000b7: /* · */
695 case 0x00002219: /* ∙ */
696 case 0x000030fb: /* ・ */
697 cch = ACS_BULLET;
698 break;
699 case 0x000003c0: /* π */
700 cch = ACS_PI;
701 break;
702 case 0x00002018: /* ‘ */
703 case 0x00002019: /* ’ */
704 cch = '\'';
705 break;
706 case 0x0000201c: /* “ */
707 case 0x0000201d: /* ” */
708 cch = '"';
709 break;
710 case 0x00002190: /* ← */
711 cch = ACS_LARROW;
712 break;
713 case 0x00002191: /* ↑ */
714 cch = ACS_UARROW;
715 break;
716 case 0x00002192: /* → */
717 cch = ACS_RARROW;
718 break;
719 case 0x00002193: /* ↓ */
720 cch = ACS_DARROW;
721 break;
722 case 0x00002260: /* ≠ */
723 cch = ACS_NEQUAL;
724 break;
725 case 0x00002261: /* ≡ */
726 cch = '=';
727 break;
728 case 0x00002264: /* ≤ */
729 cch = ACS_LEQUAL;
730 break;
731 case 0x00002265: /* ≥ */
732 cch = ACS_GEQUAL;
733 break;
734 case 0x000023ba: /* ⎺ */
735 cch = ACS_S1;
736 cch2 = cch;
737 break;
738 case 0x000023bb: /* ⎻ */
739 cch = ACS_S3;
740 cch2 = cch;
741 break;
742 case 0x000023bc: /* ⎼ */
743 cch = ACS_S7;
744 cch2 = cch;
745 break;
746 case 0x000023bd: /* ⎽ */
747 cch = ACS_S9;
748 cch2 = cch;
749 break;
750 case 0x00002500: /* ─ */
751 case 0x00002550: /* ═ */
752 cch = ACS_HLINE;
753 cch2 = cch;
754 break;
755 case 0x00002502: /* │ */
756 case 0x00002551: /* ║ */
757 cch = ACS_VLINE;
758 break;
759 case 0x0000250c: /* ┌ */
760 case 0x00002552: /* ╒ */
761 case 0x00002553: /* ╓ */
762 case 0x00002554: /* ╔ */
763 cch = ACS_ULCORNER;
764 cch2 = ACS_HLINE;
765 break;
766 case 0x00002510: /* ┐ */
767 case 0x00002555: /* ╕ */
768 case 0x00002556: /* ╖ */
769 case 0x00002557: /* ╗ */
770 cch = ACS_URCORNER;
771 break;
772 case 0x00002514: /* └ */
773 case 0x00002558: /* ╘ */
774 case 0x00002559: /* ╙ */
775 case 0x0000255a: /* ╚ */
776 cch = ACS_LLCORNER;
777 cch2 = ACS_HLINE;
778 break;
779 case 0x00002518: /* ┘ */
780 case 0x0000255b: /* ╛ */
781 case 0x0000255c: /* ╜ */
782 case 0x0000255d: /* ╝ */
783 cch = ACS_LRCORNER;
784 break;
785 case 0x0000251c: /* ├ */
786 case 0x0000255e: /* ╞ */
787 case 0x0000255f: /* ╟ */
788 case 0x00002560: /* ╠ */
789 cch = ACS_LTEE;
790 cch2 = ACS_HLINE;
791 break;
792 case 0x00002524: /* ┤ */
793 case 0x00002561: /* ╡ */
794 case 0x00002562: /* ╢ */
795 case 0x00002563: /* ╣ */
796 cch = ACS_RTEE;
797 break;
798 case 0x0000252c: /* ┬ */
799 case 0x00002564: /* ╤ */
800 case 0x00002565: /* ╥ */
801 case 0x00002566: /* ╦ */
802 cch = ACS_TTEE;
803 cch2 = ACS_HLINE;
804 break;
805 case 0x00002534: /* ┴ */
806 case 0x00002567: /* ╧ */
807 case 0x00002568: /* ╨ */
808 case 0x00002569: /* ╩ */
809 cch = ACS_BTEE;
810 cch2 = ACS_HLINE;
811 break;
812 case 0x0000253c: /* ┼ */
813 case 0x0000256a: /* ╪ */
814 case 0x0000256b: /* ╫ */
815 case 0x0000256c: /* ╬ */
816 cch = ACS_PLUS;
817 cch2 = ACS_HLINE;
818 break;
819 case 0x00002591: /* ░ */
820 cch = ACS_BOARD;
821 cch2 = cch;
822 break;
823 case 0x00002592: /* ▒ */
824 case 0x00002593: /* ▓ */
825 cch = ACS_CKBOARD;
826 cch2 = cch;
827 break;
828 case 0x00002580: /* ▀ */
829 case 0x00002584: /* ▄ */
830 case 0x00002588: /* █ */
831 case 0x0000258c: /* ▌ */
832 case 0x00002590: /* ▐ */
833 case 0x000025a0: /* ■ */
834 case 0x000025ac: /* ▬ */
835 case 0x000025ae: /* ▮ */
836 cch = ACS_BLOCK;
837 cch2 = cch;
838 break;
839 case 0x000025c6: /* ◆ */
840 case 0x00002666: /* ♦ */
841 cch = ACS_DIAMOND;
842 break;
843 case 0x00002022: /* • */
844 case 0x000025cb: /* ○ */
845 case 0x000025cf: /* ● */
846 case 0x00002603: /* ☃ */
847 case 0x0000263c: /* ☼ */
848 cch = ACS_LANTERN;
849 break;
850 case 0x0000301c: /* 〜 */
851 cch = '~';
852 break;
853 }
854 addch(cch);
855 if(caca_utf32_is_fullwidth(ch))
856 {
857 addch(cch2);
858 }
859 }
860 #endif
861 }
862
863 /*
864 * Driver initialisation
865 */
866
867 int ncurses_install(caca_display_t *dp)
868 {
869 dp->drv.id = CACA_DRIVER_NCURSES;
870 dp->drv.driver = "ncurses";
871
872 dp->drv.init_graphics = ncurses_init_graphics;
873 dp->drv.end_graphics = ncurses_end_graphics;
874 dp->drv.set_display_title = ncurses_set_display_title;
875 dp->drv.get_display_width = ncurses_get_display_width;
876 dp->drv.get_display_height = ncurses_get_display_height;
877 dp->drv.display = ncurses_display;
878 dp->drv.handle_resize = ncurses_handle_resize;
879 dp->drv.get_event = ncurses_get_event;
880 dp->drv.set_mouse = NULL;
881 dp->drv.set_cursor = ncurses_set_cursor;
882
883 return 0;
884 }
885
886 #endif /* USE_NCURSES */
887