(root)/
tar-1.35/
gnu/
c32width.c
       1  /* Determine the number of screen columns needed for a 32-bit wide character.
       2     Copyright (C) 2020-2023 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  /* Written by Bruno Haible <bruno@clisp.org>, 2023.  */
      18  
      19  #include <config.h>
      20  
      21  #define IN_C32WIDTH
      22  /* Specification.  */
      23  #include <uchar.h>
      24  
      25  #include <wchar.h>
      26  
      27  #ifdef __CYGWIN__
      28  # include <cygwin/version.h>
      29  #endif
      30  
      31  #if GNULIB_defined_mbstate_t
      32  # include "streq.h"
      33  #endif
      34  
      35  #include "localcharset.h"
      36  
      37  #if GL_CHAR32_T_IS_UNICODE
      38  # include "lc-charset-unicode.h"
      39  #endif
      40  
      41  #include "uniwidth.h"
      42  
      43  #if _GL_WCHAR_T_IS_UCS4 && !GNULIB_defined_mbstate_t
      44  _GL_EXTERN_INLINE
      45  #endif
      46  int
      47  c32width (char32_t wc)
      48  {
      49    /* The char32_t encoding of a multibyte character is defined by the way
      50       mbrtoc32() is defined.  */
      51  
      52  #if GNULIB_defined_mbstate_t            /* AIX, IRIX */
      53    /* mbrtoc32() is defined on top of mbtowc() for the non-UTF-8 locales
      54       and directly for the UTF-8 locales.  */
      55    const char *encoding = locale_charset ();
      56    if (STREQ_OPT (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0, 0))
      57      return uc_width (wc, encoding);
      58    else
      59      return wcwidth (wc);
      60  
      61  #elif HAVE_WORKING_MBRTOC32             /* glibc, Android */
      62    /* mbrtoc32() is essentially defined by the system libc.  */
      63  
      64  # if _GL_WCHAR_T_IS_UCS4
      65    /* The char32_t encoding of a multibyte character is known to be the same as
      66       the wchar_t encoding.  */
      67    return wcwidth (wc);
      68  # else
      69    /* The char32_t encoding of a multibyte character is known to be UCS-4,
      70       different from the wchar_t encoding.  */
      71    return uc_width (wc, locale_charset ());
      72  # endif
      73  
      74  #elif _GL_SMALL_WCHAR_T                 /* Cygwin, mingw, MSVC */
      75    /* The wchar_t encoding is UTF-16.
      76       The char32_t encoding is UCS-4.  */
      77  
      78  # if defined __CYGWIN__ && CYGWIN_VERSION_DLL_MAJOR >= 1007 && 0
      79    /* As an extension to POSIX, the wcwidth() function of Cygwin >= 1.7
      80       supports also wc arguments outside the Unicode BMP, that is, outside
      81       the 'wchar_t' range.  See
      82       <https://www.cygwin.com/cgit/newlib-cygwin/commit/?id=098a75dc51caa98f369d98a9809d773bc45329aa>.
      83       But the resulting values for these characters are not of good quality.  */
      84    return wcwidth (wc);
      85  # else
      86    if (wc == (wchar_t) wc)
      87      /* wc is in the range for the wcwidth function.  */
      88      return wcwidth (wc);
      89    else
      90      return uc_width (wc, locale_charset ());
      91  # endif
      92  
      93  #else /* macOS, FreeBSD, NetBSD, OpenBSD, HP-UX, Solaris, Minix, Android */
      94    /* char32_t and wchar_t are equivalent.  */
      95    static_assert (sizeof (char32_t) == sizeof (wchar_t));
      96  
      97  # if GL_CHAR32_T_IS_UNICODE && GL_CHAR32_T_VS_WCHAR_T_NEEDS_CONVERSION
      98    return uc_width (wc, locale_charset ());
      99  # endif
     100    return wcwidth (wc);
     101  #endif
     102  }