Reference edit
- Wikipedia
- The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!), Joel Spolsky, 2003-10-08
- Characters and Combining Marks, The Unicode Consortium
- If a programmer is going to read only one document summarizing Unicode this is the one to read. It presents the key terms, such as text element, character, code unit, code point, and grapheme cluster, canonical equivalence, and compatibility decomposition.
- Unicode Standard Annex #29, Unicode Text Segmentation
- another Unicode document that is particularly relevant to programmers.
- ISO Standard 10646:2012 (and electronic inserts), Information technology -- Universal Coded Character Set (UCS)
- The ISO standard based on the character coding portions of Unicode
- ISO Amendment 10646:2012/Amd 1:2013 (and electronic inserts)
- The first amendment to ISO646:2012
- Book Review: Unicode Explained, by Jukka K. Korpela (alternate), Cameron Laird
See Also edit
- Unicode and UTF-8
- Unicode file reader
- A little Unicode editor
- i18n tester
- quickly shows what parts of Unicode are supported by your fonts
- dead keys for accents
- a tiny package allowing easier entering of accented characters
- i18n - writing for the world
- some random korean text
Resources edit
- Unicode fonts and tools for X11
- The classic X bitmap fonts in an ISO 10646-1/Unicode extension
- Multilingual Unicode TrueType Fonts on the Internet, Slavic Text Processing and Typography
- links to free TrueType fonts for larger or smaller subsets of the Unicode.
- Welcome to Computers and Writing Systems, SIL International
- source of free Unicode fonts in various languages, with a particular focus on more obscure languages and local dialects.
- I18n Guy
- a website dedicated to program internationalization
- Character Sets And Code Pages At The Push Of A Button, Tex Texin
- code charts from all over.
- ascii2uni and uni2ascii
- bidirectional conversion between Unicode and more than thirty 7-bit ASCII equivalents, including RFC 2396 URI, RFC 2045 Quoted Printable format, and the \uXXXX notation used in Tcl
- Deja Vu Fonts
- a set of free fonts based on the Vera fonts, and providing a wider range of characters
Description edit
Unicode is complex. Whereas ASCII defines 128 characters, Unicode defines 1,114,112 code points, and characters are composed of one or more code points. Unicode provides code charts, but doesn't stop there. The following things are also specified by Unicode:- character classes such as capitalization, and sort order
- Rendering hints
- composition of characters from individual codepoints, and decomposed into individual code points.
- normalization of code-point sequences
- hyphenation and line-breaking
- boundaries of words and sentences
- user interaction for processes such as text deletion and highlighting
RS: Until version 3.0, 16 bits (\u0000-\uFFFD: the "Basic Multilingual Plane", BMP) were sufficient for any Unicode. From 3.1, we must expect longer codes - up to 31 bits long, as specified in ISO 10646. Why 31 bits? Because that is the maximum that can be expressed in UTF-8: 6 bytes, omitting the taboo values \xFE and \xFF:
1111110a 10aaaaaa 10bbbbbb 10bbcccc 10ccccdd 10ddddddwhere small letters stand for "payload" bits of bytes a..d, highestmost has only 7 bitsAMG: Actually, RFC 3629 [1] limits Unicode to \u0 through \U10ffff, so it's only necessary to encode 21 bits. Consequently, a valid UTF-8 sequence can only range from 1 through 4 bytes in length. Joel Spolsky's article is wrong about this.Thus, bytes 0xf8 and greater are illegal. 0xf8 through 0xfb would have introduced a five-byte sequence. 0xfc and 0xfd would have introduced a six-byte sequence. 0xfe and 0xff have always been forbidden0xc0 and 0xc1 are also forbidden since they could only appear as the first byte of an ASCII character being encoded using two bytes, though UTF-8 requires that the shortest available encoding always be used. Tcl intentionally breaks this rule by encoding ASCII NUL as 0xc0 0x80 so that a NUL can appear in text without being interpreted as a terminator. But even in Tcl, 0xc1 is never used.So UTF-8 has 10 illegal bytes out of 256. That's 3.9%. Presumably applications (such as Tcl!) can (and do!) assign custom meaning to these bytes, but the resultant string would not be valid for data interchange.
comp.lang.tcl 2008-04:
Newsgroups: comp.lang.tcl From: [email protected] Date: Sat, 26 Apr 2008 11:55:45 -0700 (PDT) Local: Sat, Apr 26 2008 2:55 pm Subject: unicode - get character representation from \uxxx notation Hello, to show my problem see the following example: > set tcl_patchLevel 8.5.3b1 > set str "n\u00E4mlich" nämlich > set c 0xE4 > set str "n\\u[format %04.4X $ch]mlich" n\u00E4mlich How do I get the \u00E4 in the character representation let's say iso8859-1 ? > encoding convertto iso8859-1 $str Newsgroups: comp.lang.tcl From: [email protected] Date: Sat, 26 Apr 2008 14:21:27 -0700 (PDT) Local: Sat, Apr 26 2008 5:21 pm Subject: Re: unicode - get character representation from \uxxx notation To convert the hex number expressed as a string 0x00e4 to a Unicode character, use: format "%c" 0x00e4 You can then use encoding convertto to convert this to another encoding, e.g.: encoding convertto iso8859-1 [format "%c" 0x00e4]
Handling characters beyond the BMP edit
LV 2008-07-08:I've a request from a developer concerning whether Tcl is capable of handling characters larger than the Unicode BMP. His application was using tdom and it encountered the 𝒜 character, which is a script-A, unicode value 0x1D49C, which tdom reports it can't handle because it is limited to UTF-8 chars up to 3 bytes in length.What do Tcl programmers do to properly process the longer characters?Note this is in an enterprise setting. Finding a solution is critical in the publishing (web or print) arena.RS 2008-07-09: Unicode out of BMP (> U+FFFF) requires a deeper rework of Tcl and Tk: we'd need 32 bit chars and/or surrogate pairs. UTF-8 at least can deal with 31-bit Unicodes by principle.LV During July, 2008, there was some discussion in the TCT mailing list [2] (let's see how long that URL lasts...) about ways that the Tcl code itself could evolve to handle things better. But for right now, users have to face either dealing with their wide unicode via a different programming language in some way (whether converting wide characters to some other similar character, using some sort of macro representation, etc.)AMG, 2015: It's been seven years since the above discussion. What progress has been made?tcl.h contains the comment:- "Tcl is currently UCS-2 and planning UTF-16 for the Unicode string rep that Tcl_UniChar represents. Changing the size of Tcl_UniChar is not supported."
Proposed fast indexing scheme for UTF-8 edit
AMG: I invented a (hopefully) fast indexing scheme for UTF-8 strings, though it could certainly be adapted for UTF-16.Instead of the current linear time UTF-16 conversion step, make an array storing the byte index of every nth character other than the first. During lookup, divide the sought-for character index c by n, then subtract one to get the array slot which stores the byte index for the start of the segment. (No need to store the start of the first segment; it's always zero!) Then scan forward one character at a time, covering at most n-1 characters.For best performance, let n be a compile-time constant power of 2. This allows all division and modulo operations to be implemented in terms of shifts and masks.The most obvious optimization is to discard the indexing array if the byte count and the character count turn out to be equal. This means the string is ASCII, so no UTF-8 magic is required.For compression, instead of b (byte index), have the array store b-c, i.e. the number of UTF-8 continuation bytes preceding the segment. Upon lookup, add c-(c%n). This can reduce memory usage by letting strings with fewer continuation bytes use unsigned 8- or 16-bit array slots. This subtraction also makes the next optimization simpler.Take the difference between the current and next array slot values (additionally subtract n if not doing the above compression) to get the number of UTF-8 continuation bytes in the segment. During the scan, decrement this value for each continuation byte encountered. When the remaining count is zero, it's known that the remaining characters are one byte each, so jump straight to the character. If a segment is all ASCII to begin with, this optimization kicks in immediately.Another potential optimization is to scan backwards from the start of the next segment (or end of string) if the character index modulo n is greater than some threshold. Probably should put the threshold at 3*n/4 since backward UTF-8 scans have to be done one byte at a time, whereas forward scans are one whole character at a time. This can be combined with the above optimization.Yet another optimization is to remember the b result of the previous index lookup and scan relative to it if within n characters forward or whatever threshold backwards.The maximum number of array slots is (byte_count/n)-1, so allocation can be done right away if the byte count is known but not the character count. Though if the string is merely NUL-terminated and not (byte)length-counted, then it's necessary to either make two passes through the string or to allocate an initial guess then geometrically grow the allocation if the guess is short.- Let s = "Ég get etið gler án þess að meiða mig."
- Let e be the UTF-8 encoding of s. e = {c3 89 67 20 67 65 74 20 65 74 69 c3 b0 20 67 6c 65 72 20 c3 a1 6e 20 c3 be 65 73 73 20 61 c3 b0 20 6d 65 69 c3 b0 61 20 6d 69 67 2e}
- Let n = 8.
- Since n is a power of two, let n = 1<<p so p = 3. Also let m = (1<<p)-1 = 7.
- The goal is to find character at index c = 22.
- Apply the subtraction optimization to get f = {1 2 4 6}. This array is obtained by scanning through the string one character at a time and recording b-c when !(c&m)&&c.
- First, find i = c>>p = 2.
- This is nonzero, so do array lookup.
- b = f[i-1] = f[1] = 2.
- c = c&m = 6.
- If i is zero, instead set b = 0.
- Next, scan forward one character at a time until c is zero.
- At each step, decrement c and increment b by the number of leading 1-bits of e[b].
- This leaves b = 26, which is the byte index of character c = 22.