Char contents
Char Is Of Case.
The following decides whether a character c belongs to case case, where 0 means lower case and 1 means upper. c is interpreted according to the character casing chart in UnicodeData.i6t, which means, it will be ZSCII for the Z-machine and Unicode for Glulx.
15[ CharIsOfCase c case
16 i tab min max len par;
17 if (c<'A') rfalse;
18 if (case == 0) {
19 if ((c >= 'a') && (c <= 'z')) rtrue;
20 tab = CharCasingChart0;
21 } else {
22 if ((c >= 'A') && (c <= 'Z')) rtrue;
23 tab = CharCasingChart1;
24 }
25 if (c<128) rfalse;
26 while (tab-->i) {
27 min = tab-->i; i++;
28 len = tab-->i; i++;
29 i++;
30 par = 0;
31 if (len<0) { par = 1; len = -len; }
32 if (c < min) rfalse;
33 if (c < min+len) {
34 if (par) { if ((c-min) % 2 == 0) rtrue; }
35 else { rtrue; }
36 }
37 }
38 rfalse;
39];
Char To Case.
And the following converts character c to the desired case, or returns it unchanged if it is not a letter with variant casings.
46[ CharToCase c case
47 i tab min max len par del f;
48 if (c<'A') return c;
49 if (case == 1) {
50 if ((c >= 'a') && (c <= 'z')) return c-32;
51 tab = CharCasingChart0;
52 } else {
53 if ((c >= 'A') && (c <= 'Z')) return c+32;
54 tab = CharCasingChart1;
55 }
56 if (c<128) return c;
57 while (tab-->i) {
58 min = tab-->i; i++;
59 len = tab-->i; i++;
60 del = tab-->i; i++;
61 par = 0;
62 if (len<0) { par = 1; len = -len; }
63 if (c < min) return c;
64 if (c < min+len) {
65 f = false;
66 if (par) { if ((c-min) % 2 == 0) f = true; }
67 else { f = true; }
68 if (f) {
69 if (del == UNIC_NCT) return c;
70 return c+del;
71 }
72 }
73 }
74 return c;
75];
Reversing Case.
It's convenient to provide this relatively fast routine to reverse the case of a letter since this is an operation used frequently in regular expression matching (see RegExp.i6t).
83#IFDEF TARGET_ZCODE;
84[ TEXT_TY_RevCase ch;
85 if (ch<'A') return ch;
86 if ((ch >= 'a') && (ch <= 'z')) return ch-'a'+'A';
87 if ((ch >= 'A') && (ch <= 'Z')) return ch-'A'+'a';
88 if (ch<128) return ch;
89 if ((ch >= 155) && (ch <= 157)) return ch+3;
90 if ((ch >= 158) && (ch <= 160)) return ch-3;
91 if ((ch >= 164) && (ch <= 165)) return ch+3;
92 if ((ch >= 167) && (ch <= 168)) return ch-3;
93 if ((ch >= 169) && (ch <= 174)) return ch+6;
94 if ((ch >= 175) && (ch <= 180)) return ch-6;
95 if ((ch >= 181) && (ch <= 185)) return ch+5;
96 if ((ch >= 186) && (ch <= 190)) return ch-5;
97 if ((ch >= 191) && (ch <= 195)) return ch+5;
98 if ((ch >= 196) && (ch <= 200)) return ch-5;
99 if (ch == 201) return 202;
100 if (ch == 202) return 201;
101 if (ch == 203) return 204;
102 if (ch == 204) return 203;
103 if ((ch >= 205) && (ch <= 207)) return ch+3;
104 if ((ch >= 208) && (ch <= 210)) return ch-3;
105 if (ch == 211) return 212;
106 if (ch == 212) return 211;
107 if (ch == 213) return 214;
108 if (ch == 214) return 213;
109 if (ch == 215 or 216) return ch+2;
110 if (ch == 217 or 218) return ch-2;
111 if (ch == 220) return 221;
112 if (ch == 221) return 220;
113 return ch;
114];
115#IFNOT;
116[ TEXT_TY_RevCase ch;
117 if (ch<'A') return ch;
118 if ((ch >= 'a') && (ch <= 'z')) return ch-'a'+'A';
119 if ((ch >= 'A') && (ch <= 'Z')) return ch-'A'+'a';
120 if (ch<128) return ch;
121 if (CharIsOfCase(ch, 0)) return CharToCase(ch, 1);
122 if (CharIsOfCase(ch, 1)) return CharToCase(ch, 0);
123 return ch;
124];
125#ENDIF;
Testing.
Not actually used: simply for testing the tables.
131[ CharTestCases case i j;
132 for (i=32: i<$E0; i++) {
133 if ((i>=127) && (i<155)) continue;
134 print i, " - ", (char) i, " -";
135 if (CharIsOfCase(i, 0)) print " lower";
136 if (CharIsOfCase(i, 1)) print " upper";
137 j = CharToCase(i, 0); if (j ~= i) print " tolower: ", (char) j;
138 j = CharToCase(i, 1); if (j ~= i) print " toupper: ", (char) j;
139 print "^";
140 }
141];