Branch data Line data Source code
1 : : /* 2 : : * libdpkg - Debian packaging suite library routines 3 : : * strwide.c - wide character string handling routines 4 : : * 5 : : * Copyright © 2004 Changwoo Ryu <cwryu@debian.org> 6 : : * Copyright © 2012-2013 Guillem Jover <guillem@debian.org> 7 : : * 8 : : * This is free software; you can redistribute it and/or modify 9 : : * it under the terms of the GNU General Public License as published by 10 : : * the Free Software Foundation; either version 2 of the License, or 11 : : * (at your option) any later version. 12 : : * 13 : : * This is distributed in the hope that it will be useful, 14 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 : : * GNU General Public License for more details. 17 : : * 18 : : * You should have received a copy of the GNU General Public License 19 : : * along with this program. If not, see <https://www.gnu.org/licenses/>. 20 : : */ 21 : : 22 : : #include <config.h> 23 : : #include <compat.h> 24 : : 25 : : #include <string.h> 26 : : #include <stdlib.h> 27 : : #ifdef ENABLE_NLS 28 : : #include <wchar.h> 29 : : #endif 30 : : 31 : : #include <dpkg/i18n.h> 32 : : #include <dpkg/dpkg.h> 33 : : #include <dpkg/string.h> 34 : : 35 : : /** 36 : : * Compute the screen width of a string. 37 : : * 38 : : * @param str The multibyte string. 39 : : * 40 : : * @return The width of the string. 41 : : */ 42 : : int 43 : 0 : str_width(const char *str) 44 : : { 45 : : #ifdef ENABLE_NLS 46 : : mbstate_t state; 47 : : wchar_t *wcs; 48 : 0 : const char *mbs = str; 49 : : size_t len, res; 50 : : int width; 51 : : 52 : 0 : len = strlen(str) + 1; 53 : 0 : wcs = m_malloc(sizeof(wcs[0]) * len); 54 : : 55 : 0 : memset(&state, 0, sizeof(state)); 56 : : 57 : 0 : res = mbsrtowcs(wcs, &mbs, len, &state); 58 [ # # ]: 0 : if (res == (size_t)-1) { 59 : : #ifdef DPKG_UNIFORM_ENCODING 60 : : ohshit(_("cannot convert multibyte string '%s' " 61 : : "to a wide-character string"), str); 62 : : #else 63 : : /* Cannot convert, fallback to ASCII method. */ 64 : 0 : free(wcs); 65 : 0 : return strlen(str); 66 : : #endif 67 : : } 68 : : 69 : 0 : width = wcswidth(wcs, res); 70 : : 71 : 0 : free(wcs); 72 : : 73 : 0 : return width; 74 : : #else 75 : : return strlen(str); 76 : : #endif 77 : : } 78 : : 79 : : /** 80 : : * Generate the crop values for a string given a maximum screen width. 81 : : * 82 : : * This function analyzes the string passed and computes the correct point 83 : : * where to crop the string, returning the amount of string and maximum 84 : : * bytes to use for padding for example. 85 : : * 86 : : * On NLS enabled builds, in addition the string will be cropped on any 87 : : * newline. 88 : : * 89 : : * @param str The string to crop. 90 : : * @param max_width The max screen width to use. 91 : : * @param[out] crop The generated crop values for the string. 92 : : */ 93 : : void 94 : 0 : str_gen_crop(const char *str, int max_width, struct str_crop_info *crop) 95 : : { 96 : : #ifdef ENABLE_NLS 97 : : mbstate_t state; 98 : : size_t str_bytes; 99 : 0 : int mbs_bytes = 0; 100 : 0 : int mbs_width = 0; 101 : : 102 : 0 : str_bytes = strlen(str) + 1; 103 : 0 : memset(&state, 0, sizeof(state)); 104 : : 105 : 0 : for (;;) { 106 : : wchar_t wc; 107 : : int wc_width; 108 : : size_t mb_bytes; 109 : : 110 : 0 : mb_bytes = mbrtowc(&wc, str, str_bytes, &state); 111 [ # # # # ]: 0 : if (mb_bytes == (size_t)-1 || mb_bytes == (size_t)-2) { 112 : : #ifdef DPKG_UNIFORM_ENCODING 113 : : ohshit(_("cannot convert multibyte sequence '%s' " 114 : : "to a wide character"), str); 115 : : #else 116 : : /* Cannot convert, fallback to ASCII method. */ 117 : 0 : crop->str_bytes = crop->max_bytes = max_width; 118 : 0 : return; 119 : : #endif 120 : : } 121 [ # # ]: 0 : if (mb_bytes == 0) 122 : 0 : break; 123 : : 124 : 0 : wc_width = wcwidth(wc); 125 [ # # ]: 0 : if (wc_width < 0) 126 : 0 : break; 127 [ # # ]: 0 : if (mbs_width + wc_width > max_width) 128 : 0 : break; 129 : : 130 : 0 : mbs_width += wc_width; 131 : 0 : mbs_bytes += mb_bytes; 132 : 0 : str_bytes -= mb_bytes; 133 : 0 : str += mb_bytes; 134 : : } 135 : : 136 : 0 : crop->str_bytes = mbs_bytes; 137 : 0 : crop->max_bytes = mbs_bytes + max_width - mbs_width; 138 : : #else 139 : : crop->str_bytes = crop->max_bytes = max_width; 140 : : #endif 141 : : }