gwenhywfar 5.10.1
gui_utils.c
Go to the documentation of this file.
1/***************************************************************************
2 begin : Fri Feb 07 2003
3 copyright : (C) 2021 by Martin Preuss
4 email : martin@libchipcard.de
5
6 ***************************************************************************
7 * *
8 * This library is free software; you can redistribute it and/or *
9 * modify it under the terms of the GNU Lesser General Public *
10 * License as published by the Free Software Foundation; either *
11 * version 2.1 of the License, or (at your option) any later version. *
12 * *
13 * This library 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 GNU *
16 * Lesser General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU Lesser General Public *
19 * License along with this library; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 * *
23 ***************************************************************************/
24
25/* included from gui.c */
26
27
28int GWEN_Gui_ConvertString(const char *text, size_t len, GWEN_BUFFER *tbuf,
29 const char *fromCs, const char *toCs)
30{
31#ifdef HAVE_ICONV
32 int rv=0;
33 iconv_t ic;
34
35 assert(tbuf);
36
37 ic=iconv_open(toCs, fromCs);
38 if (ic==(iconv_t)-1) {
39 DBG_ERROR(GWEN_LOGDOMAIN, "Cannot convert from \"%s\" to \"%s\", %s",
40 fromCs, toCs, strerror(errno));
42 }
43 else {
44 /* Some systems have iconv in libc, some have it in libiconv
45 (OSF/1 and those with the standalone portable GNU libiconv
46 installed). Check which one is available. The define
47 ICONV_CONST will be "" or "const" accordingly. */
48 ICONV_CONST char *pInbuf;
49 char *pOutbuf;
50 size_t inLeft;
51 size_t outLeft;
52 size_t done;
53 size_t space;
54
55 /* convert */
56 pInbuf=(char *)text;
57 inLeft=len;
59 space=outLeft;
60 retry:
61 pOutbuf=GWEN_Buffer_GetPosPointer(tbuf);
62 done=iconv(ic, &pInbuf, &inLeft, &pOutbuf, &outLeft);
63 GWEN_Buffer_SetPos(tbuf, space-outLeft);
65 if (done==(size_t)-1) {
66 if (errno==E2BIG) {
67 uint32_t room;
68
69 room=2*inLeft;
70 if (room<=outLeft)
71 room+=outLeft;
72 GWEN_Buffer_AllocRoom(tbuf, room);
73 /* How much additional room has actually been allocated? */
74 room=GWEN_Buffer_GetMaxUnsegmentedWrite(tbuf)-outLeft;
75 outLeft+=room;
76 space+=room;
77 goto retry;
78 }
79
80 DBG_ERROR(GWEN_LOGDOMAIN, "Error in conversion: %s (%d)",
81 strerror(errno), errno);
83 }
84 else {
85 DBG_DEBUG(GWEN_LOGDOMAIN, "Conversion done.");
86 }
87 iconv_close(ic);
88 }
89
90 return rv;
91#else /* !HAVE_ICONV */
92 return GWEN_Buffer_AppendBytes(tbuf, text, len);
93#endif
94}
95
96
97
98int GWEN_Gui_ConvertFromUtf8(const GWEN_GUI *gui, const char *text, int len, GWEN_BUFFER *tbuf)
99{
100 int rv;
101
102 rv=GWEN_Gui_ConvertString(text, len, tbuf, "UTF-8", gui->charSet);
103 if (rv<0) {
104 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
105 return rv;
106 }
107
108 return 0;
109}
110
111
112
113int GWEN_Gui_StdPrintf(const GWEN_GUI *gui, FILE *stream,
114 const char *fmt, ...)
115{
116 va_list args;
117 int rv;
118
119 assert(gui);
120
121 va_start(args, fmt);
122#ifndef HAVE_ICONV
123 rv=vfprintf(stream, fmt, args);
124#else
125 if (!gui->charSet)
126 rv=vfprintf(stream, fmt, args);
127 else {
128 GWEN_BUFFER *tbuf;
129 GWEN_BUFFER *outbuf;
130 int bufLen;
131 size_t spaceNeeded;
132
133 tbuf=GWEN_Buffer_new(0, 256, 0, 1);
135 spaceNeeded=vsnprintf(GWEN_Buffer_GetStart(tbuf), bufLen, fmt, args);
136 if (spaceNeeded==(size_t) -1) {
137 fprintf(stderr, "GWEN INTERNAL ERROR: vsnprintf returned -1 on fmt=\"%s\"?\n", fmt);
138 va_end(args);
139 return EOF;
140 }
141 if (spaceNeeded>=bufLen) {
142 GWEN_Buffer_AllocRoom(tbuf, spaceNeeded+1);
144 va_end(args);
145 va_start(args, fmt);
146 //vsprintf(GWEN_Buffer_GetStart(tbuf), fmt, args);
147 spaceNeeded=vsnprintf(GWEN_Buffer_GetStart(tbuf), bufLen, fmt, args);
148 if (spaceNeeded>=bufLen) {
149 fprintf(stderr, "GWEN INTERNAL ERROR: Still not enough space (%lu >=%lu)? SNH!\n",
150 (long unsigned int) spaceNeeded, (long unsigned int) bufLen);
151 assert(spaceNeeded<bufLen);
152 }
153 }
154 GWEN_Buffer_IncrementPos(tbuf, spaceNeeded);
156
157 outbuf=GWEN_Buffer_new(0, 2*spaceNeeded, 0, 1);
158 rv=GWEN_Gui_ConvertString(GWEN_Buffer_GetStart(tbuf), spaceNeeded,
159 outbuf, "UTF-8", gui->charSet);
160 if (rv) {
161 GWEN_Buffer_free(outbuf);
162 outbuf=tbuf;
163 }
164 else
165 GWEN_Buffer_free(tbuf);
166
167 /* let's try to return the same value as fprintf() would */
168 if (fputs(GWEN_Buffer_GetStart(outbuf), stderr)!=EOF)
169 rv=spaceNeeded;
170 else
171 rv=EOF;
172
173 GWEN_Buffer_free(outbuf);
174 }
175#endif
176
177 va_end(args);
178 return rv;
179}
180
181
182
183int GWEN_Gui_ReadString(const char *text, GWEN_BUFFER *tbuf)
184{
185#ifdef HAVE_ICONV
186 GWEN_GUI *gui;
187
188 gui=GWEN_Gui_GetGui();
189 if (gui) {
190 const char *fromCs;
191
192 if (gui->charSet)
193 fromCs=gui->charSet;
194 else
195 /* UTF-8 to UTF-8 conversion does not seem to make much sense, but
196 * it is a convenient way to check whether the input text actually
197 * is properly UTF-8 encoded.
198 */
199 fromCs="UTF-8";
200
201 return GWEN_Gui_ConvertString(text, strlen(text), tbuf, fromCs, "UTF-8");
202 }
203 else
204#endif /* HAVE_ICONV */
205 return GWEN_Buffer_AppendString(tbuf, text);
206}
207
208
209
210void GWEN_Gui_GetRawText(GWEN_UNUSED const GWEN_GUI *gui, const char *text, GWEN_BUFFER *tbuf)
211{
212 size_t len;
213 const char *p;
214
215 assert(text);
216 p=text;
217 while ((p=strchr(p, '<'))) {
218 const char *t;
219
220 t=p;
221 t++;
222 if (toupper(*t)=='H') {
223 t++;
224 if (toupper(*t)=='T') {
225 t++;
226 if (toupper(*t)=='M') {
227 t++;
228 if (toupper(*t)=='L') {
229 break;
230 }
231 }
232 }
233 }
234 p++;
235 } /* while */
236
237 if (p)
238 len=p-text;
239 else
240 len=strlen(text);
241 GWEN_Buffer_AppendBytes(tbuf, text, len);
242}
243
244
245
GWEN_BUFFER * GWEN_Buffer_new(char *buffer, uint32_t size, uint32_t used, int take)
Definition: buffer.c:42
int GWEN_Buffer_IncrementPos(GWEN_BUFFER *bf, uint32_t i)
Definition: buffer.c:452
uint32_t GWEN_Buffer_GetMaxUnsegmentedWrite(GWEN_BUFFER *bf)
Definition: buffer.c:528
int GWEN_Buffer_SetPos(GWEN_BUFFER *bf, uint32_t i)
Definition: buffer.c:261
int GWEN_Buffer_AdjustUsedBytes(GWEN_BUFFER *bf)
Definition: buffer.c:469
char * GWEN_Buffer_GetPosPointer(const GWEN_BUFFER *bf)
Definition: buffer.c:549
int GWEN_Buffer_AppendBytes(GWEN_BUFFER *bf, const char *buffer, uint32_t size)
Definition: buffer.c:361
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition: buffer.c:89
int GWEN_Buffer_AppendString(GWEN_BUFFER *bf, const char *buffer)
Definition: buffer.c:989
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition: buffer.c:235
int GWEN_Buffer_AllocRoom(GWEN_BUFFER *bf, uint32_t size)
Definition: buffer.c:285
GWENHYWFAR_API const char * fmt
Definition: buffer.h:283
#define ICONV_CONST
Definition: cgui.c:64
#define DBG_DEBUG(dbg_logger, format, args...)
Definition: debug.h:214
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:181
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
#define GWEN_ERROR_GENERIC
Definition: error.h:62
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition: buffer.h:38
GWEN_GUI * GWEN_Gui_GetGui(void)
Definition: gui.c:160
struct GWEN_GUI GWEN_GUI
Definition: gui.h:176
int GWEN_Gui_ReadString(const char *text, GWEN_BUFFER *tbuf)
Definition: gui_utils.c:183
int GWEN_Gui_ConvertString(const char *text, size_t len, GWEN_BUFFER *tbuf, const char *fromCs, const char *toCs)
Definition: gui_utils.c:28
int GWEN_Gui_ConvertFromUtf8(const GWEN_GUI *gui, const char *text, int len, GWEN_BUFFER *tbuf)
Definition: gui_utils.c:98
int GWEN_Gui_StdPrintf(const GWEN_GUI *gui, FILE *stream, const char *fmt,...)
Definition: gui_utils.c:113
void GWEN_Gui_GetRawText(GWEN_UNUSED const GWEN_GUI *gui, const char *text, GWEN_BUFFER *tbuf)
Definition: gui_utils.c:210
#define GWEN_UNUSED
#define GWEN_LOGDOMAIN
Definition: logger.h:35