// // aegis - project change supervisor // Copyright (C) 1996, 1999, 2004-2008 Peter Miller // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see // . // #include #include #include #ifndef HAVE_WCSLEN size_t wcslen(const wchar_t *wcs) { const wchar_t *start; start = wcs; while (*wcs) ++wcs; return (wcs - start); } #endif // !HAVE_WCSLEN // // NAME // column_width - determine column width of a wide character // // SYNOPSIS // int column_width(wint_t); // // DESCRIPTION // The column_width function is used to determine the column width // if a wide character. This is particularly hard to do, // especially if you have read the ISO C standard ammendments. // // WEASEL WORDS // This is the phrase used by P.J. Plauger in his CUJ columns about // standard C and C++, specially when the standard dances all // around the issue, rather than actually solving anything. Take a // squiz at these classic weasel words... // // In the original standard, ISO/IEC 9899:1990, 7.3 Character // handling reads as follows (3rd paragraph): // // The term printing character refers to a member of // an implemntation defined set of characters, each of // which occupies one printing position on a display // device; the term control character refers to a // member of an implementation defined set of characters // that are not printing characters. // // The following 2 sections are from ISO/IEC 9899:1990/Amd. 1:1995 (E): // // 7.15.2 Wide-character classification utilities (2nd paragraph) // // The term printing wide character refers to a // member of a locale-specific set of wide characters, each // of which occupies at least one printing position on a // display device; the term control wide character // refers to a member of a locale-specific set of wide // characters that are not printing wide characters. // // [ Notice how they weasel out by not-quite contradicting 7.3: a // printing char is exactly one printing position wide, but // a printing wchar_t is one or more printing positions // wide. ] // // H.14 Column width // // The number of characters to be read or written can be // specified in existing formatted i/o functions. On a // traditional display device that displays characters with // fixed pitch, the number of characters is directly // proportional to the width occupied by the characters. // So the display format can be specified through the field // width and/or the precision. // // In formatted wide-character i/o functions, the field // width and the precision specify the number of wide // characters to be read or written. The number of wide // characters is not always directly proportional to the // width of their display. For example, with Japanese // traditional display devices, a single-byte character // such as an ASCII character has half the width of a Kanji // character, even though each of them is treated as one // wide character. To control the display format for wide // characters, a set of formatted wide-character i/o // functions were proposed whose metric was the column // width instead of the character count. // // This proposal was supported only by Japan. Critics // observed that the proposal was based on such traditional // display devices with a fixed width of characters, while // many modern display devices support a broad assortment // of proportional pitch type faces. Hence, it was // questioned whether the extra i/o functions in this // proposal were really needed or were sufficiently // general. Also considered were another set of functions // that return the column width for any kind of display // devices for a given wide-character string; but these // seemed to be beyond the scope of the C language. Thus // all proposals regarding column width were withdrawn. // // [ Notice how 7.15.2 specifically states that each printing // character has a non-zero width measurable in printing // positions. Why is this metric is unavailable to the // C programmer? Presumably it is OK for an informational appendix // to contradict the body of the standard. ] // // [ The section ends with a compliant-but-non-standard way a // standard C library implementor may choose to do this. You can't // rely on it being there, and you can't rely on the suggested // semantics being used, so don't even bother having ./configure go // look for it. ] // // SO FAKE IT // Since there is no standard way to determine character width, we // will have to fake it. Hopefully, locales that need it will // define something useful. If you know of any, please let me // know. // // The wcwidth and wcswidth functions are extensions found in // X/Open CAE. So, we use the same function names as they did, // when we need to fake it (which is all of the time, if you don't // have glibc). // #include #include #if !HAVE_WCWIDTH extern "C" int wcwidth(wchar_t wc) { #if HAVE_ISWCTYPE && HAVE_WCTYPE_H static int kanji_set; static wctype_t kanji; if (!kanji_set) { kanji = wctype("kanji"); kanji_set = 1; } if (kanji && iswctype(kanji, wc)) return 2; #else (void)wc; #endif return 1; } #endif // HAVE_WCWIDTH #if !HAVE_WCSWIDTH extern "C" int wcswidth(const wchar_t *wcs, size_t n) { int result = 0; while (*wcs && n > 0) { result += wcwidth(*wcs++); --n; } return result; } #endif // HAVE_WCSWIDTH #if !HAVE_MBRTOWC extern "C" size_t mbrtowc(wchar_t *pwc, const char *s, size_t n, mbstate_t *) { return mbtowc(pwc, s, n); } #endif // HAVE_WCSWIDTH #if !HAVE_WCRTOMB extern "C" size_t wcrtomb(char *s, wchar_t wc, mbstate_t *) { return wctomb(s, wc); } #endif // HAVE_WCRTOMB