]>
Commit | Line | Data |
---|---|---|
b75a7d8f A |
1 | /* |
2 | ********************************************************************** | |
2ca993e8 | 3 | * Copyright (C) 1998-2016, International Business Machines Corporation |
b75a7d8f A |
4 | * and others. All Rights Reserved. |
5 | ********************************************************************** | |
6 | * | |
7 | * File uwmsg.c | |
8 | * | |
9 | * Modification History: | |
10 | * | |
11 | * Date Name Description | |
12 | * 06/14/99 stephen Creation. | |
13 | ******************************************************************************* | |
14 | */ | |
15 | ||
16 | #include "unicode/ucnv.h" | |
17 | #include "unicode/ustring.h" | |
18 | #include "unicode/umsg.h" | |
19 | #include "unicode/uwmsg.h" | |
20 | #include "unicode/ures.h" | |
374ca955 | 21 | #include "unicode/putil.h" |
2ca993e8 | 22 | #include "cmemory.h" |
b75a7d8f A |
23 | #include "cstring.h" |
24 | ||
25 | #include <stdlib.h> | |
26 | #include <stdarg.h> | |
27 | #include <stdio.h> | |
28 | #include <string.h> | |
29 | ||
b75a7d8f A |
30 | #define BUF_SIZE 128 |
31 | ||
32 | /* Print a ustring to the specified FILE* in the default codepage */ | |
33 | static void | |
34 | uprint(const UChar *s, | |
35 | int32_t sourceLen, | |
36 | FILE *f, | |
37 | UErrorCode *status) | |
38 | { | |
39 | /* converter */ | |
40 | UConverter *converter; | |
41 | char buf [BUF_SIZE]; | |
42 | const UChar *mySource; | |
43 | const UChar *mySourceEnd; | |
44 | char *myTarget; | |
45 | int32_t arraySize; | |
46 | ||
47 | if(s == 0) return; | |
48 | ||
49 | /* set up the conversion parameters */ | |
50 | mySource = s; | |
51 | mySourceEnd = mySource + sourceLen; | |
52 | myTarget = buf; | |
53 | arraySize = BUF_SIZE; | |
54 | ||
55 | /* open a default converter */ | |
56 | converter = ucnv_open(0, status); | |
57 | ||
58 | /* if we failed, clean up and exit */ | |
59 | if(U_FAILURE(*status)) goto finish; | |
60 | ||
61 | /* perform the conversion */ | |
62 | do { | |
63 | /* reset the error code */ | |
64 | *status = U_ZERO_ERROR; | |
65 | ||
66 | /* perform the conversion */ | |
67 | ucnv_fromUnicode(converter, &myTarget, myTarget + arraySize, | |
68 | &mySource, mySourceEnd, NULL, | |
69 | TRUE, status); | |
70 | ||
71 | /* Write the converted data to the FILE* */ | |
72 | fwrite(buf, sizeof(char), myTarget - buf, f); | |
73 | ||
74 | /* update the conversion parameters*/ | |
75 | myTarget = buf; | |
76 | arraySize = BUF_SIZE; | |
77 | } | |
78 | while(*status == U_BUFFER_OVERFLOW_ERROR); | |
79 | ||
80 | finish: | |
81 | ||
82 | /* close the converter */ | |
83 | ucnv_close(converter); | |
84 | } | |
85 | ||
b75a7d8f A |
86 | static UResourceBundle *gBundle = NULL; |
87 | ||
88 | U_STRING_DECL(gNoFormatting, " (UCONFIG_NO_FORMATTING see uconfig.h)", 38); | |
89 | ||
374ca955 | 90 | U_CFUNC UResourceBundle *u_wmsg_setPath(const char *path, UErrorCode *err) |
b75a7d8f A |
91 | { |
92 | if(U_FAILURE(*err)) | |
93 | { | |
94 | return 0; | |
95 | } | |
96 | ||
97 | if(gBundle != NULL) | |
98 | { | |
99 | *err = U_ILLEGAL_ARGUMENT_ERROR; | |
100 | return 0; | |
101 | } | |
102 | else | |
103 | { | |
104 | UResourceBundle *b = NULL; | |
105 | b = ures_open(path, NULL, err); | |
106 | if(U_FAILURE(*err)) | |
107 | { | |
108 | return 0; | |
109 | } | |
110 | ||
b75a7d8f A |
111 | gBundle = b; |
112 | ||
113 | U_STRING_INIT(gNoFormatting, " (UCONFIG_NO_FORMATTING see uconfig.h)", 38); | |
114 | } | |
115 | ||
116 | return gBundle; | |
117 | } | |
118 | ||
119 | /* Format a message and print it's output to fp */ | |
374ca955 | 120 | U_CFUNC int u_wmsg(FILE *fp, const char *tag, ... ) |
b75a7d8f A |
121 | { |
122 | const UChar *msg; | |
123 | int32_t msgLen; | |
124 | UErrorCode err = U_ZERO_ERROR; | |
125 | #if !UCONFIG_NO_FORMATTING | |
126 | va_list ap; | |
127 | #endif | |
128 | UChar result[4096]; | |
b331163b | 129 | int32_t resultLength = UPRV_LENGTHOF(result); |
b75a7d8f A |
130 | |
131 | if(gBundle == NULL) | |
132 | { | |
133 | #if 0 | |
134 | fprintf(stderr, "u_wmsg: No path set!!\n"); /* FIXME: codepage?? */ | |
135 | #endif | |
136 | return -1; | |
137 | } | |
138 | ||
139 | msg = ures_getStringByKey(gBundle, tag, &msgLen, &err); | |
140 | ||
141 | if(U_FAILURE(err)) | |
142 | { | |
b75a7d8f A |
143 | return -1; |
144 | } | |
145 | ||
146 | #if UCONFIG_NO_FORMATTING | |
2ca993e8 | 147 | resultLength = UPRV_LENGTHOF(gNoFormatting); |
b331163b | 148 | if((msgLen + resultLength) <= UPRV_LENGTHOF(result)) { |
b75a7d8f A |
149 | memcpy(result, msg, msgLen * U_SIZEOF_UCHAR); |
150 | memcpy(result + msgLen, gNoFormatting, resultLength); | |
151 | resultLength += msgLen; | |
152 | uprint(result, resultLength, fp, &err); | |
153 | } else { | |
154 | uprint(msg,msgLen, fp, &err); | |
155 | } | |
156 | #else | |
157 | va_start(ap, tag); | |
158 | ||
159 | resultLength = u_vformatMessage(uloc_getDefault(), msg, msgLen, result, resultLength, ap, &err); | |
160 | ||
161 | va_end(ap); | |
162 | ||
163 | if(U_FAILURE(err)) | |
164 | { | |
165 | #if 0 | |
166 | fprintf(stderr, "u_wmsg: failed to format %s:%s, err %s\n", | |
167 | uloc_getDefault(), | |
168 | tag, | |
169 | u_errorName(err)); | |
170 | #endif | |
171 | err = U_ZERO_ERROR; | |
172 | uprint(msg,msgLen, fp, &err); | |
173 | return -1; | |
174 | } | |
175 | ||
176 | uprint(result, resultLength, fp, &err); | |
177 | #endif | |
178 | ||
179 | if(U_FAILURE(err)) | |
180 | { | |
181 | #if 0 | |
182 | fprintf(stderr, "u_wmsg: failed to print %s: %s, err %s\n", | |
183 | uloc_getDefault(), | |
184 | tag, | |
185 | u_errorName(err)); | |
186 | #endif | |
187 | return -1; | |
188 | } | |
189 | ||
190 | return 0; | |
191 | } | |
192 | ||
193 | /* these will break if the # of messages change. simply add or remove 0's .. */ | |
374ca955 | 194 | UChar **gInfoMessages = NULL; |
b75a7d8f | 195 | |
374ca955 | 196 | UChar **gErrMessages = NULL; |
b75a7d8f A |
197 | |
198 | static const UChar *fetchErrorName(UErrorCode err) | |
199 | { | |
374ca955 A |
200 | if (!gInfoMessages) { |
201 | gInfoMessages = (UChar **)malloc((U_ERROR_WARNING_LIMIT-U_ERROR_WARNING_START)*sizeof(UChar*)); | |
202 | memset(gInfoMessages, 0, (U_ERROR_WARNING_LIMIT-U_ERROR_WARNING_START)*sizeof(UChar*)); | |
203 | } | |
204 | if (!gErrMessages) { | |
205 | gErrMessages = (UChar **)malloc(U_ERROR_LIMIT*sizeof(UChar*)); | |
206 | memset(gErrMessages, 0, U_ERROR_LIMIT*sizeof(UChar*)); | |
207 | } | |
b75a7d8f A |
208 | if(err>=0) |
209 | return gErrMessages[err]; | |
210 | else | |
211 | return gInfoMessages[err-U_ERROR_WARNING_START]; | |
212 | } | |
213 | ||
374ca955 | 214 | U_CFUNC const UChar *u_wmsg_errorName(UErrorCode err) |
b75a7d8f A |
215 | { |
216 | UChar *msg; | |
217 | int32_t msgLen; | |
218 | UErrorCode subErr = U_ZERO_ERROR; | |
219 | const char *textMsg = NULL; | |
220 | ||
221 | /* try the cache */ | |
222 | msg = (UChar*)fetchErrorName(err); | |
223 | ||
224 | if(msg) | |
225 | { | |
226 | return msg; | |
227 | } | |
228 | ||
229 | if(gBundle == NULL) | |
230 | { | |
231 | msg = NULL; | |
232 | } | |
233 | else | |
234 | { | |
235 | const char *errname = u_errorName(err); | |
236 | if (errname) { | |
237 | msg = (UChar*)ures_getStringByKey(gBundle, errname, &msgLen, &subErr); | |
238 | if(U_FAILURE(subErr)) | |
239 | { | |
240 | msg = NULL; | |
241 | } | |
242 | } | |
243 | } | |
244 | ||
245 | if(msg == NULL) /* Couldn't find it anywhere.. */ | |
246 | { | |
247 | char error[128]; | |
248 | textMsg = u_errorName(err); | |
249 | if (!textMsg) { | |
250 | sprintf(error, "UNDOCUMENTED ICU ERROR %d", err); | |
251 | textMsg = error; | |
252 | } | |
253 | msg = (UChar*)malloc((strlen(textMsg)+1)*sizeof(msg[0])); | |
254 | u_charsToUChars(textMsg, msg, (int32_t)(strlen(textMsg)+1)); | |
255 | } | |
256 | ||
257 | if(err>=0) | |
258 | gErrMessages[err] = msg; | |
259 | else | |
260 | gInfoMessages[err-U_ERROR_WARNING_START] = msg; | |
261 | ||
262 | return msg; | |
263 | } |