tuklib_mbstr_width.c revision 213688
1213688Smm/////////////////////////////////////////////////////////////////////////////// 2213688Smm// 3213688Smm/// \file tuklib_mstr_width.c 4213688Smm/// \brief Calculate width of a multibyte string 5213688Smm// 6213688Smm// Author: Lasse Collin 7213688Smm// 8213688Smm// This file has been put into the public domain. 9213688Smm// You can do whatever you want with this file. 10213688Smm// 11213688Smm/////////////////////////////////////////////////////////////////////////////// 12213688Smm 13213688Smm#include "tuklib_mbstr.h" 14213688Smm 15213688Smm#if defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH) 16213688Smm# include <wchar.h> 17213688Smm#endif 18213688Smm 19213688Smm 20213688Smmextern size_t 21213688Smmtuklib_mbstr_width(const char *str, size_t *bytes) 22213688Smm{ 23213688Smm const size_t len = strlen(str); 24213688Smm if (bytes != NULL) 25213688Smm *bytes = len; 26213688Smm 27213688Smm#if !(defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH)) 28213688Smm // In single-byte mode, the width of the string is the same 29213688Smm // as its length. 30213688Smm return len; 31213688Smm 32213688Smm#else 33213688Smm mbstate_t state; 34213688Smm memset(&state, 0, sizeof(state)); 35213688Smm 36213688Smm size_t width = 0; 37213688Smm size_t i = 0; 38213688Smm 39213688Smm // Convert one multibyte character at a time to wchar_t 40213688Smm // and get its width using wcwidth(). 41213688Smm while (i < len) { 42213688Smm wchar_t wc; 43213688Smm const size_t ret = mbrtowc(&wc, str + i, len - i, &state); 44213688Smm if (ret < 1 || ret > len) 45213688Smm return (size_t)-1; 46213688Smm 47213688Smm i += ret; 48213688Smm 49213688Smm const int wc_width = wcwidth(wc); 50213688Smm if (wc_width < 0) 51213688Smm return (size_t)-1; 52213688Smm 53213688Smm width += wc_width; 54213688Smm } 55213688Smm 56213688Smm // Require that the string ends in the initial shift state. 57213688Smm // This way the caller can be combine the string with other 58213688Smm // strings without needing to worry about the shift states. 59213688Smm if (!mbsinit(&state)) 60213688Smm return (size_t)-1; 61213688Smm 62213688Smm return width; 63213688Smm#endif 64213688Smm} 65