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 : : }
|