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 */ 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