1 /* Determine the number of screen columns needed for a character. 2 Copyright (C) 2006-2007, 2010-2021 Free Software Foundation, Inc. 3 4 This file is free software: you can redistribute it and/or modify 5 it under the terms of the GNU Lesser General Public License as 6 published by the Free Software Foundation; either version 2.1 of the 7 License, or (at your option) any later version. 8 9 This file is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU Lesser General Public License for more details. 13 14 You should have received a copy of the GNU Lesser General Public License 15 along with this program. If not, see <https://www.gnu.org/licenses/>. */ 16 17 #include <config.h> 18 19 /* Specification. */ 20 #include <wchar.h> 21 22 /* Get iswprint. */ 23 #include <wctype.h> 24 25 #include "localcharset.h" 26 #include "streq.h" 27 #include "uniwidth.h" 28 29 /* Returns 1 if the current locale is an UTF-8 locale, 0 otherwise. */ 30 static inline int 31 is_locale_utf8 (void) /* */ 32 { 33 const char *encoding = locale_charset (); 34 return STREQ_OPT (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0, 0); 35 } 36 37 #if GNULIB_WCHAR_SINGLE_LOCALE 38 /* When we know that the locale does not change, provide a speedup by 39 caching the value of is_locale_utf8. */ 40 static int cached_is_locale_utf8 = -1; 41 static inline int 42 is_locale_utf8_cached (void) /* */ 43 { 44 if (cached_is_locale_utf8 < 0) 45 cached_is_locale_utf8 = is_locale_utf8 (); 46 return cached_is_locale_utf8; 47 } 48 #else 49 /* By default, don't make assumptions, hence no caching. */ 50 # define is_locale_utf8_cached is_locale_utf8 51 #endif 52 53 int 54 wcwidth (wchar_t wc) /* */ 55 #undef wcwidth 56 { 57 /* In UTF-8 locales, use a Unicode aware width function. */ 58 if (is_locale_utf8_cached ()) 59 { 60 /* We assume that in a UTF-8 locale, a wide character is the same as a 61 Unicode character. */ 62 return uc_width (wc, "UTF-8"); 63 } 64 else 65 { 66 /* Otherwise, fall back to the system's wcwidth function. */ 67 #if HAVE_WCWIDTH 68 return wcwidth (wc); 69 #else 70 return wc == 0 ? 0 : iswprint (wc) ? 1 : -1; 71 #endif 72 } 73 }