summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generic/tclClock.c64
-rw-r--r--generic/tclClockFmt.c75
-rw-r--r--generic/tclDate.h10
-rw-r--r--generic/tclDictObj.c122
-rw-r--r--generic/tclInt.h1
-rwxr-xr-xlibrary/clock.tcl83
-rw-r--r--library/init.tcl2
-rw-r--r--library/msgcat/msgcat.tcl3
8 files changed, 269 insertions, 91 deletions
diff --git a/generic/tclClock.c b/generic/tclClock.c
index 166a4b3..e066812 100644
--- a/generic/tclClock.c
+++ b/generic/tclClock.c
@@ -60,6 +60,7 @@ typedef enum ClockLiteral {
LIT_GETSYSTEMTIMEZONE,
LIT_SETUPTIMEZONE,
LIT_MCGET, LIT_TCL_CLOCK,
+ LIT_LOCALIZE_FORMAT,
#if 0
LIT_FREESCAN,
#endif
@@ -82,7 +83,8 @@ static const char *const Literals[] = {
"::tcl::clock::TZData",
"::tcl::clock::GetSystemTimeZone",
"::tcl::clock::SetupTimeZone",
- "::msgcat::mcget", "::tcl::clock"
+ "::msgcat::mcget", "::tcl::clock",
+ "::tcl::clock::LocalizeFormat"
#if 0
"::tcl::clock::FreeScan"
#endif
@@ -487,7 +489,6 @@ MODULE_SCOPE Tcl_Obj *
ClockMCDict(ClockFmtScnCmdArgs *opts)
{
ClockClientData *dataPtr = opts->clientData;
- Tcl_Obj *callargs[3];
/* if dict not yet retrieved */
if (opts->mcDictObj == NULL) {
@@ -518,6 +519,7 @@ ClockMCDict(ClockFmtScnCmdArgs *opts)
}
if (opts->mcDictObj == NULL) {
+ Tcl_Obj *callargs[3];
/* get msgcat dictionary - ::msgcat::mcget ::tcl::clock locale */
callargs[0] = dataPtr->literals[LIT_MCGET];
callargs[1] = dataPtr->literals[LIT_TCL_CLOCK];
@@ -528,6 +530,11 @@ ClockMCDict(ClockFmtScnCmdArgs *opts)
}
opts->mcDictObj = Tcl_GetObjResult(opts->interp);
+ /* be sure that object reference not increases (dict changeable) */
+ if (opts->mcDictObj->refCount > 0) {
+ /* smart reference (shared dict as object with no ref-counter) */
+ opts->mcDictObj = Tcl_DictObjSmartRef(opts->interp, opts->mcDictObj);
+ }
if ( opts->localeObj == dataPtr->CurrentLocale ) {
Tcl_SetObjRef(dataPtr->CurrentLocaleDict, opts->mcDictObj);
} else {
@@ -535,6 +542,7 @@ ClockMCDict(ClockFmtScnCmdArgs *opts)
Tcl_UnsetObjRef(dataPtr->LastUnnormUsedLocale);
Tcl_SetObjRef(dataPtr->LastUsedLocaleDict, opts->mcDictObj);
}
+ Tcl_ResetResult(opts->interp);
}
}
@@ -626,6 +634,56 @@ ClockMCGetListIdxDict(
return valObj;
}
+MODULE_SCOPE Tcl_Obj *
+ClockLocalizeFormat(
+ ClockFmtScnCmdArgs *opts)
+{
+ ClockClientData *dataPtr = opts->clientData;
+ Tcl_Obj *valObj, *keyObj;
+
+ keyObj = ClockFrmObjGetLocFmtKey(opts->interp, opts->formatObj);
+
+ if (opts->mcDictObj == NULL) {
+ ClockMCDict(opts);
+ if (opts->mcDictObj == NULL)
+ return NULL;
+ }
+
+ /* try to find in cache within mc-catalog */
+ if (Tcl_DictObjGet(NULL, opts->mcDictObj,
+ keyObj, &valObj) != TCL_OK) {
+ return NULL;
+ }
+ if (valObj == NULL) {
+ Tcl_Obj *callargs[4];
+ /* call LocalizeFormat locale format fmtkey */
+ callargs[0] = dataPtr->literals[LIT_LOCALIZE_FORMAT];
+ callargs[1] = opts->localeObj;
+ callargs[2] = opts->formatObj;
+ callargs[3] = keyObj;
+ Tcl_IncrRefCount(keyObj);
+ if (Tcl_EvalObjv(opts->interp, 4, callargs, 0) != TCL_OK
+ ) {
+ Tcl_DecrRefCount(keyObj);
+ return NULL;
+ }
+
+ valObj = Tcl_GetObjResult(opts->interp);
+
+ if (Tcl_DictObjPut(opts->interp, opts->mcDictObj,
+ keyObj, valObj) != TCL_OK
+ ) {
+ Tcl_DecrRefCount(keyObj);
+ return NULL;
+ }
+
+ Tcl_DecrRefCount(keyObj);
+ Tcl_ResetResult(opts->interp);
+ }
+
+ return (opts->formatObj = valObj);
+}
+
/*
*----------------------------------------------------------------------
*/
@@ -2936,7 +2994,7 @@ ClockScanObjCmd(
#endif
else {
/* Use compiled version of Scan - */
-
+
ret = ClockScan(clientData, interp, info, objv[1], &opts);
}
diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c
index a3c7f20..184b52a 100644
--- a/generic/tclClockFmt.c
+++ b/generic/tclClockFmt.c
@@ -308,14 +308,14 @@ Tcl_ObjType ClockFmtObjType = {
#define ObjClockFmtScn(objPtr) \
(ClockFmtScnStorage *)objPtr->internalRep.twoPtrValue.ptr1;
-#define SetObjLitStorage(objPtr, lit) \
- objPtr->internalRep.twoPtrValue.ptr2 = lit
-#define ObjLitStorage(objPtr) \
- (ClockLitStorage *)objPtr->internalRep.twoPtrValue.ptr2;
-
-#define ClockFmtObj_SetObjIntRep(objPtr, fss, lit) \
- objPtr->internalRep.twoPtrValue.ptr1 = fss, \
- objPtr->internalRep.twoPtrValue.ptr2 = lit, \
+#define SetObjLocFmtKey(objPtr, key) \
+ Tcl_InitObjRef((Tcl_Obj *)objPtr->internalRep.twoPtrValue.ptr2, key)
+#define ObjLocFmtKey(objPtr) \
+ ((Tcl_Obj *)objPtr->internalRep.twoPtrValue.ptr2)
+
+#define ClockFmtObj_SetObjIntRep(objPtr, fss, key) \
+ objPtr->internalRep.twoPtrValue.ptr1 = fss; \
+ Tcl_InitObjRef((Tcl_Obj *)objPtr->internalRep.twoPtrValue.ptr2, key); \
objPtr->typePtr = &ClockFmtObjType;
/*
@@ -327,7 +327,6 @@ ClockFmtObj_DupInternalRep(srcPtr, copyPtr)
Tcl_Obj *copyPtr;
{
ClockFmtScnStorage *fss = ObjClockFmtScn(srcPtr);
- // ClockLitStorage *lit = ObjLitStorage(srcPtr);
if (fss != NULL) {
Tcl_MutexLock(&ClockFmtMutex);
@@ -335,7 +334,7 @@ ClockFmtObj_DupInternalRep(srcPtr, copyPtr)
Tcl_MutexUnlock(&ClockFmtMutex);
}
- ClockFmtObj_SetObjIntRep(copyPtr, fss, NULL);
+ ClockFmtObj_SetObjIntRep(copyPtr, fss, ObjLocFmtKey(srcPtr));
/* if no format representation, dup string representation */
if (fss == NULL) {
@@ -352,7 +351,6 @@ ClockFmtObj_FreeInternalRep(objPtr)
Tcl_Obj *objPtr;
{
ClockFmtScnStorage *fss = ObjClockFmtScn(objPtr);
- // ClockLitStorage *lit = ObjLitStorage(objPtr);
if (fss != NULL) {
Tcl_MutexLock(&ClockFmtMutex);
/* decrement object reference count of format/scan storage */
@@ -368,7 +366,7 @@ ClockFmtObj_FreeInternalRep(objPtr)
Tcl_MutexUnlock(&ClockFmtMutex);
}
SetObjClockFmtScn(objPtr, NULL);
- SetObjLitStorage(objPtr, NULL);
+ Tcl_UnsetObjRef(ObjLocFmtKey(objPtr));
objPtr->typePtr = NULL;
};
/*
@@ -379,16 +377,18 @@ ClockFmtObj_SetFromAny(interp, objPtr)
Tcl_Interp *interp;
Tcl_Obj *objPtr;
{
- ClockFmtScnStorage *fss;
- const char *strFmt = TclGetString(objPtr);
-
- if (!strFmt || (fss = FindOrCreateFmtScnStorage(interp, strFmt)) == NULL) {
- return TCL_ERROR;
- }
-
+ /* validate string representation before free old internal represenation */
+ (void)TclGetString(objPtr);
+
+ /* free old internal represenation */
if (objPtr->typePtr && objPtr->typePtr->freeIntRepProc)
objPtr->typePtr->freeIntRepProc(objPtr);
- ClockFmtObj_SetObjIntRep(objPtr, fss, NULL);
+
+ /* initial state of format object */
+ objPtr->internalRep.twoPtrValue.ptr1 = NULL;
+ objPtr->internalRep.twoPtrValue.ptr2 = NULL;
+ objPtr->typePtr = &ClockFmtObjType;
+
return TCL_OK;
};
/*
@@ -415,6 +415,33 @@ ClockFmtObj_UpdateString(objPtr)
/*
*----------------------------------------------------------------------
+ */
+MODULE_SCOPE Tcl_Obj*
+ClockFrmObjGetLocFmtKey(
+ Tcl_Interp *interp,
+ Tcl_Obj *objPtr)
+{
+ Tcl_Obj *keyObj;
+
+ if (objPtr->typePtr != &ClockFmtObjType) {
+ if (ClockFmtObj_SetFromAny(interp, objPtr) != TCL_OK) {
+ return NULL;
+ }
+ }
+
+ keyObj = ObjLocFmtKey(objPtr);
+ if (keyObj) {
+ return keyObj;
+ }
+
+ keyObj = Tcl_ObjPrintf("FMT_%s", TclGetString(objPtr));
+ SetObjLocFmtKey(objPtr, keyObj);
+
+ return keyObj;
+}
+
+/*
+ *----------------------------------------------------------------------
*
* Tcl_GetClockFrmScnFromObj --
*
@@ -731,7 +758,7 @@ static ClockScanTokenMap ScnWordTokenMap = {
ClockScanToken *
ClockGetOrParseScanFormat(
Tcl_Interp *interp, /* Tcl interpreter */
- Tcl_Obj *formatObj) /* Format container */
+ Tcl_Obj *formatObj) /* Format container */
{
ClockFmtScnStorage *fss;
ClockScanToken *tok;
@@ -889,6 +916,12 @@ ClockScan(
unsigned short int flags = 0;
int ret = TCL_ERROR;
+ /* get localized format */
+
+ if (ClockLocalizeFormat(opts) == NULL) {
+ return TCL_ERROR;
+ }
+
if ((tok = ClockGetOrParseScanFormat(interp, opts->formatObj)) == NULL) {
return TCL_ERROR;
}
diff --git a/generic/tclDate.h b/generic/tclDate.h
index 1c51a02..62fa693 100644
--- a/generic/tclDate.h
+++ b/generic/tclDate.h
@@ -345,10 +345,6 @@ typedef struct ClockFmtScnStorage {
* stored by offset +sizeof(self) */
} ClockFmtScnStorage;
-typedef struct ClockLitStorage {
- int dummy;
-} ClockLitStorage;
-
/*
* Prototypes of module functions.
*/
@@ -366,9 +362,15 @@ MODULE_SCOPE Tcl_Obj *
ClockMCGet(ClockFmtScnCmdArgs *opts, int mcKey);
MODULE_SCOPE Tcl_Obj *
ClockMCGetListIdxDict(ClockFmtScnCmdArgs *opts, int mcKey);
+MODULE_SCOPE Tcl_Obj *
+ ClockLocalizeFormat(ClockFmtScnCmdArgs *opts);
/* tclClockFmt.c module declarations */
+MODULE_SCOPE Tcl_Obj*
+ ClockFrmObjGetLocFmtKey(Tcl_Interp *interp,
+ Tcl_Obj *objPtr);
+
MODULE_SCOPE ClockFmtScnStorage *
Tcl_GetClockFrmScnFromObj(Tcl_Interp *interp,
Tcl_Obj *objPtr);
diff --git a/generic/tclDictObj.c b/generic/tclDictObj.c
index 1115999..3944173 100644
--- a/generic/tclDictObj.c
+++ b/generic/tclDictObj.c
@@ -51,6 +51,8 @@ static int DictSetCmd(ClientData dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *const *objv);
static int DictSizeCmd(ClientData dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *const *objv);
+static int DictSmartRefCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
static int DictUnsetCmd(ClientData dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *const *objv);
static int DictUpdateCmd(ClientData dummy, Tcl_Interp *interp,
@@ -98,6 +100,7 @@ static const EnsembleImplMap implementationMap[] = {
{"replace", DictReplaceCmd, NULL, NULL, NULL, 0 },
{"set", DictSetCmd, TclCompileDictSetCmd, NULL, NULL, 0 },
{"size", DictSizeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0 },
+ {"smartref",DictSmartRefCmd,NULL, NULL, NULL, 0 },
{"unset", DictUnsetCmd, TclCompileDictUnsetCmd, NULL, NULL, 0 },
{"update", DictUpdateCmd, TclCompileDictUpdateCmd, NULL, NULL, 0 },
{"values", DictValuesCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 },
@@ -142,7 +145,7 @@ typedef struct Dict {
* the entries in the order that they are
* created. */
int epoch; /* Epoch counter */
- size_t refCount; /* Reference counter (see above) */
+ int refcount; /* Reference counter (see above) */
Tcl_Obj *chain; /* Linked list used for invalidating the
* string representations of updated nested
* dictionaries. */
@@ -392,7 +395,7 @@ DupDictInternalRep(
newDict->epoch = 0;
newDict->chain = NULL;
- newDict->refCount = 1;
+ newDict->refcount = 1;
/*
* Store in the object.
@@ -427,7 +430,8 @@ FreeDictInternalRep(
{
Dict *dict = DICT(dictPtr);
- if (dict->refCount-- <= 1) {
+ dict->refcount--;
+ if (dict->refcount <= 0) {
DeleteDict(dict);
}
dictPtr->typePtr = NULL;
@@ -712,7 +716,7 @@ SetDictFromAny(
TclFreeIntRep(objPtr);
dict->epoch = 0;
dict->chain = NULL;
- dict->refCount = 1;
+ dict->refcount = 1;
DICT(objPtr) = dict;
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
objPtr->typePtr = &tclDictType;
@@ -1116,7 +1120,7 @@ Tcl_DictObjFirst(
searchPtr->dictionaryPtr = (Tcl_Dict) dict;
searchPtr->epoch = dict->epoch;
searchPtr->next = cPtr->nextPtr;
- dict->refCount++;
+ dict->refcount++;
if (keyPtrPtr != NULL) {
*keyPtrPtr = Tcl_GetHashKey(&dict->table, &cPtr->entry);
}
@@ -1230,7 +1234,8 @@ Tcl_DictObjDone(
if (searchPtr->epoch != -1) {
searchPtr->epoch = -1;
dict = (Dict *) searchPtr->dictionaryPtr;
- if (dict->refCount-- <= 1) {
+ dict->refcount--;
+ if (dict->refcount <= 0) {
DeleteDict(dict);
}
}
@@ -1382,7 +1387,7 @@ Tcl_NewDictObj(void)
InitChainTable(dict);
dict->epoch = 0;
dict->chain = NULL;
- dict->refCount = 1;
+ dict->refcount = 1;
DICT(dictPtr) = dict;
dictPtr->internalRep.twoPtrValue.ptr2 = NULL;
dictPtr->typePtr = &tclDictType;
@@ -1432,7 +1437,7 @@ Tcl_DbNewDictObj(
InitChainTable(dict);
dict->epoch = 0;
dict->chain = NULL;
- dict->refCount = 1;
+ dict->refcount = 1;
DICT(dictPtr) = dict;
dictPtr->internalRep.twoPtrValue.ptr2 = NULL;
dictPtr->typePtr = &tclDictType;
@@ -1957,6 +1962,77 @@ DictSizeCmd(
/*
*----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+Tcl_DictObjSmartRef(
+ Tcl_Interp *interp,
+ Tcl_Obj *dictPtr)
+{
+ Tcl_Obj *result;
+ Dict *dict;
+
+ if (dictPtr->typePtr != &tclDictType
+ && SetDictFromAny(interp, dictPtr) != TCL_OK) {
+ return NULL;
+ }
+
+ dict = DICT(dictPtr);
+
+ result = Tcl_NewObj();
+ DICT(result) = dict;
+ dict->refcount++;
+ result->internalRep.twoPtrValue.ptr2 = NULL;
+ result->typePtr = &tclDictType;
+
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DictSmartRefCmd --
+ *
+ * This function implements the "dict smartref" Tcl command. See the user
+ * documentation for details on what it does, and TIP#111 for the formal
+ * specification.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DictSmartRefCmd(
+ ClientData dummy,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Tcl_Obj *result;
+ Dict *dict;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "dictionary");
+ return TCL_ERROR;
+ }
+
+ result = Tcl_DictObjSmartRef(interp, objv[1]);
+ if (result == NULL) {
+ return TCL_ERROR;
+ }
+
+ Tcl_SetObjResult(interp, result);
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
*
* DictExistsCmd --
*
@@ -2280,7 +2356,7 @@ DictAppendCmd(
Tcl_Obj *const *objv)
{
Tcl_Obj *dictPtr, *valuePtr, *resultPtr;
- int allocatedDict = 0;
+ int i, allocatedDict = 0;
if (objc < 3) {
Tcl_WrongNumArgs(interp, 1, objv, "dictVarName key ?value ...?");
@@ -2305,33 +2381,15 @@ DictAppendCmd(
if ((objc > 3) || (valuePtr == NULL)) {
/* Only go through append activites when something will change. */
- Tcl_Obj *appendObjPtr = NULL;
-
- if (objc > 3) {
- /* Something to append */
-
- if (objc == 4) {
- appendObjPtr = objv[3];
- } else if (TCL_OK != TclStringCatObjv(interp, /* inPlace */ 1,
- objc-3, objv+3, &appendObjPtr)) {
- return TCL_ERROR;
- }
- }
- if (appendObjPtr == NULL) {
- /* => (objc == 3) => (valuePtr == NULL) */
+ if (valuePtr == NULL) {
TclNewObj(valuePtr);
- } else if (valuePtr == NULL) {
- valuePtr = appendObjPtr;
- appendObjPtr = NULL;
+ } else if (Tcl_IsShared(valuePtr)) {
+ valuePtr = Tcl_DuplicateObj(valuePtr);
}
- if (appendObjPtr) {
- if (Tcl_IsShared(valuePtr)) {
- valuePtr = Tcl_DuplicateObj(valuePtr);
- }
-
- Tcl_AppendObjToObj(valuePtr, appendObjPtr);
+ for (i=3 ; i<objc ; i++) {
+ Tcl_AppendObjToObj(valuePtr, objv[i]);
}
Tcl_DictObjPut(NULL, dictPtr, objv[2], valuePtr);
diff --git a/generic/tclInt.h b/generic/tclInt.h
index 1b37d84..a569788 100644
--- a/generic/tclInt.h
+++ b/generic/tclInt.h
@@ -2905,6 +2905,7 @@ MODULE_SCOPE int TclFindDictElement(Tcl_Interp *interp,
const char *dict, int dictLength,
const char **elementPtr, const char **nextPtr,
int *sizePtr, int *literalPtr);
+MODULE_SCOPE Tcl_Obj * Tcl_DictObjSmartRef(Tcl_Interp *interp, Tcl_Obj *);
/* TIP #280 - Modified token based evulation, with line information. */
MODULE_SCOPE int TclEvalEx(Tcl_Interp *interp, const char *script,
int numBytes, int flags, int line,
diff --git a/library/clock.tcl b/library/clock.tcl
index b4632b1..4173174 100755
--- a/library/clock.tcl
+++ b/library/clock.tcl
@@ -629,6 +629,8 @@ proc ::tcl::clock::Initialize {} {
# Caches
+ variable LocaleFormats {}; # Dictionary with localized formats
+
variable LocaleNumeralCache {}; # Dictionary whose keys are locale
# names and whose values are pairs
# comprising regexes matching numerals
@@ -2323,38 +2325,59 @@ proc ::tcl::clock::LoadWindowsDateTimeFormats { locale } {
#
#----------------------------------------------------------------------
-proc ::tcl::clock::LocalizeFormat { locale format } {
+proc ::tcl::clock::LocalizeFormat { locale format {fmtkey {}} } {
+ variable LocaleFormats
+
+ if { $fmtkey eq {} } { set fmtkey FMT_$format }
+ if { [catch {
+ set locfmt [dict get $LocaleFormats $locale $fmtkey]
+ }] } {
- # message catalog key to cache this format
- set key FORMAT_$format
+ # get map list cached or build it:
+ if { [catch {
+ set mlst [dict get $LocaleFormats $locale MLST]
+ }] } {
+
+ # message catalog dictionary:
+ set mcd [::msgcat::mcget ::tcl::clock $locale]
+
+ # Handle locale-dependent format groups by mapping them out of the format
+ # string. Note that the order of the [string map] operations is
+ # significant because later formats can refer to later ones; for example
+ # %c can refer to %X, which in turn can refer to %T.
+
+ set mlst {
+ %% %%
+ %D %m/%d/%Y
+ %+ {%a %b %e %H:%M:%S %Z %Y}
+ }
+ lappend mlst %EY [string map $mlst [dict get $mcd LOCALE_YEAR_FORMAT]]
+ lappend mlst %T [string map $mlst [dict get $mcd TIME_FORMAT_24_SECS]]
+ lappend mlst %R [string map $mlst [dict get $mcd TIME_FORMAT_24]]
+ lappend mlst %r [string map $mlst [dict get $mcd TIME_FORMAT_12]]
+ lappend mlst %X [string map $mlst [dict get $mcd TIME_FORMAT]]
+ lappend mlst %EX [string map $mlst [dict get $mcd LOCALE_TIME_FORMAT]]
+ lappend mlst %x [string map $mlst [dict get $mcd DATE_FORMAT]]
+ lappend mlst %Ex [string map $mlst [dict get $mcd LOCALE_DATE_FORMAT]]
+ lappend mlst %c [string map $mlst [dict get $mcd DATE_TIME_FORMAT]]
+ lappend mlst %Ec [string map $mlst [dict get $mcd LOCALE_DATE_TIME_FORMAT]]
+
+ dict set LocaleFormats $locale MLST $mlst
+ }
- if { [::msgcat::mcexists -exactlocale -exactnamespace $key] } {
- return [mc $key]
- }
- # Handle locale-dependent format groups by mapping them out of the format
- # string. Note that the order of the [string map] operations is
- # significant because later formats can refer to later ones; for example
- # %c can refer to %X, which in turn can refer to %T.
-
- set list {
- %% %%
- %D %m/%d/%Y
- %+ {%a %b %e %H:%M:%S %Z %Y}
+ # translate:
+ set locfmt [string map $mlst $format]
+
+ # Save original format as long as possible, because of internal representation (performance)
+ if {$locfmt eq $format} {
+ set locfmt $format
+ }
+
+ # cache it:
+ dict set LocaleFormats $locale $fmtkey $locfmt
}
- lappend list %EY [string map $list [mc LOCALE_YEAR_FORMAT]]
- lappend list %T [string map $list [mc TIME_FORMAT_24_SECS]]
- lappend list %R [string map $list [mc TIME_FORMAT_24]]
- lappend list %r [string map $list [mc TIME_FORMAT_12]]
- lappend list %X [string map $list [mc TIME_FORMAT]]
- lappend list %EX [string map $list [mc LOCALE_TIME_FORMAT]]
- lappend list %x [string map $list [mc DATE_FORMAT]]
- lappend list %Ex [string map $list [mc LOCALE_DATE_FORMAT]]
- lappend list %c [string map $list [mc DATE_TIME_FORMAT]]
- lappend list %Ec [string map $list [mc LOCALE_DATE_TIME_FORMAT]]
- set format [string map $list $format]
-
- ::msgcat::mcset $locale $key $format
- return $format
+
+ return $locfmt
}
#----------------------------------------------------------------------
@@ -4437,6 +4460,7 @@ proc ::tcl::clock::ChangeCurrentLocale {args} {
proc ::tcl::clock::ClearCaches {} {
variable FormatProc
+ variable LocaleFormats
variable LocaleNumeralCache
variable TimeZoneBad
@@ -4451,6 +4475,7 @@ proc ::tcl::clock::ClearCaches {} {
}
unset -nocomplain FormatProc
+ set LocaleFormats {}
set LocaleNumeralCache {}
set TimeZoneBad {}
InitTZData
diff --git a/library/init.tcl b/library/init.tcl
index 06a9459..ef0a84a 100644
--- a/library/init.tcl
+++ b/library/init.tcl
@@ -178,7 +178,7 @@ if {[interp issafe]} {
# Auto-loading stubs for 'clock.tcl'
- foreach cmd {add format SetupTimeZone GetSystemTimeZone __org_scan} {
+ foreach cmd {add format LocalizeFormat SetupTimeZone GetSystemTimeZone __org_scan} {
proc ::tcl::clock::$cmd args {
variable TclLibDir
source -encoding utf-8 [file join $TclLibDir clock.tcl]
diff --git a/library/msgcat/msgcat.tcl b/library/msgcat/msgcat.tcl
index 3fd2cdb..a25f6c8 100644
--- a/library/msgcat/msgcat.tcl
+++ b/library/msgcat/msgcat.tcl
@@ -947,7 +947,8 @@ proc msgcat::Merge {ns locales} {
}
}
dict set Merged $ns $loc $mrgcat
- return $mrgcat
+ # return smart reference (shared dict as object with exact one ref-counter)
+ return [dict smartref $mrgcat]
}
# msgcat::Invoke --