]>
Commit | Line | Data |
---|---|---|
b75a7d8f A |
1 | /* |
2 | ********************************************************************** | |
51004dcb | 3 | * Copyright (C) 1998-2012, 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" |
b75a7d8f A |
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 | ||
b75a7d8f A |
87 | static UResourceBundle *gBundle = NULL; |
88 | ||
89 | U_STRING_DECL(gNoFormatting, " (UCONFIG_NO_FORMATTING see uconfig.h)", 38); | |
90 | ||
374ca955 | 91 | U_CFUNC UResourceBundle *u_wmsg_setPath(const char *path, UErrorCode *err) |
b75a7d8f A |
92 | { |
93 | if(U_FAILURE(*err)) | |
94 | { | |
95 | return 0; | |
96 | } | |
97 | ||
98 | if(gBundle != NULL) | |
99 | { | |
100 | *err = U_ILLEGAL_ARGUMENT_ERROR; | |
101 | return 0; | |
102 | } | |
103 | else | |
104 | { | |
105 | UResourceBundle *b = NULL; | |
106 | b = ures_open(path, NULL, err); | |
107 | if(U_FAILURE(*err)) | |
108 | { | |
109 | return 0; | |
110 | } | |
111 | ||
b75a7d8f A |
112 | gBundle = b; |
113 | ||
114 | U_STRING_INIT(gNoFormatting, " (UCONFIG_NO_FORMATTING see uconfig.h)", 38); | |
115 | } | |
116 | ||
117 | return gBundle; | |
118 | } | |
119 | ||
120 | /* Format a message and print it's output to fp */ | |
374ca955 | 121 | U_CFUNC int u_wmsg(FILE *fp, const char *tag, ... ) |
b75a7d8f A |
122 | { |
123 | const UChar *msg; | |
124 | int32_t msgLen; | |
125 | UErrorCode err = U_ZERO_ERROR; | |
126 | #if !UCONFIG_NO_FORMATTING | |
127 | va_list ap; | |
128 | #endif | |
129 | UChar result[4096]; | |
130 | int32_t resultLength = LENGTHOF(result); | |
131 | ||
132 | if(gBundle == NULL) | |
133 | { | |
134 | #if 0 | |
135 | fprintf(stderr, "u_wmsg: No path set!!\n"); /* FIXME: codepage?? */ | |
136 | #endif | |
137 | return -1; | |
138 | } | |
139 | ||
140 | msg = ures_getStringByKey(gBundle, tag, &msgLen, &err); | |
141 | ||
142 | if(U_FAILURE(err)) | |
143 | { | |
b75a7d8f A |
144 | return -1; |
145 | } | |
146 | ||
147 | #if UCONFIG_NO_FORMATTING | |
148 | resultLength = sizeof(gNoFormatting) / U_SIZEOF_UCHAR; | |
149 | if((msgLen + resultLength) <= LENGTHOF(result)) { | |
150 | memcpy(result, msg, msgLen * U_SIZEOF_UCHAR); | |
151 | memcpy(result + msgLen, gNoFormatting, resultLength); | |
152 | resultLength += msgLen; | |
153 | uprint(result, resultLength, fp, &err); | |
154 | } else { | |
155 | uprint(msg,msgLen, fp, &err); | |
156 | } | |
157 | #else | |
158 | va_start(ap, tag); | |
159 | ||
160 | resultLength = u_vformatMessage(uloc_getDefault(), msg, msgLen, result, resultLength, ap, &err); | |
161 | ||
162 | va_end(ap); | |
163 | ||
164 | if(U_FAILURE(err)) | |
165 | { | |
166 | #if 0 | |
167 | fprintf(stderr, "u_wmsg: failed to format %s:%s, err %s\n", | |
168 | uloc_getDefault(), | |
169 | tag, | |
170 | u_errorName(err)); | |
171 | #endif | |
172 | err = U_ZERO_ERROR; | |
173 | uprint(msg,msgLen, fp, &err); | |
174 | return -1; | |
175 | } | |
176 | ||
177 | uprint(result, resultLength, fp, &err); | |
178 | #endif | |
179 | ||
180 | if(U_FAILURE(err)) | |
181 | { | |
182 | #if 0 | |
183 | fprintf(stderr, "u_wmsg: failed to print %s: %s, err %s\n", | |
184 | uloc_getDefault(), | |
185 | tag, | |
186 | u_errorName(err)); | |
187 | #endif | |
188 | return -1; | |
189 | } | |
190 | ||
191 | return 0; | |
192 | } | |
193 | ||
194 | /* these will break if the # of messages change. simply add or remove 0's .. */ | |
374ca955 | 195 | UChar **gInfoMessages = NULL; |
b75a7d8f | 196 | |
374ca955 | 197 | UChar **gErrMessages = NULL; |
b75a7d8f A |
198 | |
199 | static const UChar *fetchErrorName(UErrorCode err) | |
200 | { | |
374ca955 A |
201 | if (!gInfoMessages) { |
202 | gInfoMessages = (UChar **)malloc((U_ERROR_WARNING_LIMIT-U_ERROR_WARNING_START)*sizeof(UChar*)); | |
203 | memset(gInfoMessages, 0, (U_ERROR_WARNING_LIMIT-U_ERROR_WARNING_START)*sizeof(UChar*)); | |
204 | } | |
205 | if (!gErrMessages) { | |
206 | gErrMessages = (UChar **)malloc(U_ERROR_LIMIT*sizeof(UChar*)); | |
207 | memset(gErrMessages, 0, U_ERROR_LIMIT*sizeof(UChar*)); | |
208 | } | |
b75a7d8f A |
209 | if(err>=0) |
210 | return gErrMessages[err]; | |
211 | else | |
212 | return gInfoMessages[err-U_ERROR_WARNING_START]; | |
213 | } | |
214 | ||
374ca955 | 215 | U_CFUNC const UChar *u_wmsg_errorName(UErrorCode err) |
b75a7d8f A |
216 | { |
217 | UChar *msg; | |
218 | int32_t msgLen; | |
219 | UErrorCode subErr = U_ZERO_ERROR; | |
220 | const char *textMsg = NULL; | |
221 | ||
222 | /* try the cache */ | |
223 | msg = (UChar*)fetchErrorName(err); | |
224 | ||
225 | if(msg) | |
226 | { | |
227 | return msg; | |
228 | } | |
229 | ||
230 | if(gBundle == NULL) | |
231 | { | |
232 | msg = NULL; | |
233 | } | |
234 | else | |
235 | { | |
236 | const char *errname = u_errorName(err); | |
237 | if (errname) { | |
238 | msg = (UChar*)ures_getStringByKey(gBundle, errname, &msgLen, &subErr); | |
239 | if(U_FAILURE(subErr)) | |
240 | { | |
241 | msg = NULL; | |
242 | } | |
243 | } | |
244 | } | |
245 | ||
246 | if(msg == NULL) /* Couldn't find it anywhere.. */ | |
247 | { | |
248 | char error[128]; | |
249 | textMsg = u_errorName(err); | |
250 | if (!textMsg) { | |
251 | sprintf(error, "UNDOCUMENTED ICU ERROR %d", err); | |
252 | textMsg = error; | |
253 | } | |
254 | msg = (UChar*)malloc((strlen(textMsg)+1)*sizeof(msg[0])); | |
255 | u_charsToUChars(textMsg, msg, (int32_t)(strlen(textMsg)+1)); | |
256 | } | |
257 | ||
258 | if(err>=0) | |
259 | gErrMessages[err] = msg; | |
260 | else | |
261 | gInfoMessages[err-U_ERROR_WARNING_START] = msg; | |
262 | ||
263 | return msg; | |
264 | } |