1 /**************************************************************************
2 *
3 * Copyright (C) 2001-2006, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 *
6 ***************************************************************************
7 *
8 * ufortune - An ICU resources sample program
9 *
10 * Demonstrates
11 * Defining resources for use by an application
12 * Compiling and packaging them into a dll
13 * Referencing the resource-containing dll from application code
14 * Loading resource data using ICU's API
15 *
16 * Created Nov. 7, 2001 by Andy Heninger
17 *
18 * ufortune is a variant of the Unix "fortune" command, with
19 * ICU resources that contain the fortune-cookie sayings.
20 * Using resources allows fortunes in different languages to
21 * be selected based on locale.
22 */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <time.h>
28
29 #include "unicode/udata.h" /* ICU API for data handling. */
30 #include "unicode/ures.h" /* ICU API for resource loading */
31 #include "unicode/ustdio.h" /* ICU API for reading & writing Unicode data */
32 /* to files, possibly including character */
33 /* set conversions. */
34 #include "unicode/ustring.h"
35
36 #ifndef UFORTUNE_NOSETAPPDATA
37 /*
38 * Resource Data Reference. The data is packaged as a dll (or .so or
39 * whatever, depending on the platform) that exports a data
40 * symbol. The application (that's us) references that symbol,
41 * here, and will pass the data address to ICU, which will then
42 * be able to fetch resources from the data.
43 */
44 extern const void U_IMPORT *fortune_resources_dat;
45 #endif
46
47 void u_write(const UChar *what, int len);
48
49
50 /*
51 * main() This one function is all of the application code.
52 */
main(int argc,char ** argv)53 int main(int argc, char **argv)
54 {
55 UBool displayUsage = FALSE; /* Set true if command line err or help */
56 /* option was requested. */
57 UBool verbose = FALSE; /* Set true if -v command line option. */
58 char *optionError = NULL; /* If command line contains an unrecognized */
59 /* option, this will point to it. */
60 char *locale=NULL; /* Locale name. Null for system default, */
61 /* otherwise set from command line. */
62 const char * programName = argv[0]; /* Program invocation name. */
63
64
65 UFILE *u_stdout; /* Unicode stdout file. */
66 UErrorCode err = U_ZERO_ERROR; /* Error return, used for most ICU */
67 /* functions. */
68
69 UResourceBundle *myResources; /* ICU Resource "handles" */
70 UResourceBundle *fortunes_r;
71
72 int32_t numFortunes; /* Number of fortune strings available. */
73 int i;
74
75 const UChar *resString; /* Points to strings fetched from Resources. */
76 int32_t len;
77
78
79 /* Process command line options.
80 * -l locale specify a locale
81 * -v verbose mode. Display extra messages.
82 * -? or --help display a usage line
83 */
84 for (i=1; i<argc; i++) {
85 if (strcmp(argv[i], "-l") ==0) {
86 if (++i < argc) {
87 locale = argv[i];
88 }
89 continue;
90 }
91 if (strcmp(argv[i], "-v") == 0) {
92 verbose = TRUE;
93 continue;}
94 if (strcmp(argv[i], "-?") == 0 ||
95 strcmp(argv[i], "--help") == 0) {
96 displayUsage = TRUE;
97 continue;}
98 optionError = argv[i];
99 displayUsage = TRUE;
100 break;
101 }
102
103 /* ICU's icuio package provides a convenient way to write Unicode
104 * data to stdout. The string data that we get from resources
105 * will be UChar * strings, which icuio can handle nicely.
106 */
107 u_stdout = u_finit(stdout, NULL /*locale*/, NULL /*codepage */);
108 if (verbose) {
109 u_fprintf(u_stdout, "%s: checking output via icuio.\n", programName);
110 }
111
112 #ifndef UFORTUNE_NOSETAPPDATA
113 /* Tell ICU where our resource data is located in memory.
114 * The data lives in the Fortune_Resources dll, and we just
115 * pass the address of an exported symbol from that library
116 * to ICU.
117 */
118 udata_setAppData("fortune_resources", &fortune_resources_dat, &err);
119 if (U_FAILURE(err)) {
120 fprintf(stderr, "%s: udata_setAppData failed with error \"%s\"\n", programName, u_errorName(err));
121 exit(-1);
122 }
123 #endif
124
125 /* Open our resources.
126 */
127 myResources = ures_open("fortune_resources", locale, &err);
128 if (U_FAILURE(err)) {
129 fprintf(stderr, "%s: ures_open failed with error \"%s\"\n", programName, u_errorName(err));
130 exit(-1);
131 }
132 if (verbose) {
133 u_fprintf(u_stdout, "status from ures_open(\"fortune_resources\", %s) is %s\n",
134 locale? locale: " ", u_errorName(err));
135 }
136
137 /*
138 * Display any command line option usage errors and/or the
139 * usage help message. These messages come from our resource bundle.
140 */
141 if (optionError != NULL) {
142 const UChar *msg = ures_getStringByKey(myResources, "optionMessage", &len, &err);
143 if (U_FAILURE(err)) {
144 fprintf(stderr, "%s: ures_getStringByKey(\"optionMessage\") failed, %s\n",
145 programName, u_errorName(err));
146 exit(-1);
147 }
148 u_file_write(msg, len, u_stdout); /* msg is UChar *, from resource */
149 u_fprintf(u_stdout, " %s\n", optionError); /* optionError is char *, from argv */
150 }
151
152 if (displayUsage) {
153 const UChar *usage;
154 int returnValue=0;
155
156 usage = ures_getStringByKey(myResources, "usage", &len, &err);
157 if (U_FAILURE(err)) {
158 fprintf(stderr, "%s: ures_getStringByKey(\"usage\") failed, %s\n", programName, u_errorName(err));
159 exit(-1);
160 }
161 u_file_write(usage, len, u_stdout);
162 if (optionError != NULL) {returnValue = -1;}
163 return returnValue;
164 }
165
166 /*
167 * Open the "fortunes" resources from within the already open resources
168 */
169 fortunes_r = ures_getByKey(myResources, "fortunes", NULL, &err);
170 if (U_FAILURE(err)) {
171 fprintf(stderr, "%s: ures_getByKey(\"fortunes\") failed, %s\n", programName, u_errorName(err));
172 exit(-1);
173 }
174
175
176 /*
177 * Pick up and display a random fortune
178 *
179 */
180 numFortunes = ures_countArrayItems(myResources, "fortunes", &err);
181 if (U_FAILURE(err)) {
182 fprintf(stderr, "%s: ures_countArrayItems(\"fortunes\") failed, %s\n", programName, u_errorName(err));
183 exit(-1);
184 }
185 if (numFortunes <= 0) {
186 fprintf(stderr, "%s: no fortunes found.\n", programName);
187 exit(-1);
188 }
189
190 i = (int)time(NULL) % numFortunes; /* Use time to pick a somewhat-random fortune. */
191 resString = ures_getStringByIndex(fortunes_r, i, &len, &err);
192 if (U_FAILURE(err)) {
193 fprintf(stderr, "%s: ures_getStringByIndex(%d) failed, %s\n", programName, i, u_errorName(err));
194 exit(-1);
195 }
196
197 u_file_write(resString, len, u_stdout); /* Write out the message */
198 u_fputc(0x0a, u_stdout); /* and a trailing newline */
199
200 return 0;
201 }
202
203