1fdd4e1e0SJan Lentfer /****************************************************************************
2*32bb5217SDaniel Fojt  * Copyright 2020 Thomas E. Dickey                                          *
3*32bb5217SDaniel Fojt  * Copyright 2002-2011,2016 Free Software Foundation, Inc.                  *
4fdd4e1e0SJan Lentfer  *                                                                          *
5fdd4e1e0SJan Lentfer  * Permission is hereby granted, free of charge, to any person obtaining a  *
6fdd4e1e0SJan Lentfer  * copy of this software and associated documentation files (the            *
7fdd4e1e0SJan Lentfer  * "Software"), to deal in the Software without restriction, including      *
8fdd4e1e0SJan Lentfer  * without limitation the rights to use, copy, modify, merge, publish,      *
9fdd4e1e0SJan Lentfer  * distribute, distribute with modifications, sublicense, and/or sell       *
10fdd4e1e0SJan Lentfer  * copies of the Software, and to permit persons to whom the Software is    *
11fdd4e1e0SJan Lentfer  * furnished to do so, subject to the following conditions:                 *
12fdd4e1e0SJan Lentfer  *                                                                          *
13fdd4e1e0SJan Lentfer  * The above copyright notice and this permission notice shall be included  *
14fdd4e1e0SJan Lentfer  * in all copies or substantial portions of the Software.                   *
15fdd4e1e0SJan Lentfer  *                                                                          *
16fdd4e1e0SJan Lentfer  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
17fdd4e1e0SJan Lentfer  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
18fdd4e1e0SJan Lentfer  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
19fdd4e1e0SJan Lentfer  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
20fdd4e1e0SJan Lentfer  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
21fdd4e1e0SJan Lentfer  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
22fdd4e1e0SJan Lentfer  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
23fdd4e1e0SJan Lentfer  *                                                                          *
24fdd4e1e0SJan Lentfer  * Except as contained in this notice, the name(s) of the above copyright   *
25fdd4e1e0SJan Lentfer  * holders shall not be used in advertising or otherwise to promote the     *
26fdd4e1e0SJan Lentfer  * sale, use or other dealings in this Software without prior written       *
27fdd4e1e0SJan Lentfer  * authorization.                                                           *
28fdd4e1e0SJan Lentfer  ****************************************************************************/
29fdd4e1e0SJan Lentfer 
30fdd4e1e0SJan Lentfer /****************************************************************************
311d102085SJan Lentfer  *  Author: Thomas E. Dickey 2002-on                                        *
32fdd4e1e0SJan Lentfer  ****************************************************************************/
33fdd4e1e0SJan Lentfer 
34fdd4e1e0SJan Lentfer /*
35fdd4e1e0SJan Lentfer **	lib_get_wch.c
36fdd4e1e0SJan Lentfer **
37fdd4e1e0SJan Lentfer **	The routine get_wch().
38fdd4e1e0SJan Lentfer **
39fdd4e1e0SJan Lentfer */
40fdd4e1e0SJan Lentfer 
41fdd4e1e0SJan Lentfer #include <curses.priv.h>
421d102085SJan Lentfer #include <ctype.h>
43fdd4e1e0SJan Lentfer 
44*32bb5217SDaniel Fojt MODULE_ID("$Id: lib_get_wch.c,v 1.25 2020/02/02 23:34:34 tom Exp $")
45fdd4e1e0SJan Lentfer 
NCURSES_EXPORT(int)46fdd4e1e0SJan Lentfer NCURSES_EXPORT(int)
47fdd4e1e0SJan Lentfer wget_wch(WINDOW *win, wint_t *result)
48fdd4e1e0SJan Lentfer {
491d102085SJan Lentfer     SCREEN *sp;
50fdd4e1e0SJan Lentfer     int code;
5100d8f3c4SJohn Marino     int value = 0;
52fdd4e1e0SJan Lentfer     wchar_t wch;
531d102085SJan Lentfer #ifndef state_unused
541d102085SJan Lentfer     mbstate_t state;
551d102085SJan Lentfer #endif
56fdd4e1e0SJan Lentfer 
5700d8f3c4SJohn Marino     T((T_CALLED("wget_wch(%p)"), (void *) win));
58fdd4e1e0SJan Lentfer 
59fdd4e1e0SJan Lentfer     /*
60fdd4e1e0SJan Lentfer      * We can get a stream of single-byte characters and KEY_xxx codes from
61fdd4e1e0SJan Lentfer      * _nc_wgetch(), while we want to return a wide character or KEY_xxx code.
62fdd4e1e0SJan Lentfer      */
631d102085SJan Lentfer     _nc_lock_global(curses);
641d102085SJan Lentfer     sp = _nc_screen_of(win);
65*32bb5217SDaniel Fojt 
661d102085SJan Lentfer     if (sp != 0) {
67*32bb5217SDaniel Fojt 	size_t count = 0;
68*32bb5217SDaniel Fojt 
69fdd4e1e0SJan Lentfer 	for (;;) {
70*32bb5217SDaniel Fojt 	    char buffer[(MB_LEN_MAX * 9) + 1];	/* allow some redundant shifts */
71*32bb5217SDaniel Fojt 
721d102085SJan Lentfer 	    T(("reading %d of %d", (int) count + 1, (int) sizeof(buffer)));
731d102085SJan Lentfer 	    code = _nc_wgetch(win, &value, TRUE EVENTLIST_2nd((_nc_eventlist
741d102085SJan Lentfer 							       *) 0));
75fdd4e1e0SJan Lentfer 	    if (code == ERR) {
76fdd4e1e0SJan Lentfer 		break;
77fdd4e1e0SJan Lentfer 	    } else if (code == KEY_CODE_YES) {
78fdd4e1e0SJan Lentfer 		/*
791d102085SJan Lentfer 		 * If we were processing an incomplete multibyte character,
801d102085SJan Lentfer 		 * return an error since we have a KEY_xxx code which
811d102085SJan Lentfer 		 * interrupts it.  For some cases, we could improve this by
821d102085SJan Lentfer 		 * writing a new version of lib_getch.c(!), but it is not clear
831d102085SJan Lentfer 		 * whether the improvement would be worth the effort.
84fdd4e1e0SJan Lentfer 		 */
85fdd4e1e0SJan Lentfer 		if (count != 0) {
8600d8f3c4SJohn Marino 		    safe_ungetch(SP_PARM, value);
87fdd4e1e0SJan Lentfer 		    code = ERR;
88fdd4e1e0SJan Lentfer 		}
89fdd4e1e0SJan Lentfer 		break;
90fdd4e1e0SJan Lentfer 	    } else if (count + 1 >= sizeof(buffer)) {
9100d8f3c4SJohn Marino 		safe_ungetch(SP_PARM, value);
92fdd4e1e0SJan Lentfer 		code = ERR;
93fdd4e1e0SJan Lentfer 		break;
94fdd4e1e0SJan Lentfer 	    } else {
95*32bb5217SDaniel Fojt 		int status;
96*32bb5217SDaniel Fojt 
971d102085SJan Lentfer 		buffer[count++] = (char) UChar(value);
98fdd4e1e0SJan Lentfer 		reset_mbytes(state);
99fdd4e1e0SJan Lentfer 		status = count_mbytes(buffer, count, state);
100fdd4e1e0SJan Lentfer 		if (status >= 0) {
101fdd4e1e0SJan Lentfer 		    reset_mbytes(state);
102fdd4e1e0SJan Lentfer 		    if (check_mbytes(wch, buffer, count, state) != status) {
103fdd4e1e0SJan Lentfer 			code = ERR;	/* the two calls should match */
10400d8f3c4SJohn Marino 			safe_ungetch(SP_PARM, value);
105fdd4e1e0SJan Lentfer 		    }
106fdd4e1e0SJan Lentfer 		    value = wch;
107fdd4e1e0SJan Lentfer 		    break;
108fdd4e1e0SJan Lentfer 		}
109fdd4e1e0SJan Lentfer 	    }
110fdd4e1e0SJan Lentfer 	}
1111d102085SJan Lentfer     } else {
1121d102085SJan Lentfer 	code = ERR;
1131d102085SJan Lentfer     }
1143468e90cSJohn Marino 
1153468e90cSJohn Marino     if (result != 0)
11600d8f3c4SJohn Marino 	*result = (wint_t) value;
1173468e90cSJohn Marino 
1181d102085SJan Lentfer     _nc_unlock_global(curses);
11900d8f3c4SJohn Marino     T(("result %#o", value));
120fdd4e1e0SJan Lentfer     returnCode(code);
121fdd4e1e0SJan Lentfer }
122