| /************************************************************************** | 
 | * | 
 | *   Copyright (C) 2001, International Business Machines | 
 | *   Corporation and others.  All Rights Reserved. | 
 | * | 
 | *************************************************************************** | 
 | * | 
 | *   ufortune - An ICU resources sample program | 
 | * | 
 | *      Demonstrates | 
 | *         Defining resources for use by an application | 
 | *         Compiling and packaging them into a dll | 
 | *         Referencing the resource-containing dll from application code | 
 | *         Loading resource data using ICU's API | 
 | * | 
 | *      Created Nov. 7, 2001  by Andy Heninger | 
 | * | 
 | *      ufortune is a variant of the Unix "fortune" command, with | 
 | *               ICU resources that contain the fortune-cookie sayings. | 
 | *               Using resources allows  fortunes in different languages to | 
 | *               be selected based on locale. | 
 | */ | 
 |  | 
 | #include <stdio.h> | 
 | #include <stdlib.h> | 
 | #include <string.h> | 
 | #include <time.h> | 
 |  | 
 | #include "unicode/udata.h"     /* ICU API for data handling.                 */ | 
 | #include "unicode/ures.h"      /* ICU API for resource loading               */ | 
 | #include "unicode/ustdio.h"    /* ICU API for reading & writing Unicode data */ | 
 |                                /*   to files, possibly including character   */ | 
 |                                /*   set conversions.                         */ | 
 | #include "unicode/ustring.h" | 
 |  | 
 | /* | 
 |  *  Resource Data Reference.  The data is packaged as a dll (or .so or | 
 |  *           whatever, depending on the platform) that exports a data | 
 |  *           symbol.  The application (that's us) references that symbol, | 
 |  *           here, and will pass the data address to ICU, which will then | 
 |  *           be able to fetch resources from the data. | 
 |  */ | 
 | extern  const void U_IMPORT *fortune_resources_dat; | 
 | void u_write(const UChar *what, int len); | 
 |  | 
 |  | 
 | /* | 
 |  *  main()   This one function is all of the application code. | 
 |  */ | 
 | int main(int argc, char **argv) | 
 | { | 
 |     UBool              displayUsage  = FALSE;    /* Set true if command line err or help      */ | 
 |                                                  /*   option was requested.                   */ | 
 |     UBool              verbose       = FALSE;    /* Set true if -v command line option.       */ | 
 |     char              *optionError   = NULL;     /* If command line contains an unrecognized  */ | 
 |                                                  /*   option, this will point to it.          */ | 
 |     char              *locale=NULL;              /* Locale name.  Null for system default,    */ | 
 |                                                  /*   otherwise set from command line.        */ | 
 |     const char *       programName   = argv[0];  /* Program invocation name.                  */ | 
 |  | 
 |  | 
 |     UFILE             *u_stdout;                 /* Unicode stdout file.                      */ | 
 |     UErrorCode         err           = U_ZERO_ERROR;   /* Error return, used for most ICU     */ | 
 |                                                        /*   functions.                        */ | 
 |  | 
 |     UResourceBundle   *myResources;              /* ICU Resource "handles"                    */ | 
 |     UResourceBundle   *fortunes_r; | 
 |  | 
 |     int32_t            numFortunes;              /* Number of fortune strings available.      */ | 
 |     int                i; | 
 |  | 
 |     const UChar       *resString;                /* Points to strings fetched from Resources. */ | 
 |     int32_t            len; | 
 |  | 
 |  | 
 |     /*  Process command line options. | 
 |      *     -l  locale          specify a locale | 
 |      *     -v                  verbose mode.  Display extra messages. | 
 |      *     -? or --help        display a usage line | 
 |      */ | 
 |     for (i=1; i<argc; i++) { | 
 |         if (strcmp(argv[i], "-l") ==0) { | 
 |             if (++i < argc) { | 
 |                 locale = argv[i]; | 
 |             } | 
 |             continue; | 
 |         } | 
 |         if (strcmp(argv[i], "-v") == 0) { | 
 |             verbose = TRUE; | 
 |             continue;} | 
 |         if (strcmp(argv[i], "-?") == 0 || | 
 |             strcmp(argv[i], "--help") == 0) { | 
 |             displayUsage = TRUE; | 
 |             continue;} | 
 |         optionError = argv[i]; | 
 |         displayUsage = TRUE; | 
 |         break; | 
 |     } | 
 |  | 
 |     /* ICU's ustdio package provides a convenient way to write Unicode | 
 |      *    data to stdout.  The string data that we get from resources | 
 |      *    will be UChar * strings, which ustdio can handle nicely. | 
 |      */ | 
 |     u_stdout = u_finit(stdout, NULL /*locale*/,  NULL /*codepage */); | 
 |     if (verbose) { | 
 |         u_fprintf(u_stdout, "%s:  checking output via ustdio.\n", programName); | 
 |     } | 
 |  | 
 |     /* Tell ICU where our resource data is located in memory. | 
 |      *   The data lives in the Fortune_Resources dll, and we just | 
 |      *   pass the address of an exported symbol from that library | 
 |      *   to ICU. | 
 |      */ | 
 |     udata_setAppData("fortune_resources", &fortune_resources_dat, &err); | 
 |     if (U_FAILURE(err)) { | 
 |         fprintf(stderr, "%s: ures_open failed with error \"%s\"\n", programName, u_errorName(err)); | 
 |         exit(-1); | 
 |     } | 
 |  | 
 |     /* Open our resources. | 
 |     */ | 
 |     myResources = ures_open("fortune_resources", locale, &err); | 
 |     if (U_FAILURE(err)) { | 
 |         fprintf(stderr, "%s: ures_open failed with error \"%s\"\n", programName, u_errorName(err)); | 
 |         exit(-1); | 
 |     } | 
 |     if (verbose) { | 
 |         u_fprintf(u_stdout, "status from ures_open(\"fortune_resources\", %s) is %s\n", | 
 |             locale? locale: " ", u_errorName(err)); | 
 |     } | 
 |  | 
 |     /* | 
 |      * Display any command line option usage errors and/or the | 
 |      *     usage help message.  These messages come from our resource bundle. | 
 |      */ | 
 |     if (optionError != NULL) { | 
 |         const UChar *msg = ures_getStringByKey(myResources, "optionMessage", &len, &err); | 
 |         if (U_FAILURE(err)) { | 
 |             fprintf(stderr, "%s: ures_getStringByKey(\"optionMessage\") failed, %s\n", | 
 |                 programName, u_errorName(err)); | 
 |             exit(-1); | 
 |         } | 
 |         u_file_write(msg,  len, u_stdout);              /* msg is UChar *, from resource    */ | 
 |         u_fprintf(u_stdout, " %s\n", optionError);      /* optionError is char *, from argv */ | 
 |     } | 
 |  | 
 |     if (displayUsage) { | 
 |         const UChar *usage; | 
 |         int          returnValue=0; | 
 |  | 
 |         usage = ures_getStringByKey(myResources, "usage", &len, &err); | 
 |         if (U_FAILURE(err)) { | 
 |             fprintf(stderr, "%s: ures_getStringByKey(\"usage\") failed, %s\n", programName, u_errorName(err)); | 
 |             exit(-1); | 
 |         } | 
 |         u_file_write(usage,  len, u_stdout); | 
 |         if (optionError != NULL) {returnValue = -1;} | 
 |         return returnValue; | 
 |     } | 
 |  | 
 |     /* | 
 |      * Open the "fortunes" resources from within the already open resources | 
 |      */ | 
 |     fortunes_r = ures_getByKey(myResources, "fortunes", NULL, &err); | 
 |     if (U_FAILURE(err)) { | 
 |         fprintf(stderr, "%s: ures_getByKey(\"fortunes\") failed, %s\n", programName, u_errorName(err)); | 
 |         exit(-1); | 
 |     } | 
 |  | 
 |  | 
 |     /* | 
 |      * Pick up and display a random fortune | 
 |      * | 
 |      */ | 
 |     numFortunes = ures_countArrayItems(myResources, "fortunes", &err); | 
 |     if (U_FAILURE(err)) { | 
 |         fprintf(stderr, "%s: ures_countArrayItems(\"fortunes\") failed, %s\n", programName, u_errorName(err)); | 
 |         exit(-1); | 
 |     } | 
 |     if (numFortunes <= 0) { | 
 |         fprintf(stderr, "%s: no fortunes found.\n"); | 
 |         exit(-1); | 
 |     } | 
 |  | 
 |     i = time(NULL) % numFortunes;    /*  Use time to pick a somewhat-random fortune.  */ | 
 |     resString = ures_getStringByIndex(fortunes_r, i, &len, &err); | 
 |     if (U_FAILURE(err)) { | 
 |         fprintf(stderr, "%s: ures_getStringByIndex(%d) failed, %s\n", programName, i, u_errorName(err)); | 
 |         exit(-1); | 
 |     } | 
 |  | 
 |     u_file_write(resString, len, u_stdout);      /* Write out the message           */ | 
 | 	u_fputc(0x0a, u_stdout);                     /*   and a trailing newline	    */ | 
 |  | 
 |     return 0; | 
 | } | 
 |  |