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