LocaleXlate.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $TOG: LocaleXlate.c /main/14 1999/10/14 15:58:52 mgreess $ */
  24. /************************************<+>*************************************
  25. ****************************************************************************
  26. $FILEBEG$: LocaleXlate.c
  27. $PROJECT$: CDE 1.0
  28. $COMPONENT$: DtLcx service
  29. $1LINER$: Locale translation routines
  30. $COPYRIGHT$:
  31. (c) Copyright 1993, 1994 Hewlett-Packard Company
  32. (c) Copyright 1993, 1994 International Business Machines Corp.
  33. (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  34. (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of Novell, Inc.
  35. $END$
  36. ****************************************************************************
  37. ************************************<+>*************************************/
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #if defined(sun)
  42. #include <sys/utsname.h>
  43. #endif
  44. #include <limits.h>
  45. #define X_INCLUDE_PWD_H
  46. #define XOS_USE_XT_LOCKING
  47. #include <X11/Xos_r.h> /* for getpw... */
  48. #include <sys/param.h> /* MAXPATHLEN */
  49. #include <sys/utsname.h> /* for uname */
  50. #include <unistd.h>
  51. /* for Xrm */
  52. #include <X11/Intrinsic.h>
  53. #include <X11/Xresource.h>
  54. #include "XlationSvc.h"
  55. /*=================================================================
  56. $SHAREDBEG$: This is the header file that should appear in all
  57. DtLcx topics
  58. =======================================================$SKIP$======*/
  59. /*$INCLUDE$*/
  60. #include "LocaleXlate.h"
  61. /*$END$*/
  62. /*========================================================*/
  63. /*================ Introductory Info =====================*/
  64. /*========================================================*/
  65. #if DOC
  66. /*========================================================*/
  67. $INTROBEG$: _DtLcx family
  68. $1LINER$: Translate locale and codeset strings to/from any platform
  69. $SUMMARY$:
  70. The _DtLcx family of routines enables the translation of a
  71. locale string from any platform into a standard locale string,
  72. and from standard locale string to the locale string of any platform.
  73. This is useful because each platform, and in fact within
  74. version ranges of some platforms, different strings are used
  75. that have the same meaning. This becomes a problem as soon as
  76. any of these strings is stored in a file. If the file is
  77. opened on a platform for which the string has no meaning,
  78. that functionality supported by using the string is lost.
  79. With the _DtLcx service, the string can be translated into
  80. a string appropriate to the current platform.
  81. Standard locale strings are based on the XoJIG proposed strings,
  82. but with a slightly altered syntax to adhere to the constraints
  83. of the translation database.
  84. The following are the current set of standard strings:
  85. _DtLcx uses the _DtXlate translation database services,
  86. but the _DtLcx routines provide a high-level interface to
  87. the _DtXlate routines tuned to locales. They allow any
  88. component of a locale to be translated individually.
  89. The _DtLcxOpenAllDbs() routine opens all the predefined
  90. locale translation databases that can be found. These
  91. may are the following:
  92. /usr/dt/config/svc/<platform>.lcx
  93. /etc/dt/config/svc/<platform>.lcx
  94. $HOME/.dt/config/svc/<platform>.lcx
  95. Alternatively, the DTLCXSEARCHPATH directory may be used
  96. to specify a colon separated search path. Relative paths
  97. in the search path are relative to the current working
  98. directory.
  99. One of the nice features of the _DtLcx service is that
  100. the translation database is designed for extension. So
  101. if new locales need to be supported, a system admin
  102. or user can add the specifications to the appropriate
  103. file and it will be immediately accessible.
  104. /*=$END$================================================*/
  105. #endif
  106. #if DOC
  107. /*========================================================*/
  108. $INTROBEG$: _DtLcx translation table syntax
  109. $1LINER$: translation table syntax for _DtLcx
  110. $SUMMARY$:
  111. BNF Syntax of Locale Translation Specification
  112. ==============================================
  113. For the full syntax of translation specifications,
  114. see the _DtXlate documentation.
  115. <stdvalue> ::= <langterr>[.<codeset>[.<modifier>]]
  116. <langterr> ::= <identifier> | <matchall>
  117. <codeset> ::= <identifier> | <matchall>
  118. <modifier> ::= <identifier> | <matchall>
  119. <opvalue> ::= (<vischars>|<metachar>)+ | '"'(<anychar>|<metachar>)+'"'
  120. Semantics of the Translation Specification
  121. ==========================================
  122. For a full description of translation table semantics,
  123. refer to the _DtXlatedocumentation.
  124. <operations> : a CDE-standardized identifier for the operation(s) to
  125. which the value applies. The operation(s) need not be supported by every
  126. platform, but CDE must have standardized an identifier for the operation
  127. in order for it to be used. More than one identifier may be included by
  128. concatenating them using the ',' separator, eg. "iconv1,iconv3".
  129. _DtLcx defines a number of standard operation strings that use
  130. locales. Users of _DtLcx should use the constants beginning
  131. _DtLCX_OPER... to specify a particular operation.
  132. <stdvalue> : a sequence of one or more '.'-separated CDE-standardizd
  133. identifiers or matchall characters. This represents the canonical
  134. string used as a standard representation of a semantic value that
  135. may vary in different situations.
  136. <langterr> : a CDE-standardized identifier for a language and territory
  137. for which the operation is valid. The language and territory must be
  138. supported or irrelvant for the operations, as qualified for platform
  139. and version, e.g. en_US. The identifier need not be the identifier
  140. used on any actual platform to specify language and territory.
  141. <codeset> : a CDE-standardized identifier for a codeset for which the
  142. operation is valid. The codeset must be supported or irrelvant for
  143. the operations, as qualified for platform and version, e.g. iso88591.
  144. The identifier need not be the identifier used on any actual platform
  145. to specify codeset.
  146. <modifier> : a CDE-standardized identifier for a locale modifier.
  147. The modifier must be supported or irrelvant for the operations,
  148. as qualified for platform and version. The identifier need not be
  149. the identifier used on any actual platform to specify modifiers.
  150. <opvalue> : can be used in three ways. When a straight translation,
  151. it is string that is matched against a query locale value to determine
  152. the standard value of the locale. When a OpToStd translation,
  153. the string is a regular expression that is matched against the
  154. query string. When a StdToOp translation, the string is a
  155. replacement value for the std value and may contain subexpression
  156. replacement specifiers.
  157. $EXAMPLE$:
  158. These are some example specs:
  159. HP-UX.900-999.setlocale.=.en_US.HP-ROMAN8: american
  160. HP-UX.900-999.setlocale.=.en_US.ISO-8859-1: american.iso88591
  161. HP-UX.900-999.setlocale.=.nl_NL.HP-ROMAN8: dutch
  162. HP-UX.900-999.setlocale.=.nl_NL.ISO-8859-1: dutch.iso88591
  163. /*=$END$================================================*/
  164. #endif
  165. #if DOC
  166. /*========================================================*/
  167. $INTROBEG$: _DtLcx example usage
  168. $1LINER$: Examples of how to _DtLcx
  169. $EXAMPLE$:
  170. #include <LocaleXlate.h>
  171. main()
  172. {
  173. _DtXlateDb db = NULL;
  174. int ret;
  175. char plat[_DtPLATFORM_MAX_LEN];
  176. int execver;
  177. int compver;
  178. char * val = NULL;
  179. char * str = NULL;
  180. char * val1 = NULL;
  181. char * val2 = NULL;
  182. char * val3 = NULL;
  183. ret = _DtLcxOpenAllDbs(&db);
  184. ret = _DtXlateGetXlateEnv(db,plat,&execver,&compver);
  185. printf("Platform: %s\nExec Ver: %d\nComp Ver: %d\n",
  186. plat,execver,compver);
  187. ret = _DtLcxXlateStdToOp(db,plat,compver,DtLCX_OPER_SETLOCALE,
  188. str="en_US.hp-roman8",NULL,NULL,NULL,&val);
  189. if (ret==0) printf("setlocale(%s) xlation=%s\n", str, val);
  190. else printf("no xlation\n", val);
  191. ret = _DtLcxXlateStdToOp(db,plat,compver,DtLCX_OPER_SETLOCALE,
  192. str="en_US.?",NULL,NULL,NULL,&val);
  193. if (ret==0) printf("setlocale(%s) xlation=%s\n", str, val);
  194. else printf("no xlation\n", val);
  195. ret = _DtLcxXlateOpToStd(db,plat,execver,DtLCX_OPER_SETLOCALE,
  196. str="american",&val,&val1,&val2,&val3);
  197. if (ret==0) printf("setlocale(%s) xlation=%s; %s; %s; %s\n",
  198. str, val,val1,val2,val3);
  199. else printf("no xlation\n", val,val1,val2,val3);
  200. ret = _DtLcxXlateOpToStd(db,plat,execver,DtLCX_OPER_SETLOCALE,
  201. str="dutch@fold",&val,&val1,&val2,&val3);
  202. if (ret==0) printf("setlocale(%s) xlation=%s; %s; %s; %s\n",
  203. str, val,val1,val2,val3);
  204. ret = _DtLcxCloseDb(&db);
  205. }
  206. /*=$END$================================================*/
  207. #endif
  208. /*========================================================*/
  209. /*====================== Constants =======================*/
  210. /*========================================================*/
  211. /*=============== private =================*/
  212. /* A "random" number used to ensure that the Db has been initalized */
  213. #define PATH_SEPARATOR ':'
  214. #define EOS '\0'
  215. #define DIR_SLASH '/'
  216. #define DIR_SLASH_STR "/"
  217. #define MATCHALL_STR "?"
  218. #define DOT_STR "."
  219. /*=============== internal =================*/
  220. #define DTLCXSEARCHPATH "DTLCXSEARCHPATH"
  221. #ifndef CDE_CONFIGURATION_TOP
  222. #define CDE_CONFIGURATION_TOP "/etc/dt"
  223. #endif
  224. #ifndef CDE_INSTALLATION_TOP
  225. #define CDE_INSTALLATION_TOP "/usr/dt"
  226. #endif
  227. #ifndef CDE_USER_TOP
  228. #define CDE_USER_TOP ".dt"
  229. #endif
  230. #define DtLCX_USER_PATH s_LcxUserPath
  231. #define DtLCX_INSTALL_AND_CONFIG_PATHS s_LcxInstallAndConfigPaths
  232. #define _DtLCX_INSTALL_DB_DIR CDE_INSTALLATION_TOP "/config/svc/"
  233. /* This is the file type of a _DtLcx file */
  234. #define _DtLCX_DATABASE_TYPE ".lcx"
  235. /* This is the name of the fallback _DtLcx file */
  236. #define _DtLCX_DATABASE_FALLBACK ("dtcomplete" _DtLCX_DATABASE_TYPE)
  237. /* This is the name of the CDE standard _DtLcx file */
  238. #define _DtLCX_DATABASE_CDE ("CDE" _DtLCX_DATABASE_TYPE)
  239. /*========================================================*/
  240. /*====================== Variables =======================*/
  241. /*========================================================*/
  242. static char s_LcxUserPath[] = CDE_USER_TOP "/config/svc";
  243. static char s_LcxInstallAndConfigPaths[] =
  244. CDE_INSTALLATION_TOP "/config/svc:"
  245. CDE_CONFIGURATION_TOP "/config/svc:";
  246. /*========================================================*/
  247. /*================== Private routines ====================*/
  248. /*========================================================*/
  249. #if DOC
  250. /*========================================================*/
  251. /*
  252. $PFUNBEG$: GetHomeDirPath()
  253. $1LINER$: Retrieves path to current user's home directory
  254. $SUMMARY$:
  255. Looks for first the HOME and then USER environment
  256. variables. If these are not set, uses the password
  257. info to get the user's home directory.
  258. $ARGS$:
  259. outptr: pts to string allocated by caller to hold the home dir path
  260. Generally, the string should be at least MAXPATHLEN+1 in size.
  261. max: maximum number of bytes allowed (including ending bytes).
  262. $RETURNS$:
  263. */
  264. /*================================================$SKIP$==*/
  265. #endif
  266. static
  267. void GetHomeDirPath(
  268. char * outptr,
  269. unsigned int max)
  270. { /*$CODE$*/
  271. int uid;
  272. char * ptr = NULL;
  273. _Xgetpwparams pwd_buf;
  274. struct passwd * pwd_ret;
  275. if((ptr = (char *)getenv("HOME")) == NULL)
  276. {
  277. if((ptr = (char *)getenv("USER")) != NULL)
  278. pwd_ret = _XGetpwnam(ptr, pwd_buf);
  279. else
  280. {
  281. uid = getuid();
  282. pwd_ret = _XGetpwuid(uid, pwd_buf);
  283. }
  284. if (pwd_ret != NULL)
  285. ptr = pwd_ret->pw_dir;
  286. else
  287. ptr = NULL;
  288. }
  289. if (ptr && strlen(ptr))
  290. {
  291. strncpy(outptr, ptr, max-1);
  292. outptr[max-1] = '\0';
  293. }
  294. else outptr[0] = '\0' ;
  295. } /*$END$*/
  296. /*========================================================*/
  297. /*================ Public DtLcx routines =================*/
  298. /*========================================================*/
  299. #if DOC
  300. /*========================================================*/
  301. $FUNBEG$: _DtLcxOpenAllDbs()
  302. $1LINER$: Open and merge all locale translation databases that can be found
  303. $SUMMARY$:
  304. DtLcxOpenAllDbs() locates all translation databases
  305. named "<platform>.lcx" present in the DTLCXSEARCHPATH
  306. directories. If none exist, the file "dtcomplete.lcx"
  307. is tried in those directories. Finally, the database "CDE.lcx"
  308. is merged into those databases already loaded.
  309. The <platform> string is taken from uname(2), which is the
  310. same string returned by the command 'uname -s'. For example,
  311. on HP-UX platforms, the string is "HPUX", so the translation
  312. databases to be loaded must be named "HPUX.lcx".
  313. By default, the search paths are:
  314. DTLCXSEARCHPATH = "/usr/dt/config/svc:" \
  315. "/etc/dt/config/svc:" \
  316. "$HOME/.dt/config/svc"
  317. Alternatively, the DTLCXSEARCHPATH directory may be used
  318. to specify a colon separated search path. Relative paths
  319. in the search path are relative to the current working
  320. directory.
  321. $ARGS$:
  322. $RETURNS$:
  323. Returns the return value of _DtXlateOpenAllDbs()
  324. /*================================================$SKIP$==*/
  325. #endif
  326. int _DtLcxOpenAllDbs(
  327. _DtXlateDb * ret_db)
  328. { /*$CODE$*/
  329. char * paths;
  330. char * dbPaths;
  331. struct utsname names;
  332. int ret = 0;
  333. int globRet = -1;
  334. int len;
  335. char lcxfile[100];
  336. char homePath[MAXPATHLEN];
  337. _DtXlateDb cde_db = NULL;
  338. #define MAXSHORTFNAMELEN 14
  339. /* get host specifics and generate platform-specific lcx file name */
  340. uname(&names);
  341. len = MAXSHORTFNAMELEN - strlen(_DtLCX_DATABASE_TYPE);
  342. strncpy(lcxfile,names.sysname,len);
  343. lcxfile[len-1] = EOS;
  344. strcat(lcxfile,_DtLCX_DATABASE_TYPE); /* e.g. HP-UX.lcx */
  345. /* get paths for LCX */
  346. paths = getenv(DTLCXSEARCHPATH);
  347. if (NULL != paths && paths[0] != EOS)
  348. {
  349. dbPaths = strdup(paths);
  350. }
  351. else
  352. {
  353. const char *slash;
  354. char *end;
  355. /* no DTLCXSEARCHPATH; build a default path */
  356. GetHomeDirPath(homePath, MAXPATHLEN);
  357. end = homePath + strlen(homePath);
  358. _DtMBStrrchr(homePath,DIR_SLASH,-1,&slash);
  359. if ((end - 1) != slash && end < homePath + MAXPATHLEN - 2 )
  360. {
  361. *end++ = DIR_SLASH;
  362. *end = EOS;
  363. }
  364. if (end < homePath + MAXPATHLEN - strlen(DtLCX_USER_PATH) - 1)
  365. strcat(homePath,DtLCX_USER_PATH);
  366. dbPaths = malloc(sizeof(char) *
  367. (strlen(homePath)+strlen(DtLCX_INSTALL_AND_CONFIG_PATHS)+5));
  368. if (dbPaths)
  369. sprintf(dbPaths,"%s:%s",DtLCX_INSTALL_AND_CONFIG_PATHS,homePath);
  370. }
  371. /* open all dbs of filename found in paths */
  372. globRet = _DtXlateOpenAllDbs(dbPaths,lcxfile, ret_db);
  373. if (globRet != 0)
  374. { /* on failure */
  375. /* open all dbs of the fallback filename found in paths */
  376. globRet = _DtXlateOpenAllDbs(dbPaths,_DtLCX_DATABASE_FALLBACK, ret_db);
  377. }
  378. /* merge in the CDE standard translations database */
  379. ret = _DtXlateOpenAllDbs(dbPaths,_DtLCX_DATABASE_CDE, &cde_db);
  380. if (ret == 0)
  381. {
  382. globRet = 0;
  383. _DtXlateMergeDbs(&cde_db,ret_db); /* cde_db get's closed by the merge */
  384. }
  385. else
  386. _DtXlateCloseDb(&cde_db);
  387. if(dbPaths) free(dbPaths);
  388. return globRet;
  389. } /*$END$*/
  390. #if DOC
  391. /*========================================================*/
  392. $FUNBEG$: _DtLcxCloseDb()
  393. $1LINER$: Close an open locale translation database
  394. $SUMMARY$:
  395. _DtLcxCloseDb() releases all memory associated with
  396. the translation database. Further use of the database
  397. object is an error.
  398. $ARGS$:
  399. $RETURNS$:
  400. 0: database was valid and has been closed
  401. -1: invalid database pointer
  402. $DEF$:
  403. int _DtLcxCloseDb(
  404. _DtXlateDb * io_db)
  405. $NOTE$: the current implementation is a macro call to
  406. _DtXlateCloseDb().
  407. /*================================================$SKIP$==*/
  408. #endif
  409. #if DOC
  410. /*========================================================*/
  411. /*
  412. $FUNBEG$: _DtLcxXlateOpToStd()
  413. $1LINER$: Translate an operation-specific locale to a standard locale
  414. $SUMMARY$:
  415. _DtLcxXlateOpToStd() is designed to allow a locale string
  416. that is specific to some platform, version, and operation to be
  417. translated to a CDE standard locale. For example, a locale
  418. string stored in a file on systemA and recovered by an application
  419. on systemB can be translated into a CDE standard locale by the
  420. application on system B.
  421. The xlationDb is the database to use for the translation.
  422. It must have been opened with a call to _DtLcxOpenAllDbs().
  423. The platform and version arguments can be used to specify
  424. systemA if the information is known. The platform value
  425. should be one of _DtPLATFORM_xxx. If platform is unknown,
  426. use _DtPLATFORM_UNKNOWN, and if version is unknown, use -1.
  427. The operation is an optional argument. If the operation is known
  428. from which the opValue originated or for which it was intended
  429. for use on systemA, the operation may be specified using the
  430. appropriate DtLCX_OPER_xxx constant. If the operation is unknown,
  431. it should be NULL.
  432. The opValue is the systemA locale string recovered by the
  433. application on systemB and which should be translated. It is
  434. an error if it is NULL.
  435. Zero or more of the ret_xxx arguments may be NULL values.
  436. If they are NULL, that value is not determined. For
  437. non-NULL ret_xxx arguments, the string value of each
  438. is allocated using malloc() and the pointer is assigned
  439. at the location pointed to by the argument. The caller
  440. function should free the memory wth free() when it is
  441. no longer needed. The ret_xxx arguments have the following
  442. values.
  443. The ret_stdLocale points to a caller-owned string with
  444. the CDE standard equivalent to opValue. This value is the '.'-
  445. separated concatenation of the <langterr> and <codeset> fields
  446. of the specification. If <langterr> or <codeset> is the matchall
  447. character, that value and the '.' separator are dropped.
  448. The ret_stdLangTerr points to a caller-owned string with
  449. the CDE standard equivalent of the opValue's language and
  450. territory. If <langterr> or <codeset> in the translation
  451. specification is the matchall character, the value is the
  452. empty string.
  453. The ret_stdCodeset points to a caller-owned string with
  454. the CDE standard equivalent of the opValue's codeset.
  455. If <codeset> in the translation specification is the matchall
  456. character, the value is the empty string.
  457. The ret_stdModifier points to a caller-owned string with
  458. the CDE standard equivalent of the opValue's modifier.
  459. If <modifier> in the translation specification is the matchall
  460. character or not present, the value is the empty string.
  461. $ARGS$:
  462. xlation_db: a translation database
  463. platform: the platform string (see _DtXlateGetXlateEnv())
  464. version: the version number (see _DtXlateGetXlateEnv())
  465. operation: the operation of interest, e.g. "setlocale"
  466. opValue: the operation-specific value pattern
  467. ret_stdLocale: location where ptr to standard locale string is stored
  468. ret_stdLangTerr:location where ptr to standard lang+terr string is stored
  469. ret_stdCodeset: location where ptr to standard codeset string is stored
  470. ret_stdModifier:location where ptr to standard modifier string is stored
  471. $RETURNS$:
  472. Return values are those of _DtXlateOpToStd()
  473. */
  474. /*================================================$SKIP$==*/
  475. #endif
  476. int _DtLcxXlateOpToStd(
  477. const _DtXlateDb xlationDb,
  478. const char * platform,
  479. const int version,
  480. const char * operation,
  481. const char * opValue,
  482. char * * ret_stdLocale,
  483. char * * ret_stdLangTerr,
  484. char * * ret_stdCodeset,
  485. char * * ret_stdModifier)
  486. { /*$CODE$*/
  487. int ret;
  488. char * stdValue = NULL;
  489. Boolean freeStdValue = True;
  490. int scanned = 0;
  491. char langterr[50];
  492. char codeset[50];
  493. char mod[50];
  494. /* do the translation */
  495. ret = _DtXlateOpToStdValue(xlationDb,platform,version,operation,opValue,
  496. &stdValue,NULL);
  497. /* std locale string syntax: langterr.codeset.modifier */
  498. /* parse into the desire chunks */
  499. if (ret == 0 && stdValue)
  500. scanned = sscanf(stdValue,"%[^.].%[^.].%s",langterr,codeset,mod);
  501. /* locale string is just the std value */
  502. if ( ret_stdLocale )
  503. { *ret_stdLocale = stdValue; freeStdValue = False; }
  504. if ( ret_stdLangTerr)
  505. { *ret_stdLangTerr = ( scanned >= 1 ? strdup(langterr) : NULL); }
  506. if ( ret_stdCodeset )
  507. { *ret_stdCodeset = ( scanned >= 2 ? strdup(codeset) : NULL); }
  508. if ( ret_stdModifier )
  509. { *ret_stdModifier = ( scanned >= 3 ? strdup(mod) : NULL); }
  510. if (freeStdValue && NULL != stdValue) free(stdValue);
  511. return ret;
  512. } /*$END$*/
  513. #if DOC
  514. /*========================================================*/
  515. $FUNBEG$: _DtLcxXlateStdToOp()
  516. $1LINER$: Translate a standard locale to an operation-specific one
  517. $SUMMARY$:
  518. _DtLcxXlateStdToOp() is designed to allow a locale string
  519. that is the CDE standard locale to be translated to the appropriate
  520. string for some platform, version, and operation. For example, a
  521. CDE locale string stored in a file on systemA and recovered by an
  522. application on systemB can be translated into a platform- and
  523. operation-specific locale by the application on system B.
  524. _DtLcxXlateStdToOp() takes a number of query qualifiers
  525. and determines the best translation that matches them. The
  526. routine allocates memory for the resulting operation-specific
  527. locale using malloc() and stores the pointer to it at the
  528. location pointed to by ret_opValue. If the query qualifiers
  529. do not uniquely identify a translation specification, the
  530. specification used is chosen at random from those that match.
  531. [Random selection is an artifact of using XrmEnumerateDatabase()
  532. to process the contents of the table--entries are not presented
  533. to the processing routine in a pre-specified order.]
  534. The xlationDb is the database to use for the translation.
  535. It must have been opened with a call to _DtLcxOpenAllDbs().
  536. The platform and version arguments are optional. If the desired
  537. platform is the current one for the executing application,
  538. use _DtPLATFORM_CURRENT, and if version is the current one
  539. for the application, use -1.
  540. The operation is a required argument, and should be selected
  541. from the DtLCX_OPER_xxx constants.
  542. The stdLocale is the CDE standard locale string, such as the
  543. one recovered using _DtLcxXlateOpToStd(). The value is
  544. the '.'-separated concatenation of the <langterr>, <codeset>,
  545. and <modifier> fields, or it may be NULL. The stdLocale string
  546. alone *or* any combination of stdLangTerr, stdCodeset, and
  547. stdModifier strings may be specified for the translation, but
  548. not both.
  549. The stdLangTerr, stdCodeset, and stdModifier are the CDE strings,
  550. such as the one recovered using _DtLcxXlateOpToStd(). The
  551. strings are valid across CDE platforms and across operations.
  552. The stdLangTerr, stdCodeset, or stdModifier string may be used
  553. alone *or* in any combination with each other, but not with the
  554. stdLocale string. The values may also be NULL.
  555. $ARGS$:
  556. xlationDb: a translation database
  557. platform: the platform string (see _DtXlateGetXlateEnv())
  558. version: the version number (see _DtXlateGetXlateEnv())
  559. operation: the operation of interest, e.g. "setlocale"
  560. stdValue: the standard value pattern
  561. stdLocale: standard locale strin
  562. stdLangTerr: standard lang+terr string
  563. stdCodeset: standard codeset string
  564. stdModifier: standard modifier string
  565. ret_opValue: location where ptr to translated string is stored
  566. $RETURNS$:
  567. -1: if all stdXxx strings have NULL values
  568. plus the return values are those of _DtXlateStdToOp()
  569. /*================================================$SKIP$==*/
  570. #endif
  571. int _DtLcxXlateStdToOp(
  572. const _DtXlateDb xlationDb,
  573. const char * platform,
  574. const int version,
  575. const char * operation,
  576. const char * stdLocale,
  577. const char * stdLangTerr,
  578. const char * stdCodeset,
  579. const char * stdModifier,
  580. char * * ret_opValue)
  581. { /*$CODE$*/
  582. #define DTLCXXLATE_STDTOOP_BUFSIZE 256
  583. char stdValueBuf[DTLCXXLATE_STDTOOP_BUFSIZE];
  584. char *stdValue = stdValueBuf;
  585. char empty = EOS;
  586. char * matchall = MATCHALL_STR;
  587. char * dot = DOT_STR;
  588. char * sepLC = &empty;
  589. char * sepCM = &empty;
  590. int retval;
  591. if (stdLocale)
  592. {
  593. if (strlen(stdLocale) >= DTLCXXLATE_STDTOOP_BUFSIZE)
  594. stdValue = malloc(strlen(stdLocale) + 1);
  595. else
  596. stdValue = stdValueBuf;
  597. stdValue[0] = EOS;
  598. strcpy(stdValue, stdLocale);
  599. }
  600. else
  601. {
  602. int need = 0;
  603. int bytes_needed = 0;
  604. #define NEED_LANGTERR 0x01
  605. #define NEED_CODESET 0x02
  606. #define NEED_MODIFIER 0x04
  607. if (stdLangTerr) need = NEED_LANGTERR;
  608. if (stdCodeset) need = NEED_LANGTERR | NEED_CODESET;
  609. if (stdModifier) need = NEED_LANGTERR | NEED_CODESET | NEED_MODIFIER;
  610. if (need == 0) return -1; /* RETURN: need a pattern */
  611. /* only include matchalls for those that are needed */
  612. /* This is needed because of the manner of scoring matches.
  613. If unnecessary matchall's are present, that can detract
  614. from the score. */
  615. if (need & NEED_LANGTERR)
  616. { stdLangTerr = (stdLangTerr ? stdLangTerr : matchall); }
  617. if (need & (NEED_LANGTERR | NEED_CODESET))
  618. { stdCodeset = (stdCodeset ? stdCodeset : matchall); sepLC = dot; }
  619. if (need & (NEED_LANGTERR | NEED_CODESET | NEED_MODIFIER))
  620. { stdModifier = (stdModifier ? stdModifier : matchall); sepCM = dot; }
  621. bytes_needed =
  622. strlen(stdLangTerr) + strlen(sepLC) + strlen(stdCodeset) +
  623. strlen(sepCM) + strlen(stdModifier) + 1;
  624. if (bytes_needed > DTLCXXLATE_STDTOOP_BUFSIZE)
  625. stdValue = malloc(bytes_needed);
  626. else
  627. stdValue = stdValueBuf;
  628. /* generate the std value string */
  629. stdValue[0] = EOS;
  630. sprintf(stdValue,
  631. "%s%s%s%s%s",
  632. stdLangTerr, sepLC, stdCodeset, sepCM, stdModifier);
  633. }
  634. retval = _DtXlateStdToOpValue(
  635. xlationDb,platform,version,operation,
  636. stdValue, ret_opValue,NULL);
  637. if (stdValue && stdValue != stdValueBuf) free(stdValue);
  638. return retval;
  639. } /*$END$*/