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 
28 int 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 
98 int 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 
113 int 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);
134  bufLen=GWEN_Buffer_GetMaxUnsegmentedWrite(tbuf)-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);
143  bufLen=GWEN_Buffer_GetMaxUnsegmentedWrite(tbuf)-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 
183 int 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 
210 void 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 
GWENHYWFAR_API const char * fmt
Definition: buffer.h:283
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
uint32_t GWEN_Buffer_GetMaxUnsegmentedWrite(GWEN_BUFFER *bf)
Definition: buffer.c:528
int GWEN_Gui_ConvertFromUtf8(const GWEN_GUI *gui, const char *text, int len, GWEN_BUFFER *tbuf)
Definition: gui_utils.c:98
void GWEN_Gui_GetRawText(GWEN_UNUSED const GWEN_GUI *gui, const char *text, GWEN_BUFFER *tbuf)
Definition: gui_utils.c:210
int GWEN_Buffer_AdjustUsedBytes(GWEN_BUFFER *bf)
Definition: buffer.c:469
#define GWEN_LOGDOMAIN
Definition: logger.h:35
GWEN_BUFFER * GWEN_Buffer_new(char *buffer, uint32_t size, uint32_t used, int take)
Definition: buffer.c:42
int GWEN_Gui_StdPrintf(const GWEN_GUI *gui, FILE *stream, const char *fmt,...)
Definition: gui_utils.c:113
char * GWEN_Buffer_GetPosPointer(const GWEN_BUFFER *bf)
Definition: buffer.c:549
int GWEN_Buffer_IncrementPos(GWEN_BUFFER *bf, uint32_t i)
Definition: buffer.c:452
#define DBG_DEBUG(dbg_logger, format, args...)
Definition: debug.h:214
GWEN_GUI * GWEN_Gui_GetGui(void)
Definition: gui.c:160
#define GWEN_ERROR_GENERIC
Definition: error.h:62
int GWEN_Gui_ConvertString(const char *text, size_t len, GWEN_BUFFER *tbuf, const char *fromCs, const char *toCs)
Definition: gui_utils.c:28
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition: buffer.c:89
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition: buffer.h:38
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
int GWEN_Buffer_SetPos(GWEN_BUFFER *bf, uint32_t i)
Definition: buffer.c:261
#define ICONV_CONST
Definition: cgui.c:64
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:181
struct GWEN_GUI GWEN_GUI
Definition: gui.h:176
int GWEN_Buffer_AppendBytes(GWEN_BUFFER *bf, const char *buffer, uint32_t size)
Definition: buffer.c:361
int GWEN_Gui_ReadString(const char *text, GWEN_BUFFER *tbuf)
Definition: gui_utils.c:183
#define GWEN_UNUSED
int GWEN_Buffer_AppendString(GWEN_BUFFER *bf, const char *buffer)
Definition: buffer.c:989