client: Unbreak standalone build
[empserver] / doc / unicode
1 Empire has been extended to optionally work with Unicode.  This file
2 documents the design and implementation of this change.
3
4
5 Traditional Empire Character Set
6 --------------------------------
7
8 Empire has always used plain ASCII.  It abused the most significant
9 bit for highlighting.  Some commands cleared this bit from some input,
10 others didn't.
11
12 The restriction to the archaic ASCII character set bothered some
13 players.  It is barely serviceable for most western languages other
14 than English, and useless for everything else.  This is unbecoming for
15 a game played around the world.
16
17
18 What is Unicode?
19 ----------------
20
21 Unicode is the emerging standard character set for all multi-lingual
22 applications.  The core of Unicode is identical to the Universal
23 Character Set (UCS) defined in ISO 10646.
24
25 UCS is 31-bit.  The most commonly used characters are the range
26 0-0xFFFD, the so called Basic Multilingual Plane (BMP).
27
28 A character set can be encoded in different ways.  Popular encodings
29 are UCS-4 (four byte wide characters), UCS-2 (two byte wide
30 characters; can't represent characters outside the BMP directly), and
31 UTF-8 (a multibyte encoding).
32
33 UTF-8 has a few desirable properties.  In particular, it is a
34 compatible extension of plain (7-bit) ASCII: every ASCII string is
35 also a valid UTF-8 string, and a plain ASCII byte (an octet with the
36 most significant bit clear) in an UTF-8 string always encodes the
37 ASCII character, i.e. it is never part of a multibyte sequence.
38
39 To learn more, see the Unicode FAQ, currently at
40 <http://www.cl.cam.ac.uk/~mgk25/unicode.html>.
41
42
43 Requirements for Unicode Support in Empire
44 ------------------------------------------
45
46 * Full backward compatibility to existing clients
47
48 * Easy to support for clients
49
50 * Minimal impact on server code; no additional portability headaches
51
52 * Interoperability between old and new clients and servers
53
54
55 Principles of Design
56 --------------------
57
58 Client/server communications uses what we call external encoding:
59 either traditional Empire ASCII (7-bit ASCII plus highlighting bit) or
60 UTF-8.  The choice between the encoding is under the control of the
61 client, and defaults to Empire ASCII.  The chosen encoding is a
62 property of the session; it doesn't carry over the future sessions.
63 Highlighting is only supported for output (from server to client).
64 Highlighting in UTF-8 is done with control characters: ASCII SO (Shift
65 Out, C-n, decimal 14) starts highlighting, and ASCII SI (Shift In,
66 C-o, decimal 15) stops highlighting.  Text encoded in the client's
67 external encoding is called user text.
68
69 There are two internal encodings.  We use UTF-8 for player-player
70 communication, and Empire ASCII for everything else.  Most of the
71 time, there's no difference, because ASCII is valid UTF-8.  The
72 exception is where the highlighting bit can be used.  We call such
73 text normal text.
74
75 Input from the client needs to be translated from the client's
76 external encoding into internal encoding.  We call this input
77 filtering.  Since highlighting is not supported on input, the result
78 is always valid UTF-8.  Commands retrieve input that is player-player
79 communication directly as UTF-8.  Other input is retrieved as ASCII,
80 with non-ASCII characters replaced by '?'.
81
82 Input filtering from UTF-8 drops ASCII control characters except
83 '\t' and '\n'.
84
85 Input filtering from ASCII additionally replaces non-ASCII characters
86 by '?'.  The result is plain ASCII, which is also valid UTF-8.
87
88 Output to the client needs to be translated from internal encoding to
89 the client's external encoding.  We call this output filtering.  It is
90 integrated into the printing functions, i.e. the functions for sending
91 output to the client.  Most of them accept normal text.  Some accept
92 UTF-8, and some only plain ASCII; all of these are clearly documented.
93
94 Output filtering to ASCII doesn't change normal text.  In UTF-8 text,
95 it replaces non-ASCII characters by '?'.
96
97 Output filtering to UTF-8 doesn't change UTF-8 text.  In normal text,
98 it strips highlighting bits and inserts SI/SO control characters in
99 their place.
100
101
102 Notes for Clients
103 -----------------
104
105 Clients use session option utf-8 during login to switch the session to
106 UTF-8.  Highlighting is done differently in UTF-8 sessions.  Consult
107 doc/clients-howto for details.
108
109 An ASCII session should work just like previous server versions,
110 except for the treatment of control and non-ASCII characters.  We
111 believe the new behavior makes more sense.
112
113 How to program your host to let you use Unicode in your client's user
114 interface is platform dependent, and beyond the scope of this
115 document.
116
117 Wolfpack's empclient supports UTF-8 if it runs in a terminal that
118 understands UTF-8.  See its manual page.
119
120
121 Implementation Notes
122 --------------------
123
124 A session uses UTF-8 rather than Empire ASCII if PF_UTF8 is set in
125 member flags of struct player.  Session option utf-8 manipulates this
126 flag.
127
128 Input and output filtering code is in src/lib/subs/pr.c.
129
130 Almost all code is untouched, almost all strings are still normal
131 text.  Use of the other encodings is commented (well, we tried!).
132
133 The following commands and features have been changed to cope with
134 Unicode:
135
136 * telegram, announce, pray and turn
137
138   Get the text of the message as UTF-8.  Actually, the commands
139   themselves weren't affected, only the common code to get a
140   telex-like message, getele().
141
142 * read, wire and the automatic display of MOTD and game-down messages
143
144   Display messages as UTF-8.  The changes were limited to common
145   message display code.  Its entry point was renamed from prnf() to
146   uprnf(), to make its unusual UTF-8 argument a bit more obvious.
147
148 * flash and wall
149
150   Retrieve the text to send as UTF-8, and send it to the recipient(s)
151   with output filtering appropriate for their session applied.
152
153   The text to send can be given on the command line itself.  In this
154   case it has to be fetched from the raw command line buffer.  Since
155   that buffer is already UTF-8, no change was required.
156
157   The commands can also prompt for the text to send.  A new function
158   ugetstring() patterned after existing getstring() takes care of
159   that.
160
161   Output filtering is handled by pr_flash().