From patchwork Wed Jun 22 22:23:20 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Samuel Thibault X-Patchwork-Id: 9193867 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 901676075A for ; Wed, 22 Jun 2016 22:28:32 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7CE5726785 for ; Wed, 22 Jun 2016 22:28:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6FAC22841B; Wed, 22 Jun 2016 22:28:32 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 58F2626785 for ; Wed, 22 Jun 2016 22:28:31 +0000 (UTC) Received: from localhost ([::1]:32946 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bFqdK-0000nl-Gn for patchwork-qemu-devel@patchwork.kernel.org; Wed, 22 Jun 2016 18:28:30 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59651) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bFqYa-00043b-Mz for qemu-devel@nongnu.org; Wed, 22 Jun 2016 18:23:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bFqYU-0006EG-JN for qemu-devel@nongnu.org; Wed, 22 Jun 2016 18:23:36 -0400 Received: from hera.aquilenet.fr ([141.255.128.1]:51259) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bFqYU-0006Df-6v for qemu-devel@nongnu.org; Wed, 22 Jun 2016 18:23:30 -0400 Received: from localhost (localhost [127.0.0.1]) by hera.aquilenet.fr (Postfix) with ESMTP id 8C2FD8ABA; Thu, 23 Jun 2016 00:23:23 +0200 (CEST) Received: from hera.aquilenet.fr ([127.0.0.1]) by localhost (hera.aquilenet.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 3rnL_qiPlL9z; Thu, 23 Jun 2016 00:23:23 +0200 (CEST) Received: from var.youpi.perso.aquilenet.fr (ARennes-656-1-291-142.w2-10.abo.wanadoo.fr [2.10.55.142]) by hera.aquilenet.fr (Postfix) with ESMTPSA id 9C5C78AB7; Thu, 23 Jun 2016 00:23:22 +0200 (CEST) Received: from samy by var.youpi.perso.aquilenet.fr with local (Exim 4.87) (envelope-from ) id 1bFqYO-0006Ps-Uz; Thu, 23 Jun 2016 00:23:24 +0200 From: Samuel Thibault To: qemu-devel@nongnu.org, kraxel@redhat.com, pbonzini@redhat.com, berrange@redhat.com, peter.maydell@linaro.org, mjt@tls.msk.ru Date: Thu, 23 Jun 2016 00:23:20 +0200 Message-Id: <1466634202-24616-4-git-send-email-samuel.thibault@ens-lyon.org> X-Mailer: git-send-email 2.8.1 In-Reply-To: <1466634202-24616-1-git-send-email-samuel.thibault@ens-lyon.org> References: <1466634202-24616-1-git-send-email-samuel.thibault@ens-lyon.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 141.255.128.1 Subject: [Qemu-devel] [PATCH 3/5] curses: use wide output functions X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Samuel Thibault Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP This makes use of cchar_t instead of chtype when using ncursesw, which allows to store a wide char as well as the WACS values. This also allows to complete the printable glyphs list beyond ascii and the ACS values. Signed-off-by: Samuel Thibault --- hw/display/vga.c | 4 +- include/ui/console.h | 19 +++- ui/curses.c | 270 ++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 278 insertions(+), 15 deletions(-) diff --git a/hw/display/vga.c b/hw/display/vga.c index 9ebc54f..53d3c9a 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -1968,7 +1968,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) for (i = 0; i < size; src ++, dst ++, i ++) { console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src))); - if (*dst != val) { + if (memcmp(dst, &val, sizeof(val))) { *dst = val; c_max = i; break; @@ -1977,7 +1977,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) c_min = i; for (; i < size; src ++, dst ++, i ++) { console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src))); - if (*dst != val) { + if (memcmp(dst, &val, sizeof(val))) { *dst = val; c_max = i; } diff --git a/include/ui/console.h b/include/ui/console.h index 52a5f65..2939176 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -336,8 +336,12 @@ static inline pixman_format_code_t surface_format(DisplaySurface *s) #ifdef CONFIG_CURSES #include +#ifdef CONFIG_CURSESW +typedef cchar_t console_ch_t; +#else typedef chtype console_ch_t; -extern chtype vga_to_curses[]; +#endif +extern console_ch_t vga_to_curses[]; #else typedef unsigned long console_ch_t; #endif @@ -345,16 +349,27 @@ static inline void console_write_ch(console_ch_t *dest, uint32_t ch) { uint8_t c = ch; #ifdef CONFIG_CURSES +#ifdef CONFIG_CURSESW + if (vga_to_curses[c].chars[0]) { + *dest = vga_to_curses[c]; + } else { + dest->chars[0] = c; + dest->attr = 0; + } + dest->attr |= ch & ~0xff; +#else if (vga_to_curses[c]) { ch &= ~(console_ch_t)0xff; ch |= vga_to_curses[c]; } + *dest = ch; +#endif #else if (c == '\0') { ch |= ' '; } -#endif *dest = ch; +#endif } typedef struct GraphicHwOps { diff --git a/ui/curses.c b/ui/curses.c index 438b8be..9ef54b5 100644 --- a/ui/curses.c +++ b/ui/curses.c @@ -28,6 +28,11 @@ #include #include #endif +#ifdef CONFIG_CURSESW +#include +#include +#include +#endif #include "qemu-common.h" #include "ui/console.h" @@ -43,16 +48,25 @@ static WINDOW *screenpad = NULL; static int width, height, gwidth, gheight, invalidate; static int px, py, sminx, sminy, smaxx, smaxy; +#ifdef CONFIG_CURSESW +console_ch_t vga_to_curses[256]; +#else chtype vga_to_curses[256]; +#endif static void curses_update(DisplayChangeListener *dcl, int x, int y, int w, int h) { - chtype *line; + console_ch_t *line; - line = ((chtype *) screen) + y * width; - for (h += y; y < h; y ++, line += width) + line = ((console_ch_t *) screen) + y * width; + for (h += y; y < h; y ++, line += width) { +#ifdef CONFIG_CURSESW + mvwadd_wchnstr(screenpad, y, 0, line, width); +#else mvwaddchnstr(screenpad, y, 0, line, width); +#endif + } pnoutrefresh(screenpad, py, px, sminy, sminx, smaxy - 1, smaxx - 1); refresh(); @@ -362,15 +376,245 @@ static void curses_setup(void) /* * Setup mapping for vga to curses line graphics. - * FIXME: for better font, have to use ncursesw and setlocale() */ -#if 0 - /* FIXME: map from where? */ - ACS_S1; - ACS_S3; - ACS_S7; - ACS_S9; -#endif + +#ifdef CONFIG_CURSESW + vga_to_curses['\0'].chars[0] = L' '; + vga_to_curses[0x01].chars[0] = L'\u263a'; + vga_to_curses[0x02].chars[0] = L'\u263b'; + vga_to_curses[0x03].chars[0] = L'\u2665'; + vga_to_curses[0x04].chars[0] = L'\u2666'; + vga_to_curses[0x05].chars[0] = L'\u2663'; + vga_to_curses[0x06].chars[0] = L'\u2660'; + vga_to_curses[0x07].chars[0] = L'\u2022'; + vga_to_curses[0x08].chars[0] = L'\u25d8'; + vga_to_curses[0x09].chars[0] = L'\u25cb'; + vga_to_curses[0x0a].chars[0] = L'\u25d9'; + vga_to_curses[0x0b].chars[0] = L'\u2642'; + vga_to_curses[0x0c].chars[0] = L'\u2640'; + vga_to_curses[0x0d].chars[0] = L'\u266a'; + vga_to_curses[0x0e].chars[0] = L'\u266b'; + vga_to_curses[0x0f].chars[0] = L'\u263c'; + vga_to_curses[0x10].chars[0] = L'\u25ba'; + vga_to_curses[0x11].chars[0] = L'\u25c4'; + vga_to_curses[0x12].chars[0] = L'\u2195'; + vga_to_curses[0x13].chars[0] = L'\u203c'; + vga_to_curses[0x14].chars[0] = L'\u00b6'; + vga_to_curses[0x15].chars[0] = L'\u00a7'; + vga_to_curses[0x16].chars[0] = L'\u25ac'; + vga_to_curses[0x17].chars[0] = L'\u21a8'; + vga_to_curses[0x18].chars[0] = L'\u2191'; + vga_to_curses[0x19].chars[0] = L'\u2193'; + vga_to_curses[0x1a].chars[0] = L'\u2192'; + vga_to_curses[0x1b].chars[0] = L'\u2190'; + vga_to_curses[0x1c].chars[0] = L'\u221f'; + vga_to_curses[0x1d].chars[0] = L'\u2194'; + vga_to_curses[0x1e].chars[0] = L'\u25b2'; + vga_to_curses[0x1f].chars[0] = L'\u25bc'; + + { + /* Hardcode CP437 to unicode */ + vga_to_curses[0x80].chars[0] = L'\u00C7'; + vga_to_curses[0x81].chars[0] = L'\u00FC'; + vga_to_curses[0x82].chars[0] = L'\u00E9'; + vga_to_curses[0x83].chars[0] = L'\u00E2'; + vga_to_curses[0x84].chars[0] = L'\u00E4'; + vga_to_curses[0x85].chars[0] = L'\u00E0'; + vga_to_curses[0x86].chars[0] = L'\u00E5'; + vga_to_curses[0x87].chars[0] = L'\u00E7'; + vga_to_curses[0x88].chars[0] = L'\u00EA'; + vga_to_curses[0x89].chars[0] = L'\u00EB'; + vga_to_curses[0x8a].chars[0] = L'\u00E8'; + vga_to_curses[0x8b].chars[0] = L'\u00EF'; + vga_to_curses[0x8c].chars[0] = L'\u00EE'; + vga_to_curses[0x8d].chars[0] = L'\u00EC'; + vga_to_curses[0x8e].chars[0] = L'\u00C4'; + vga_to_curses[0x8f].chars[0] = L'\u00C5'; + vga_to_curses[0x90].chars[0] = L'\u00C9'; + vga_to_curses[0x91].chars[0] = L'\u00E6'; + vga_to_curses[0x92].chars[0] = L'\u00C6'; + vga_to_curses[0x93].chars[0] = L'\u00F4'; + vga_to_curses[0x94].chars[0] = L'\u00F6'; + vga_to_curses[0x95].chars[0] = L'\u00F2'; + vga_to_curses[0x96].chars[0] = L'\u00FB'; + vga_to_curses[0x97].chars[0] = L'\u00F9'; + vga_to_curses[0x98].chars[0] = L'\u00FF'; + vga_to_curses[0x99].chars[0] = L'\u00D6'; + vga_to_curses[0x9a].chars[0] = L'\u00DC'; + vga_to_curses[0x9b].chars[0] = L'\u00A2'; + vga_to_curses[0x9c].chars[0] = L'\u00A3'; + vga_to_curses[0x9d].chars[0] = L'\u00A5'; + vga_to_curses[0x9e].chars[0] = L'\u20A7'; + vga_to_curses[0x9f].chars[0] = L'\u0192'; + vga_to_curses[0xa0].chars[0] = L'\u00E1'; + vga_to_curses[0xa1].chars[0] = L'\u00ED'; + vga_to_curses[0xa2].chars[0] = L'\u00F3'; + vga_to_curses[0xa3].chars[0] = L'\u00FA'; + vga_to_curses[0xa4].chars[0] = L'\u00F1'; + vga_to_curses[0xa5].chars[0] = L'\u00D1'; + vga_to_curses[0xa6].chars[0] = L'\u00AA'; + vga_to_curses[0xa7].chars[0] = L'\u00BA'; + vga_to_curses[0xa8].chars[0] = L'\u00BF'; + vga_to_curses[0xa9].chars[0] = L'\u2310'; + vga_to_curses[0xaa].chars[0] = L'\u00AC'; + vga_to_curses[0xab].chars[0] = L'\u00BD'; + vga_to_curses[0xac].chars[0] = L'\u00BC'; + vga_to_curses[0xad].chars[0] = L'\u00A1'; + vga_to_curses[0xae].chars[0] = L'\u00AB'; + vga_to_curses[0xaf].chars[0] = L'\u00BB'; + vga_to_curses[0xb0].chars[0] = L'\u2591'; + vga_to_curses[0xb1].chars[0] = L'\u2592'; + vga_to_curses[0xb2].chars[0] = L'\u2593'; + vga_to_curses[0xb3].chars[0] = L'\u2502'; + vga_to_curses[0xb4].chars[0] = L'\u2524'; + vga_to_curses[0xb5].chars[0] = L'\u2561'; + vga_to_curses[0xb6].chars[0] = L'\u2562'; + vga_to_curses[0xb7].chars[0] = L'\u2556'; + vga_to_curses[0xb8].chars[0] = L'\u2555'; + vga_to_curses[0xb9].chars[0] = L'\u2563'; + vga_to_curses[0xba].chars[0] = L'\u2551'; + vga_to_curses[0xbb].chars[0] = L'\u2557'; + vga_to_curses[0xbc].chars[0] = L'\u255D'; + vga_to_curses[0xbd].chars[0] = L'\u255C'; + vga_to_curses[0xbe].chars[0] = L'\u255B'; + vga_to_curses[0xbf].chars[0] = L'\u2510'; + vga_to_curses[0xc0].chars[0] = L'\u2514'; + vga_to_curses[0xc1].chars[0] = L'\u2534'; + vga_to_curses[0xc2].chars[0] = L'\u252C'; + vga_to_curses[0xc3].chars[0] = L'\u251C'; + vga_to_curses[0xc4].chars[0] = L'\u2500'; + vga_to_curses[0xc5].chars[0] = L'\u253C'; + vga_to_curses[0xc6].chars[0] = L'\u255E'; + vga_to_curses[0xc7].chars[0] = L'\u255F'; + vga_to_curses[0xc8].chars[0] = L'\u255A'; + vga_to_curses[0xc9].chars[0] = L'\u2554'; + vga_to_curses[0xca].chars[0] = L'\u2569'; + vga_to_curses[0xcb].chars[0] = L'\u2566'; + vga_to_curses[0xcc].chars[0] = L'\u2560'; + vga_to_curses[0xcd].chars[0] = L'\u2550'; + vga_to_curses[0xce].chars[0] = L'\u256C'; + vga_to_curses[0xcf].chars[0] = L'\u2567'; + vga_to_curses[0xd0].chars[0] = L'\u2568'; + vga_to_curses[0xd1].chars[0] = L'\u2564'; + vga_to_curses[0xd2].chars[0] = L'\u2565'; + vga_to_curses[0xd3].chars[0] = L'\u2559'; + vga_to_curses[0xd4].chars[0] = L'\u2558'; + vga_to_curses[0xd5].chars[0] = L'\u2552'; + vga_to_curses[0xd6].chars[0] = L'\u2553'; + vga_to_curses[0xd7].chars[0] = L'\u256B'; + vga_to_curses[0xd8].chars[0] = L'\u256A'; + vga_to_curses[0xd9].chars[0] = L'\u2518'; + vga_to_curses[0xda].chars[0] = L'\u250C'; + vga_to_curses[0xdb].chars[0] = L'\u2588'; + vga_to_curses[0xdc].chars[0] = L'\u2584'; + vga_to_curses[0xdd].chars[0] = L'\u258C'; + vga_to_curses[0xde].chars[0] = L'\u2590'; + vga_to_curses[0xdf].chars[0] = L'\u2580'; + vga_to_curses[0xe0].chars[0] = L'\u03B1'; + vga_to_curses[0xe1].chars[0] = L'\u00DF'; + vga_to_curses[0xe2].chars[0] = L'\u0393'; + vga_to_curses[0xe3].chars[0] = L'\u03C0'; + vga_to_curses[0xe4].chars[0] = L'\u03A3'; + vga_to_curses[0xe5].chars[0] = L'\u03C3'; + vga_to_curses[0xe6].chars[0] = L'\u00B5'; + vga_to_curses[0xe7].chars[0] = L'\u03C4'; + vga_to_curses[0xe8].chars[0] = L'\u03A6'; + vga_to_curses[0xe9].chars[0] = L'\u0398'; + vga_to_curses[0xea].chars[0] = L'\u03A9'; + vga_to_curses[0xeb].chars[0] = L'\u03B4'; + vga_to_curses[0xec].chars[0] = L'\u221E'; + vga_to_curses[0xed].chars[0] = L'\u03C6'; + vga_to_curses[0xee].chars[0] = L'\u03B5'; + vga_to_curses[0xef].chars[0] = L'\u2229'; + vga_to_curses[0xf0].chars[0] = L'\u2261'; + vga_to_curses[0xf1].chars[0] = L'\u00B1'; + vga_to_curses[0xf2].chars[0] = L'\u2265'; + vga_to_curses[0xf3].chars[0] = L'\u2264'; + vga_to_curses[0xf4].chars[0] = L'\u2320'; + vga_to_curses[0xf5].chars[0] = L'\u2321'; + vga_to_curses[0xf6].chars[0] = L'\u00F7'; + vga_to_curses[0xf7].chars[0] = L'\u2248'; + vga_to_curses[0xf8].chars[0] = L'\u00B0'; + vga_to_curses[0xf9].chars[0] = L'\u2219'; + vga_to_curses[0xfa].chars[0] = L'\u00B7'; + vga_to_curses[0xfb].chars[0] = L'\u221A'; + vga_to_curses[0xfc].chars[0] = L'\u207F'; + vga_to_curses[0xfd].chars[0] = L'\u00B2'; + vga_to_curses[0xfe].chars[0] = L'\u25A0'; + vga_to_curses[0xff].chars[0] = L'\u00A0'; + } + if (strcmp(nl_langinfo(CODESET), "UTF-8")) { + /* Non-Unicode capable, use termcap equivalents for those available */ + for (i = 0; i <= 0xff; i++) + { + if (vga_to_curses[i].chars[0] == L'\u00a3') + vga_to_curses[i] = *WACS_STERLING; + if (vga_to_curses[i].chars[0] == L'\u2591') + vga_to_curses[i] = *WACS_BOARD; + if (vga_to_curses[i].chars[0] == L'\u2592') + vga_to_curses[i] = *WACS_CKBOARD; + if (vga_to_curses[i].chars[0] == L'\u2502') + vga_to_curses[i] = *WACS_VLINE; + if (vga_to_curses[i].chars[0] == L'\u2524') + vga_to_curses[i] = *WACS_RTEE; + if (vga_to_curses[i].chars[0] == L'\u2510') + vga_to_curses[i] = *WACS_URCORNER; + if (vga_to_curses[i].chars[0] == L'\u2514') + vga_to_curses[i] = *WACS_LLCORNER; + if (vga_to_curses[i].chars[0] == L'\u2534') + vga_to_curses[i] = *WACS_BTEE; + if (vga_to_curses[i].chars[0] == L'\u252c') + vga_to_curses[i] = *WACS_TTEE; + if (vga_to_curses[i].chars[0] == L'\u251c') + vga_to_curses[i] = *WACS_LTEE; + if (vga_to_curses[i].chars[0] == L'\u2500') + vga_to_curses[i] = *WACS_HLINE; + if (vga_to_curses[i].chars[0] == L'\u253c') + vga_to_curses[i] = *WACS_PLUS; + if (vga_to_curses[i].chars[0] == L'\u256c') + vga_to_curses[i] = *WACS_LANTERN; + if (vga_to_curses[i].chars[0] == L'\u256a') + vga_to_curses[i] = *WACS_NEQUAL; + if (vga_to_curses[i].chars[0] == L'\u2518') + vga_to_curses[i] = *WACS_LRCORNER; + if (vga_to_curses[i].chars[0] == L'\u250c') + vga_to_curses[i] = *WACS_ULCORNER; + if (vga_to_curses[i].chars[0] == L'\u2588') + vga_to_curses[i] = *WACS_BLOCK; + if (vga_to_curses[i].chars[0] == L'\u03c0') + vga_to_curses[i] = *WACS_PI; + if (vga_to_curses[i].chars[0] == L'\u00b1') + vga_to_curses[i] = *WACS_PLMINUS; + if (vga_to_curses[i].chars[0] == L'\u2265') + vga_to_curses[i] = *WACS_GEQUAL; + if (vga_to_curses[i].chars[0] == L'\u2264') + vga_to_curses[i] = *WACS_LEQUAL; + if (vga_to_curses[i].chars[0] == L'\u00b0') + vga_to_curses[i] = *WACS_DEGREE; + if (vga_to_curses[i].chars[0] == L'\u25a0') + vga_to_curses[i] = *WACS_BULLET; + if (vga_to_curses[i].chars[0] == L'\u2666') + vga_to_curses[i] = *WACS_DIAMOND; + if (vga_to_curses[i].chars[0] == L'\u2192') + vga_to_curses[i] = *WACS_RARROW; + if (vga_to_curses[i].chars[0] == L'\u2190') + vga_to_curses[i] = *WACS_LARROW; + if (vga_to_curses[i].chars[0] == L'\u2191') + vga_to_curses[i] = *WACS_UARROW; + if (vga_to_curses[i].chars[0] == L'\u2193') + vga_to_curses[i] = *WACS_DARROW; + if (vga_to_curses[i].chars[0] == L'\u23ba') + vga_to_curses[i] = *WACS_S1; + if (vga_to_curses[i].chars[0] == L'\u23bb') + vga_to_curses[i] = *WACS_S3; + if (vga_to_curses[i].chars[0] == L'\u23bc') + vga_to_curses[i] = *WACS_S7; + if (vga_to_curses[i].chars[0] == L'\u23bd') + vga_to_curses[i] = *WACS_S9; + } + } +#else + /* No wide char support, hardcode ASCII + termcap-portable CP437 */ /* ACS_* is not constant. So, we can't initialize statically. */ vga_to_curses['\0'] = ' '; vga_to_curses[0x04] = ACS_DIAMOND; @@ -401,6 +645,7 @@ static void curses_setup(void) vga_to_curses[0xf3] = ACS_LEQUAL; vga_to_curses[0xf8] = ACS_DEGREE; vga_to_curses[0xfe] = ACS_BULLET; +#endif } static void curses_keyboard_setup(void) @@ -434,6 +679,9 @@ void curses_display_init(DisplayState *ds, int full_screen) } #endif +#ifdef CONFIG_CURSESW + setlocale(LC_CTYPE, ""); +#endif curses_setup(); curses_keyboard_setup(); atexit(curses_atexit);