145 lines
3.8 KiB
Tcl
Vendored
145 lines
3.8 KiB
Tcl
Vendored
#----------------------------------------------------------------------
|
|
#
|
|
# icu.tcl --
|
|
#
|
|
# This file implements the portions of the [tcl::unsupported::icu]
|
|
# ensemble that are coded in Tcl.
|
|
#
|
|
#----------------------------------------------------------------------
|
|
#
|
|
# Copyright © 2024 Ashok P. Nadkarni
|
|
# See the file "license.terms" for information on usage and redistribution
|
|
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|
#
|
|
#----------------------------------------------------------------------
|
|
|
|
::tcl::unsupported::loadIcu
|
|
|
|
namespace eval ::tcl::unsupported::icu {
|
|
# Map Tcl encoding names to ICU and back. Note ICU has multiple aliases
|
|
# for the same encoding.
|
|
variable tclToIcu
|
|
variable icuToTcl
|
|
|
|
proc LogError {message} {
|
|
puts stderr $message
|
|
}
|
|
|
|
proc Init {} {
|
|
variable tclToIcu
|
|
variable icuToTcl
|
|
# There are some special cases where names do not line up
|
|
# at all. Map Tcl -> ICU
|
|
array set specialCases {
|
|
ebcdic ebcdic-cp-us
|
|
macCentEuro maccentraleurope
|
|
utf16 UTF16_PlatformEndian
|
|
utf-16be UnicodeBig
|
|
utf-16le UnicodeLittle
|
|
utf32 UTF32_PlatformEndian
|
|
}
|
|
# Ignore all errors. Do not want to hold up Tcl
|
|
# if ICU not available
|
|
if {[catch {
|
|
foreach tclName [encoding names] {
|
|
if {[catch {
|
|
set icuNames [aliases $tclName]
|
|
} erMsg]} {
|
|
LogError "Could not get aliases for $tclName: $erMsg"
|
|
continue
|
|
}
|
|
if {[llength $icuNames] == 0} {
|
|
# E.g. macGreek -> x-MacGreek
|
|
set icuNames [aliases x-$tclName]
|
|
if {[llength $icuNames] == 0} {
|
|
# Still no joy, check for special cases
|
|
if {[info exists specialCases($tclName)]} {
|
|
set icuNames [aliases $specialCases($tclName)]
|
|
}
|
|
}
|
|
}
|
|
# If the Tcl name is also an ICU name use it else use
|
|
# the first name which is the canonical ICU name
|
|
set pos [lsearch -exact -nocase $icuNames $tclName]
|
|
if {$pos >= 0} {
|
|
lappend tclToIcu($tclName) [lindex $icuNames $pos] {*}[lreplace $icuNames $pos $pos]
|
|
} else {
|
|
set tclToIcu($tclName) $icuNames
|
|
}
|
|
foreach icuName $icuNames {
|
|
lappend icuToTcl($icuName) $tclName
|
|
}
|
|
}
|
|
} errMsg]} {
|
|
LogError $errMsg
|
|
}
|
|
array default set tclToIcu ""
|
|
array default set icuToTcl ""
|
|
|
|
# Redefine ourselves to no-op.
|
|
proc Init {} {}
|
|
}
|
|
# Primarily used during development
|
|
proc MappedIcuNames {{pat *}} {
|
|
Init
|
|
variable icuToTcl
|
|
return [array names icuToTcl $pat]
|
|
}
|
|
# Primarily used during development
|
|
proc UnmappedIcuNames {{pat *}} {
|
|
Init
|
|
variable icuToTcl
|
|
set unmappedNames {}
|
|
foreach icuName [converters] {
|
|
if {[llength [icuToTcl $icuName]] == 0} {
|
|
lappend unmappedNames $icuName
|
|
}
|
|
foreach alias [aliases $icuName] {
|
|
if {[llength [icuToTcl $alias]] == 0} {
|
|
lappend unmappedNames $alias
|
|
}
|
|
}
|
|
}
|
|
# Aliases can be duplicates. Remove
|
|
return [lsort -unique [lsearch -inline -all $unmappedNames $pat]]
|
|
}
|
|
# Primarily used during development
|
|
proc UnmappedTclNames {{pat *}} {
|
|
Init
|
|
variable tclToIcu
|
|
set unmappedNames {}
|
|
foreach tclName [encoding names] {
|
|
# Note entry will always exist. Check if empty
|
|
if {[llength [tclToIcu $tclName]] == 0} {
|
|
lappend unmappedNames $tclName
|
|
}
|
|
}
|
|
return [lsearch -inline -all $unmappedNames $pat]
|
|
}
|
|
|
|
# Returns the Tcl equivalent of an ICU encoding name or
|
|
# the empty string in case not found.
|
|
proc icuToTcl {icuName} {
|
|
Init
|
|
proc icuToTcl {icuName} {
|
|
variable icuToTcl
|
|
return [lindex $icuToTcl($icuName) 0]
|
|
}
|
|
icuToTcl $icuName
|
|
}
|
|
|
|
# Returns the ICU equivalent of an Tcl encoding name or
|
|
# the empty string in case not found.
|
|
proc tclToIcu {tclName} {
|
|
Init
|
|
proc tclToIcu {tclName} {
|
|
variable tclToIcu
|
|
return [lindex $tclToIcu($tclName) 0]
|
|
}
|
|
tclToIcu $tclName
|
|
}
|
|
|
|
|
|
namespace export {[a-z]*}
|
|
namespace ensemble create
|
|
}
|