197049Speter/**************************************************************************** 2184989Srafan * Copyright (c) 2002-2007,2008 Free Software Foundation, Inc. * 397049Speter * * 497049Speter * Permission is hereby granted, free of charge, to any person obtaining a * 597049Speter * copy of this software and associated documentation files (the * 697049Speter * "Software"), to deal in the Software without restriction, including * 797049Speter * without limitation the rights to use, copy, modify, merge, publish, * 897049Speter * distribute, distribute with modifications, sublicense, and/or sell * 997049Speter * copies of the Software, and to permit persons to whom the Software is * 1097049Speter * furnished to do so, subject to the following conditions: * 1197049Speter * * 1297049Speter * The above copyright notice and this permission notice shall be included * 1397049Speter * in all copies or substantial portions of the Software. * 1497049Speter * * 1597049Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 1697049Speter * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 1797049Speter * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 1897049Speter * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 1997049Speter * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 2097049Speter * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 2197049Speter * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 2297049Speter * * 2397049Speter * Except as contained in this notice, the name(s) of the above copyright * 2497049Speter * holders shall not be used in advertising or otherwise to promote the * 2597049Speter * sale, use or other dealings in this Software without prior written * 2697049Speter * authorization. * 2797049Speter ****************************************************************************/ 2897049Speter 2997049Speter/**************************************************************************** 30166124Srafan * Author: Thomas E. Dickey 2002-on * 3197049Speter ****************************************************************************/ 3297049Speter 3397049Speter/* 3497049Speter** lib_get_wch.c 3597049Speter** 3697049Speter** The routine get_wch(). 3797049Speter** 3897049Speter*/ 3997049Speter 4097049Speter#include <curses.priv.h> 41166124Srafan#include <ctype.h> 4297049Speter 43184989SrafanMODULE_ID("$Id: lib_get_wch.c,v 1.17 2008/08/16 19:22:55 tom Exp $") 4497049Speter 45166124Srafan#if HAVE_MBTOWC && HAVE_MBLEN 46166124Srafan#define reset_mbytes(state) mblen(NULL, 0), mbtowc(NULL, NULL, 0) 47166124Srafan#define count_mbytes(buffer,length,state) mblen(buffer,length) 48166124Srafan#define check_mbytes(wch,buffer,length,state) \ 49166124Srafan (int) mbtowc(&wch, buffer, length) 50166124Srafan#define state_unused 51166124Srafan#elif HAVE_MBRTOWC && HAVE_MBRLEN 52166124Srafan#define reset_mbytes(state) init_mb(state) 53166124Srafan#define count_mbytes(buffer,length,state) mbrlen(buffer,length,&state) 54166124Srafan#define check_mbytes(wch,buffer,length,state) \ 55166124Srafan (int) mbrtowc(&wch, buffer, length, &state) 56166124Srafan#else 57166124Srafanmake an error 58166124Srafan#endif 59166124Srafan 6097049SpeterNCURSES_EXPORT(int) 61166124Srafanwget_wch(WINDOW *win, wint_t *result) 6297049Speter{ 63184989Srafan SCREEN *sp; 6497049Speter int code; 65166124Srafan char buffer[(MB_LEN_MAX * 9) + 1]; /* allow some redundant shifts */ 6697049Speter int status; 6797049Speter size_t count = 0; 6897049Speter unsigned long value; 6997049Speter wchar_t wch; 70166124Srafan#ifndef state_unused 71166124Srafan mbstate_t state; 72166124Srafan#endif 7397049Speter 7497049Speter T((T_CALLED("wget_wch(%p)"), win)); 75166124Srafan 7697049Speter /* 7797049Speter * We can get a stream of single-byte characters and KEY_xxx codes from 7897049Speter * _nc_wgetch(), while we want to return a wide character or KEY_xxx code. 7997049Speter */ 80184989Srafan _nc_lock_global(curses); 81184989Srafan sp = _nc_screen_of(win); 82184989Srafan if (sp != 0) { 83184989Srafan for (;;) { 84184989Srafan T(("reading %d of %d", (int) count + 1, (int) sizeof(buffer))); 85184989Srafan code = _nc_wgetch(win, &value, TRUE EVENTLIST_2nd((_nc_eventlist 86184989Srafan *) 0)); 87184989Srafan if (code == ERR) { 88184989Srafan break; 89184989Srafan } else if (code == KEY_CODE_YES) { 90184989Srafan /* 91184989Srafan * If we were processing an incomplete multibyte character, 92184989Srafan * return an error since we have a KEY_xxx code which 93184989Srafan * interrupts it. For some cases, we could improve this by 94184989Srafan * writing a new version of lib_getch.c(!), but it is not clear 95184989Srafan * whether the improvement would be worth the effort. 96184989Srafan */ 97184989Srafan if (count != 0) { 98184989Srafan _nc_ungetch(sp, (int) value); 99184989Srafan code = ERR; 100184989Srafan } 101184989Srafan break; 102184989Srafan } else if (count + 1 >= sizeof(buffer)) { 103184989Srafan _nc_ungetch(sp, (int) value); 10497049Speter code = ERR; 105184989Srafan break; 106184989Srafan } else { 107184989Srafan buffer[count++] = (char) UChar(value); 108166124Srafan reset_mbytes(state); 109184989Srafan status = count_mbytes(buffer, count, state); 110184989Srafan if (status >= 0) { 111184989Srafan reset_mbytes(state); 112184989Srafan if (check_mbytes(wch, buffer, count, state) != status) { 113184989Srafan code = ERR; /* the two calls should match */ 114184989Srafan _nc_ungetch(sp, (int) value); 115184989Srafan } 116184989Srafan value = wch; 117184989Srafan break; 11897049Speter } 11997049Speter } 12097049Speter } 121184989Srafan } else { 122184989Srafan code = ERR; 12397049Speter } 12497049Speter *result = value; 125184989Srafan _nc_unlock_global(curses); 126166124Srafan T(("result %#lo", value)); 12797049Speter returnCode(code); 12897049Speter} 129