mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
746 lines
26 KiB
C
746 lines
26 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these librararies and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/* $TOG: LocaleXlate.c /main/14 1999/10/14 15:58:52 mgreess $ */
|
|
/************************************<+>*************************************
|
|
****************************************************************************
|
|
$FILEBEG$: LocaleXlate.c
|
|
$PROJECT$: CDE 1.0
|
|
$COMPONENT$: DtLcx service
|
|
$1LINER$: Locale translation routines
|
|
$COPYRIGHT$:
|
|
(c) Copyright 1993, 1994 Hewlett-Packard Company
|
|
(c) Copyright 1993, 1994 International Business Machines Corp.
|
|
(c) Copyright 1993, 1994 Sun Microsystems, Inc.
|
|
(c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of Novell, Inc.
|
|
$END$
|
|
****************************************************************************
|
|
************************************<+>*************************************/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#if defined(sun)
|
|
#include <sys/utsname.h>
|
|
#endif
|
|
#include <limits.h>
|
|
#define X_INCLUDE_PWD_H
|
|
#define XOS_USE_XT_LOCKING
|
|
#include <X11/Xos_r.h> /* for getpw... */
|
|
#include <sys/param.h> /* MAXPATHLEN */
|
|
#include <sys/utsname.h> /* for uname */
|
|
#include <unistd.h>
|
|
|
|
/* for Xrm */
|
|
#include <X11/Intrinsic.h>
|
|
#include <X11/Xresource.h>
|
|
|
|
#include "XlationSvc.h"
|
|
/*=================================================================
|
|
$SHAREDBEG$: This is the header file that should appear in all
|
|
DtLcx topics
|
|
=======================================================$SKIP$======*/
|
|
/*$INCLUDE$*/
|
|
#include "LocaleXlate.h"
|
|
/*$END$*/
|
|
|
|
/*========================================================*/
|
|
/*================ Introductory Info =====================*/
|
|
/*========================================================*/
|
|
|
|
#if DOC
|
|
/*========================================================*/
|
|
$INTROBEG$: _DtLcx family
|
|
$1LINER$: Translate locale and codeset strings to/from any platform
|
|
$SUMMARY$:
|
|
The _DtLcx family of routines enables the translation of a
|
|
locale string from any platform into a standard locale string,
|
|
and from standard locale string to the locale string of any platform.
|
|
|
|
This is useful because each platform, and in fact within
|
|
version ranges of some platforms, different strings are used
|
|
that have the same meaning. This becomes a problem as soon as
|
|
any of these strings is stored in a file. If the file is
|
|
opened on a platform for which the string has no meaning,
|
|
that functionality supported by using the string is lost.
|
|
With the _DtLcx service, the string can be translated into
|
|
a string appropriate to the current platform.
|
|
|
|
Standard locale strings are based on the XoJIG proposed strings,
|
|
but with a slightly altered syntax to adhere to the constraints
|
|
of the translation database.
|
|
|
|
The following are the current set of standard strings:
|
|
|
|
_DtLcx uses the _DtXlate translation database services,
|
|
but the _DtLcx routines provide a high-level interface to
|
|
the _DtXlate routines tuned to locales. They allow any
|
|
component of a locale to be translated individually.
|
|
|
|
The _DtLcxOpenAllDbs() routine opens all the predefined
|
|
locale translation databases that can be found. These
|
|
may are the following:
|
|
/usr/dt/config/svc/<platform>.lcx
|
|
/etc/dt/config/svc/<platform>.lcx
|
|
$HOME/.dt/config/svc/<platform>.lcx
|
|
|
|
Alternatively, the DTLCXSEARCHPATH directory may be used
|
|
to specify a colon separated search path. Relative paths
|
|
in the search path are relative to the current working
|
|
directory.
|
|
|
|
One of the nice features of the _DtLcx service is that
|
|
the translation database is designed for extension. So
|
|
if new locales need to be supported, a system admin
|
|
or user can add the specifications to the appropriate
|
|
file and it will be immediately accessible.
|
|
|
|
/*=$END$================================================*/
|
|
#endif
|
|
|
|
#if DOC
|
|
/*========================================================*/
|
|
$INTROBEG$: _DtLcx translation table syntax
|
|
$1LINER$: translation table syntax for _DtLcx
|
|
$SUMMARY$:
|
|
|
|
BNF Syntax of Locale Translation Specification
|
|
==============================================
|
|
|
|
For the full syntax of translation specifications,
|
|
see the _DtXlate documentation.
|
|
|
|
<stdvalue> ::= <langterr>[.<codeset>[.<modifier>]]
|
|
<langterr> ::= <identifier> | <matchall>
|
|
<codeset> ::= <identifier> | <matchall>
|
|
<modifier> ::= <identifier> | <matchall>
|
|
<opvalue> ::= (<vischars>|<metachar>)+ | '"'(<anychar>|<metachar>)+'"'
|
|
|
|
Semantics of the Translation Specification
|
|
==========================================
|
|
|
|
For a full description of translation table semantics,
|
|
refer to the _DtXlatedocumentation.
|
|
|
|
<operations> : a CDE-standardized identifier for the operation(s) to
|
|
which the value applies. The operation(s) need not be supported by every
|
|
platform, but CDE must have standardized an identifier for the operation
|
|
in order for it to be used. More than one identifier may be included by
|
|
concatenating them using the ',' separator, eg. "iconv1,iconv3".
|
|
|
|
_DtLcx defines a number of standard operation strings that use
|
|
locales. Users of _DtLcx should use the constants beginning
|
|
_DtLCX_OPER... to specify a particular operation.
|
|
|
|
<stdvalue> : a sequence of one or more '.'-separated CDE-standardizd
|
|
identifiers or matchall characters. This represents the canonical
|
|
string used as a standard representation of a semantic value that
|
|
may vary in different situations.
|
|
|
|
<langterr> : a CDE-standardized identifier for a language and territory
|
|
for which the operation is valid. The language and territory must be
|
|
supported or irrelvant for the operations, as qualified for platform
|
|
and version, e.g. en_US. The identifier need not be the identifier
|
|
used on any actual platform to specify language and territory.
|
|
|
|
<codeset> : a CDE-standardized identifier for a codeset for which the
|
|
operation is valid. The codeset must be supported or irrelvant for
|
|
the operations, as qualified for platform and version, e.g. iso88591.
|
|
The identifier need not be the identifier used on any actual platform
|
|
to specify codeset.
|
|
|
|
<modifier> : a CDE-standardized identifier for a locale modifier.
|
|
The modifier must be supported or irrelvant for the operations,
|
|
as qualified for platform and version. The identifier need not be
|
|
the identifier used on any actual platform to specify modifiers.
|
|
|
|
<opvalue> : can be used in three ways. When a straight translation,
|
|
it is string that is matched against a query locale value to determine
|
|
the standard value of the locale. When a OpToStd translation,
|
|
the string is a regular expression that is matched against the
|
|
query string. When a StdToOp translation, the string is a
|
|
replacement value for the std value and may contain subexpression
|
|
replacement specifiers.
|
|
|
|
$EXAMPLE$:
|
|
These are some example specs:
|
|
|
|
HP-UX.900-999.setlocale.=.en_US.HP-ROMAN8: american
|
|
HP-UX.900-999.setlocale.=.en_US.ISO-8859-1: american.iso88591
|
|
HP-UX.900-999.setlocale.=.nl_NL.HP-ROMAN8: dutch
|
|
HP-UX.900-999.setlocale.=.nl_NL.ISO-8859-1: dutch.iso88591
|
|
/*=$END$================================================*/
|
|
#endif
|
|
|
|
#if DOC
|
|
/*========================================================*/
|
|
$INTROBEG$: _DtLcx example usage
|
|
$1LINER$: Examples of how to _DtLcx
|
|
$EXAMPLE$:
|
|
#include <LocaleXlate.h>
|
|
main()
|
|
{
|
|
_DtXlateDb db = NULL;
|
|
int ret;
|
|
char plat[_DtPLATFORM_MAX_LEN];
|
|
int execver;
|
|
int compver;
|
|
char * val = NULL;
|
|
char * str = NULL;
|
|
char * val1 = NULL;
|
|
char * val2 = NULL;
|
|
char * val3 = NULL;
|
|
|
|
ret = _DtLcxOpenAllDbs(&db);
|
|
|
|
ret = _DtXlateGetXlateEnv(db,plat,&execver,&compver);
|
|
printf("Platform: %s\nExec Ver: %d\nComp Ver: %d\n",
|
|
plat,execver,compver);
|
|
ret = _DtLcxXlateStdToOp(db,plat,compver,DtLCX_OPER_SETLOCALE,
|
|
str="en_US.hp-roman8",NULL,NULL,NULL,&val);
|
|
if (ret==0) printf("setlocale(%s) xlation=%s\n", str, val);
|
|
else printf("no xlation\n", val);
|
|
|
|
ret = _DtLcxXlateStdToOp(db,plat,compver,DtLCX_OPER_SETLOCALE,
|
|
str="en_US.?",NULL,NULL,NULL,&val);
|
|
if (ret==0) printf("setlocale(%s) xlation=%s\n", str, val);
|
|
else printf("no xlation\n", val);
|
|
|
|
ret = _DtLcxXlateOpToStd(db,plat,execver,DtLCX_OPER_SETLOCALE,
|
|
str="american",&val,&val1,&val2,&val3);
|
|
if (ret==0) printf("setlocale(%s) xlation=%s; %s; %s; %s\n",
|
|
str, val,val1,val2,val3);
|
|
else printf("no xlation\n", val,val1,val2,val3);
|
|
|
|
ret = _DtLcxXlateOpToStd(db,plat,execver,DtLCX_OPER_SETLOCALE,
|
|
str="dutch@fold",&val,&val1,&val2,&val3);
|
|
if (ret==0) printf("setlocale(%s) xlation=%s; %s; %s; %s\n",
|
|
str, val,val1,val2,val3);
|
|
|
|
ret = _DtLcxCloseDb(&db);
|
|
}
|
|
/*=$END$================================================*/
|
|
#endif
|
|
|
|
|
|
/*========================================================*/
|
|
/*====================== Constants =======================*/
|
|
/*========================================================*/
|
|
|
|
/*=============== private =================*/
|
|
/* A "random" number used to ensure that the Db has been initalized */
|
|
#define PATH_SEPARATOR ':'
|
|
#define EOS '\0'
|
|
#define DIR_SLASH '/'
|
|
#define DIR_SLASH_STR "/"
|
|
|
|
#define MATCHALL_STR "?"
|
|
#define DOT_STR "."
|
|
|
|
/*=============== internal =================*/
|
|
#define DTLCXSEARCHPATH "DTLCXSEARCHPATH"
|
|
|
|
#ifndef CDE_CONFIGURATION_TOP
|
|
#define CDE_CONFIGURATION_TOP "/etc/dt"
|
|
#endif
|
|
|
|
#ifndef CDE_INSTALLATION_TOP
|
|
#define CDE_INSTALLATION_TOP "/usr/dt"
|
|
#endif
|
|
|
|
#ifndef CDE_USER_TOP
|
|
#define CDE_USER_TOP ".dt"
|
|
#endif
|
|
|
|
#define DtLCX_USER_PATH s_LcxUserPath
|
|
#define DtLCX_INSTALL_AND_CONFIG_PATHS s_LcxInstallAndConfigPaths
|
|
|
|
#define _DtLCX_INSTALL_DB_DIR CDE_INSTALLATION_TOP "/config/svc/"
|
|
|
|
/* This is the file type of a _DtLcx file */
|
|
#define _DtLCX_DATABASE_TYPE ".lcx"
|
|
/* This is the name of the fallback _DtLcx file */
|
|
#define _DtLCX_DATABASE_FALLBACK ("dtcomplete" _DtLCX_DATABASE_TYPE)
|
|
/* This is the name of the CDE standard _DtLcx file */
|
|
#define _DtLCX_DATABASE_CDE ("CDE" _DtLCX_DATABASE_TYPE)
|
|
|
|
/*========================================================*/
|
|
/*====================== Variables =======================*/
|
|
/*========================================================*/
|
|
|
|
static char s_LcxUserPath[] = CDE_USER_TOP "/config/svc";
|
|
static char s_LcxInstallAndConfigPaths[] =
|
|
CDE_INSTALLATION_TOP "/config/svc:"
|
|
CDE_CONFIGURATION_TOP "/config/svc:";
|
|
|
|
/*========================================================*/
|
|
/*================== Private routines ====================*/
|
|
/*========================================================*/
|
|
|
|
#if DOC
|
|
/*========================================================*/
|
|
/*
|
|
$PFUNBEG$: GetHomeDirPath()
|
|
$1LINER$: Retrieves path to current user's home directory
|
|
$SUMMARY$:
|
|
Looks for first the HOME and then USER environment
|
|
variables. If these are not set, uses the password
|
|
info to get the user's home directory.
|
|
$ARGS$:
|
|
outptr: pts to string allocated by caller to hold the home dir path
|
|
Generally, the string should be at least MAXPATHLEN+1 in size.
|
|
max: maximum number of bytes allowed (including ending bytes).
|
|
$RETURNS$:
|
|
*/
|
|
/*================================================$SKIP$==*/
|
|
#endif
|
|
static
|
|
void GetHomeDirPath(
|
|
char * outptr,
|
|
unsigned int max)
|
|
{ /*$CODE$*/
|
|
int uid;
|
|
char * ptr = NULL;
|
|
_Xgetpwparams pwd_buf;
|
|
struct passwd * pwd_ret;
|
|
|
|
if((ptr = (char *)getenv("HOME")) == NULL)
|
|
{
|
|
if((ptr = (char *)getenv("USER")) != NULL)
|
|
pwd_ret = _XGetpwnam(ptr, pwd_buf);
|
|
else
|
|
{
|
|
uid = getuid();
|
|
pwd_ret = _XGetpwuid(uid, pwd_buf);
|
|
}
|
|
if (pwd_ret != NULL)
|
|
ptr = pwd_ret->pw_dir;
|
|
else
|
|
ptr = NULL;
|
|
}
|
|
|
|
if (ptr && strlen(ptr))
|
|
{
|
|
strncpy(outptr, ptr, max-1);
|
|
outptr[max-1] = '\0';
|
|
}
|
|
else outptr[0] = '\0' ;
|
|
} /*$END$*/
|
|
|
|
|
|
/*========================================================*/
|
|
/*================ Public DtLcx routines =================*/
|
|
/*========================================================*/
|
|
|
|
|
|
#if DOC
|
|
/*========================================================*/
|
|
$FUNBEG$: _DtLcxOpenAllDbs()
|
|
$1LINER$: Open and merge all locale translation databases that can be found
|
|
$SUMMARY$:
|
|
DtLcxOpenAllDbs() locates all translation databases
|
|
named "<platform>.lcx" present in the DTLCXSEARCHPATH
|
|
directories. If none exist, the file "dtcomplete.lcx"
|
|
is tried in those directories. Finally, the database "CDE.lcx"
|
|
is merged into those databases already loaded.
|
|
|
|
The <platform> string is taken from uname(2), which is the
|
|
same string returned by the command 'uname -s'. For example,
|
|
on HP-UX platforms, the string is "HPUX", so the translation
|
|
databases to be loaded must be named "HPUX.lcx".
|
|
|
|
By default, the search paths are:
|
|
DTLCXSEARCHPATH = "/usr/dt/config/svc:" \
|
|
"/etc/dt/config/svc:" \
|
|
"$HOME/.dt/config/svc"
|
|
|
|
Alternatively, the DTLCXSEARCHPATH directory may be used
|
|
to specify a colon separated search path. Relative paths
|
|
in the search path are relative to the current working
|
|
directory.
|
|
$ARGS$:
|
|
$RETURNS$:
|
|
Returns the return value of _DtXlateOpenAllDbs()
|
|
/*================================================$SKIP$==*/
|
|
#endif
|
|
|
|
int _DtLcxOpenAllDbs(
|
|
_DtXlateDb * ret_db)
|
|
{ /*$CODE$*/
|
|
char * paths;
|
|
char * dbPaths;
|
|
struct utsname names;
|
|
int ret = 0;
|
|
int globRet = -1;
|
|
int len;
|
|
char lcxfile[100];
|
|
char homePath[MAXPATHLEN];
|
|
_DtXlateDb cde_db = NULL;
|
|
|
|
#define MAXSHORTFNAMELEN 14
|
|
|
|
/* get host specifics and generate platform-specific lcx file name */
|
|
uname(&names);
|
|
len = MAXSHORTFNAMELEN - strlen(_DtLCX_DATABASE_TYPE);
|
|
strncpy(lcxfile,names.sysname,len);
|
|
lcxfile[len-1] = EOS;
|
|
strcat(lcxfile,_DtLCX_DATABASE_TYPE); /* e.g. HP-UX.lcx */
|
|
|
|
/* get paths for LCX */
|
|
paths = getenv(DTLCXSEARCHPATH);
|
|
if (NULL != paths && paths[0] != EOS)
|
|
{
|
|
dbPaths = strdup(paths);
|
|
}
|
|
else
|
|
{
|
|
const char *slash;
|
|
char *end;
|
|
|
|
/* no DTLCXSEARCHPATH; build a default path */
|
|
GetHomeDirPath(homePath, MAXPATHLEN);
|
|
end = homePath + strlen(homePath);
|
|
_DtMBStrrchr(homePath,DIR_SLASH,-1,&slash);
|
|
if ((end - 1) != slash && end < homePath + MAXPATHLEN - 2 )
|
|
{
|
|
*end++ = DIR_SLASH;
|
|
*end = EOS;
|
|
}
|
|
if (end < homePath + MAXPATHLEN - strlen(DtLCX_USER_PATH) - 1)
|
|
strcat(homePath,DtLCX_USER_PATH);
|
|
|
|
dbPaths = malloc(sizeof(char) *
|
|
(strlen(homePath)+strlen(DtLCX_INSTALL_AND_CONFIG_PATHS)+5));
|
|
if (dbPaths)
|
|
sprintf(dbPaths,"%s:%s",DtLCX_INSTALL_AND_CONFIG_PATHS,homePath);
|
|
}
|
|
|
|
/* open all dbs of filename found in paths */
|
|
globRet = _DtXlateOpenAllDbs(dbPaths,lcxfile, ret_db);
|
|
if (globRet != 0)
|
|
{ /* on failure */
|
|
/* open all dbs of the fallback filename found in paths */
|
|
globRet = _DtXlateOpenAllDbs(dbPaths,_DtLCX_DATABASE_FALLBACK, ret_db);
|
|
}
|
|
|
|
/* merge in the CDE standard translations database */
|
|
ret = _DtXlateOpenAllDbs(dbPaths,_DtLCX_DATABASE_CDE, &cde_db);
|
|
|
|
if (ret == 0)
|
|
{
|
|
globRet = 0;
|
|
_DtXlateMergeDbs(&cde_db,ret_db); /* cde_db get's closed by the merge */
|
|
}
|
|
else
|
|
_DtXlateCloseDb(&cde_db);
|
|
|
|
if(dbPaths) free(dbPaths);
|
|
return globRet;
|
|
} /*$END$*/
|
|
|
|
#if DOC
|
|
/*========================================================*/
|
|
$FUNBEG$: _DtLcxCloseDb()
|
|
$1LINER$: Close an open locale translation database
|
|
$SUMMARY$:
|
|
_DtLcxCloseDb() releases all memory associated with
|
|
the translation database. Further use of the database
|
|
object is an error.
|
|
$ARGS$:
|
|
$RETURNS$:
|
|
0: database was valid and has been closed
|
|
-1: invalid database pointer
|
|
|
|
$DEF$:
|
|
int _DtLcxCloseDb(
|
|
_DtXlateDb * io_db)
|
|
$NOTE$: the current implementation is a macro call to
|
|
_DtXlateCloseDb().
|
|
/*================================================$SKIP$==*/
|
|
#endif
|
|
|
|
|
|
#if DOC
|
|
/*========================================================*/
|
|
/*
|
|
$FUNBEG$: _DtLcxXlateOpToStd()
|
|
$1LINER$: Translate an operation-specific locale to a standard locale
|
|
$SUMMARY$:
|
|
_DtLcxXlateOpToStd() is designed to allow a locale string
|
|
that is specific to some platform, version, and operation to be
|
|
translated to a CDE standard locale. For example, a locale
|
|
string stored in a file on systemA and recovered by an application
|
|
on systemB can be translated into a CDE standard locale by the
|
|
application on system B.
|
|
|
|
The xlationDb is the database to use for the translation.
|
|
It must have been opened with a call to _DtLcxOpenAllDbs().
|
|
|
|
The platform and version arguments can be used to specify
|
|
systemA if the information is known. The platform value
|
|
should be one of _DtPLATFORM_xxx. If platform is unknown,
|
|
use _DtPLATFORM_UNKNOWN, and if version is unknown, use -1.
|
|
|
|
The operation is an optional argument. If the operation is known
|
|
from which the opValue originated or for which it was intended
|
|
for use on systemA, the operation may be specified using the
|
|
appropriate DtLCX_OPER_xxx constant. If the operation is unknown,
|
|
it should be NULL.
|
|
|
|
The opValue is the systemA locale string recovered by the
|
|
application on systemB and which should be translated. It is
|
|
an error if it is NULL.
|
|
|
|
Zero or more of the ret_xxx arguments may be NULL values.
|
|
If they are NULL, that value is not determined. For
|
|
non-NULL ret_xxx arguments, the string value of each
|
|
is allocated using malloc() and the pointer is assigned
|
|
at the location pointed to by the argument. The caller
|
|
function should free the memory wth free() when it is
|
|
no longer needed. The ret_xxx arguments have the following
|
|
values.
|
|
|
|
The ret_stdLocale points to a caller-owned string with
|
|
the CDE standard equivalent to opValue. This value is the '.'-
|
|
separated concatenation of the <langterr> and <codeset> fields
|
|
of the specification. If <langterr> or <codeset> is the matchall
|
|
character, that value and the '.' separator are dropped.
|
|
|
|
The ret_stdLangTerr points to a caller-owned string with
|
|
the CDE standard equivalent of the opValue's language and
|
|
territory. If <langterr> or <codeset> in the translation
|
|
specification is the matchall character, the value is the
|
|
empty string.
|
|
|
|
The ret_stdCodeset points to a caller-owned string with
|
|
the CDE standard equivalent of the opValue's codeset.
|
|
If <codeset> in the translation specification is the matchall
|
|
character, the value is the empty string.
|
|
|
|
The ret_stdModifier points to a caller-owned string with
|
|
the CDE standard equivalent of the opValue's modifier.
|
|
If <modifier> in the translation specification is the matchall
|
|
character or not present, the value is the empty string.
|
|
$ARGS$:
|
|
xlation_db: a translation database
|
|
platform: the platform string (see _DtXlateGetXlateEnv())
|
|
version: the version number (see _DtXlateGetXlateEnv())
|
|
operation: the operation of interest, e.g. "setlocale"
|
|
opValue: the operation-specific value pattern
|
|
ret_stdLocale: location where ptr to standard locale string is stored
|
|
ret_stdLangTerr:location where ptr to standard lang+terr string is stored
|
|
ret_stdCodeset: location where ptr to standard codeset string is stored
|
|
ret_stdModifier:location where ptr to standard modifier string is stored
|
|
$RETURNS$:
|
|
Return values are those of _DtXlateOpToStd()
|
|
*/
|
|
/*================================================$SKIP$==*/
|
|
#endif
|
|
|
|
int _DtLcxXlateOpToStd(
|
|
const _DtXlateDb xlationDb,
|
|
const char * platform,
|
|
const int version,
|
|
const char * operation,
|
|
const char * opValue,
|
|
char * * ret_stdLocale,
|
|
char * * ret_stdLangTerr,
|
|
char * * ret_stdCodeset,
|
|
char * * ret_stdModifier)
|
|
{ /*$CODE$*/
|
|
int ret;
|
|
char * stdValue = NULL;
|
|
Boolean freeStdValue = True;
|
|
int scanned = 0;
|
|
char langterr[50];
|
|
char codeset[50];
|
|
char mod[50];
|
|
|
|
/* do the translation */
|
|
ret = _DtXlateOpToStdValue(xlationDb,platform,version,operation,opValue,
|
|
&stdValue,NULL);
|
|
|
|
/* std locale string syntax: langterr.codeset.modifier */
|
|
/* parse into the desire chunks */
|
|
if (ret == 0 && stdValue)
|
|
scanned = sscanf(stdValue,"%[^.].%[^.].%s",langterr,codeset,mod);
|
|
|
|
/* locale string is just the std value */
|
|
|
|
if ( ret_stdLocale )
|
|
{ *ret_stdLocale = stdValue; freeStdValue = False; }
|
|
if ( ret_stdLangTerr)
|
|
{ *ret_stdLangTerr = ( scanned >= 1 ? strdup(langterr) : NULL); }
|
|
if ( ret_stdCodeset )
|
|
{ *ret_stdCodeset = ( scanned >= 2 ? strdup(codeset) : NULL); }
|
|
if ( ret_stdModifier )
|
|
{ *ret_stdModifier = ( scanned >= 3 ? strdup(mod) : NULL); }
|
|
|
|
if (freeStdValue && NULL != stdValue) free(stdValue);
|
|
return ret;
|
|
} /*$END$*/
|
|
|
|
|
|
#if DOC
|
|
/*========================================================*/
|
|
$FUNBEG$: _DtLcxXlateStdToOp()
|
|
$1LINER$: Translate a standard locale to an operation-specific one
|
|
$SUMMARY$:
|
|
_DtLcxXlateStdToOp() is designed to allow a locale string
|
|
that is the CDE standard locale to be translated to the appropriate
|
|
string for some platform, version, and operation. For example, a
|
|
CDE locale string stored in a file on systemA and recovered by an
|
|
application on systemB can be translated into a platform- and
|
|
operation-specific locale by the application on system B.
|
|
|
|
_DtLcxXlateStdToOp() takes a number of query qualifiers
|
|
and determines the best translation that matches them. The
|
|
routine allocates memory for the resulting operation-specific
|
|
locale using malloc() and stores the pointer to it at the
|
|
location pointed to by ret_opValue. If the query qualifiers
|
|
do not uniquely identify a translation specification, the
|
|
specification used is chosen at random from those that match.
|
|
[Random selection is an artifact of using XrmEnumerateDatabase()
|
|
to process the contents of the table--entries are not presented
|
|
to the processing routine in a pre-specified order.]
|
|
|
|
The xlationDb is the database to use for the translation.
|
|
It must have been opened with a call to _DtLcxOpenAllDbs().
|
|
|
|
The platform and version arguments are optional. If the desired
|
|
platform is the current one for the executing application,
|
|
use _DtPLATFORM_CURRENT, and if version is the current one
|
|
for the application, use -1.
|
|
|
|
The operation is a required argument, and should be selected
|
|
from the DtLCX_OPER_xxx constants.
|
|
|
|
The stdLocale is the CDE standard locale string, such as the
|
|
one recovered using _DtLcxXlateOpToStd(). The value is
|
|
the '.'-separated concatenation of the <langterr>, <codeset>,
|
|
and <modifier> fields, or it may be NULL. The stdLocale string
|
|
alone *or* any combination of stdLangTerr, stdCodeset, and
|
|
stdModifier strings may be specified for the translation, but
|
|
not both.
|
|
|
|
The stdLangTerr, stdCodeset, and stdModifier are the CDE strings,
|
|
such as the one recovered using _DtLcxXlateOpToStd(). The
|
|
strings are valid across CDE platforms and across operations.
|
|
The stdLangTerr, stdCodeset, or stdModifier string may be used
|
|
alone *or* in any combination with each other, but not with the
|
|
stdLocale string. The values may also be NULL.
|
|
$ARGS$:
|
|
xlationDb: a translation database
|
|
platform: the platform string (see _DtXlateGetXlateEnv())
|
|
version: the version number (see _DtXlateGetXlateEnv())
|
|
operation: the operation of interest, e.g. "setlocale"
|
|
stdValue: the standard value pattern
|
|
stdLocale: standard locale strin
|
|
stdLangTerr: standard lang+terr string
|
|
stdCodeset: standard codeset string
|
|
stdModifier: standard modifier string
|
|
ret_opValue: location where ptr to translated string is stored
|
|
$RETURNS$:
|
|
-1: if all stdXxx strings have NULL values
|
|
plus the return values are those of _DtXlateStdToOp()
|
|
/*================================================$SKIP$==*/
|
|
#endif
|
|
|
|
int _DtLcxXlateStdToOp(
|
|
const _DtXlateDb xlationDb,
|
|
const char * platform,
|
|
const int version,
|
|
const char * operation,
|
|
const char * stdLocale,
|
|
const char * stdLangTerr,
|
|
const char * stdCodeset,
|
|
const char * stdModifier,
|
|
char * * ret_opValue)
|
|
{ /*$CODE$*/
|
|
#define DTLCXXLATE_STDTOOP_BUFSIZE 256
|
|
char stdValueBuf[DTLCXXLATE_STDTOOP_BUFSIZE];
|
|
char *stdValue = stdValueBuf;
|
|
char empty = EOS;
|
|
char * matchall = MATCHALL_STR;
|
|
char * dot = DOT_STR;
|
|
char * sepLC = ∅
|
|
char * sepCM = ∅
|
|
int retval;
|
|
|
|
if (stdLocale)
|
|
{
|
|
if (strlen(stdLocale) >= DTLCXXLATE_STDTOOP_BUFSIZE)
|
|
stdValue = malloc(strlen(stdLocale) + 1);
|
|
else
|
|
stdValue = stdValueBuf;
|
|
|
|
stdValue[0] = EOS;
|
|
strcpy(stdValue, stdLocale);
|
|
}
|
|
else
|
|
{
|
|
int need = 0;
|
|
int bytes_needed = 0;
|
|
|
|
#define NEED_LANGTERR 0x01
|
|
#define NEED_CODESET 0x02
|
|
#define NEED_MODIFIER 0x04
|
|
|
|
if (stdLangTerr) need = NEED_LANGTERR;
|
|
if (stdCodeset) need = NEED_LANGTERR | NEED_CODESET;
|
|
if (stdModifier) need = NEED_LANGTERR | NEED_CODESET | NEED_MODIFIER;
|
|
|
|
if (need == 0) return -1; /* RETURN: need a pattern */
|
|
|
|
/* only include matchalls for those that are needed */
|
|
/* This is needed because of the manner of scoring matches.
|
|
If unnecessary matchall's are present, that can detract
|
|
from the score. */
|
|
if (need & NEED_LANGTERR)
|
|
{ stdLangTerr = (stdLangTerr ? stdLangTerr : matchall); }
|
|
if (need & (NEED_LANGTERR | NEED_CODESET))
|
|
{ stdCodeset = (stdCodeset ? stdCodeset : matchall); sepLC = dot; }
|
|
if (need & (NEED_LANGTERR | NEED_CODESET | NEED_MODIFIER))
|
|
{ stdModifier = (stdModifier ? stdModifier : matchall); sepCM = dot; }
|
|
|
|
bytes_needed =
|
|
strlen(stdLangTerr) + strlen(sepLC) + strlen(stdCodeset) +
|
|
strlen(sepCM) + strlen(stdModifier) + 1;
|
|
|
|
if (bytes_needed > DTLCXXLATE_STDTOOP_BUFSIZE)
|
|
stdValue = malloc(bytes_needed);
|
|
else
|
|
stdValue = stdValueBuf;
|
|
|
|
/* generate the std value string */
|
|
stdValue[0] = EOS;
|
|
sprintf(stdValue,
|
|
"%s%s%s%s%s",
|
|
stdLangTerr, sepLC, stdCodeset, sepCM, stdModifier);
|
|
}
|
|
|
|
retval = _DtXlateStdToOpValue(
|
|
xlationDb,platform,version,operation,
|
|
stdValue, ret_opValue,NULL);
|
|
if (stdValue && stdValue != stdValueBuf) free(stdValue);
|
|
return retval;
|
|
} /*$END$*/
|