llvm-mos-sdk
charset.h
Go to the documentation of this file.
1 // Copyright 2023 LLVM-MOS Project Licensed under the Apache License,
2 // Version 2.0 with LLVM Exceptions. See
3 // https://github.com/llvm-mos/llvm-mos-sdk/blob/main/LICENSE for license
4 // information.
5 
6 #if __cplusplus < 202002L
7 #error charset support requies C++20
8 #else
9 #ifndef _CHARSET_H
10 #define _CHARSET_H
11 
12 #include <cstddef>
13 
14 namespace charset_impl {
15 
16 template <size_t N> struct UnshiftedString {
17  char Str[N]{};
18 
19  constexpr UnshiftedString(char const (&Src)[N]) {
20  for (size_t I = 0; I < N; ++I) {
21  if (Src[I] >= 0x80)
22  throw "use U prefix for unicode string literals";
23  Str[I] = TranslateUnicode(Src[I]);
24  }
25  }
26 
27  constexpr UnshiftedString(char16_t const (&Src)[N]) {
28  for (size_t I = 0; I < N; ++I) {
29  if (Src[I] >= 0xD800 && Src[I] <= 0xDFFF)
30  throw "use U prefix for unicode string literals";
31  Str[I] = TranslateUnicode(Src[I]);
32  }
33  }
34 
35  constexpr UnshiftedString(char32_t const (&Src)[N]) {
36  for (size_t I = 0; I < N; ++I)
37  Str[I] = TranslateUnicode(Src[I]);
38  }
39 
40  constexpr char TranslateUnicode(char32_t C) {
41  switch (C) {
42  default:
43  throw "Unsupported";
44 
45  // C0 control codes are uninterpreted.
46  case 0x0000 ... 0x001f:
47  return C;
48 
49  // Name: Map from Commodore 64/128 (interchange) primary character set to
50  // Unicode
51 
52  // Date: 2018 April 20
53 
54  // Original Author: Rebecca Bettencourt <support@kreativekorp.com>
55 
56  case 0x0020:
57  return 0x20; // SPACE
58  case 0x0021:
59  return 0x21; // EXCLAMATION MARK
60  case 0x0022:
61  return 0x22; // QUOTATION MARK
62  case 0x0023:
63  return 0x23; // NUMBER SIGN
64  case 0x0024:
65  return 0x24; // DOLLAR SIGN
66  case 0x0025:
67  return 0x25; // PERCENT SIGN
68  case 0x0026:
69  return 0x26; // AMPERSAND
70  case 0x0027:
71  return 0x27; // APOSTROPHE
72  case 0x0028:
73  return 0x28; // LEFT PARENTHESIS
74  case 0x0029:
75  return 0x29; // RIGHT PARENTHESIS
76  case 0x002A:
77  return 0x2A; // ASTERISK
78  case 0x002B:
79  return 0x2B; // PLUS SIGN
80  case 0x002C:
81  return 0x2C; // COMMA
82  case 0x002D:
83  return 0x2D; // HYPHEN-MINUS
84  case 0x002E:
85  return 0x2E; // FULL STOP
86  case 0x002F:
87  return 0x2F; // SOLIDUS
88  case 0x0030:
89  return 0x30; // DIGIT ZERO
90  case 0x0031:
91  return 0x31; // DIGIT ONE
92  case 0x0032:
93  return 0x32; // DIGIT TWO
94  case 0x0033:
95  return 0x33; // DIGIT THREE
96  case 0x0034:
97  return 0x34; // DIGIT FOUR
98  case 0x0035:
99  return 0x35; // DIGIT FIVE
100  case 0x0036:
101  return 0x36; // DIGIT SIX
102  case 0x0037:
103  return 0x37; // DIGIT SEVEN
104  case 0x0038:
105  return 0x38; // DIGIT EIGHT
106  case 0x0039:
107  return 0x39; // DIGIT NINE
108  case 0x003A:
109  return 0x3A; // COLON
110  case 0x003B:
111  return 0x3B; // SEMICOLON
112  case 0x003C:
113  return 0x3C; // LESS-THAN SIGN
114  case 0x003D:
115  return 0x3D; // EQUALS SIGN
116  case 0x003E:
117  return 0x3E; // GREATER-THAN SIGN
118  case 0x003F:
119  return 0x3F; // QUESTION MARK
120  case 0x0040:
121  return 0x40; // COMMERCIAL AT
122  case 0x0041:
123  return 0x41; // LATIN CAPITAL LETTER A
124  case 0x0042:
125  return 0x42; // LATIN CAPITAL LETTER B
126  case 0x0043:
127  return 0x43; // LATIN CAPITAL LETTER C
128  case 0x0044:
129  return 0x44; // LATIN CAPITAL LETTER D
130  case 0x0045:
131  return 0x45; // LATIN CAPITAL LETTER E
132  case 0x0046:
133  return 0x46; // LATIN CAPITAL LETTER F
134  case 0x0047:
135  return 0x47; // LATIN CAPITAL LETTER G
136  case 0x0048:
137  return 0x48; // LATIN CAPITAL LETTER H
138  case 0x0049:
139  return 0x49; // LATIN CAPITAL LETTER I
140  case 0x004A:
141  return 0x4A; // LATIN CAPITAL LETTER J
142  case 0x004B:
143  return 0x4B; // LATIN CAPITAL LETTER K
144  case 0x004C:
145  return 0x4C; // LATIN CAPITAL LETTER L
146  case 0x004D:
147  return 0x4D; // LATIN CAPITAL LETTER M
148  case 0x004E:
149  return 0x4E; // LATIN CAPITAL LETTER N
150  case 0x004F:
151  return 0x4F; // LATIN CAPITAL LETTER O
152  case 0x0050:
153  return 0x50; // LATIN CAPITAL LETTER P
154  case 0x0051:
155  return 0x51; // LATIN CAPITAL LETTER Q
156  case 0x0052:
157  return 0x52; // LATIN CAPITAL LETTER R
158  case 0x0053:
159  return 0x53; // LATIN CAPITAL LETTER S
160  case 0x0054:
161  return 0x54; // LATIN CAPITAL LETTER T
162  case 0x0055:
163  return 0x55; // LATIN CAPITAL LETTER U
164  case 0x0056:
165  return 0x56; // LATIN CAPITAL LETTER V
166  case 0x0057:
167  return 0x57; // LATIN CAPITAL LETTER W
168  case 0x0058:
169  return 0x58; // LATIN CAPITAL LETTER X
170  case 0x0059:
171  return 0x59; // LATIN CAPITAL LETTER Y
172  case 0x005A:
173  return 0x5A; // LATIN CAPITAL LETTER Z
174  case 0x005B:
175  return 0x5B; // LEFT SQUARE BRACKET
176  case 0x00A3:
177  return 0x5C; // POUND SIGN
178  case 0x005D:
179  return 0x5D; // RIGHT SQUARE BRACKET
180  case 0x2191:
181  return 0x5E; // UPWARDS ARROW
182  case 0x2190:
183  return 0x5F; // LEFTWARDS ARROW
184  case 0x2500:
185  return 0x60; // BOX DRAWINGS LIGHT HORIZONTAL
186  case 0x2660:
187  return 0x61; // BLACK SPADE SUIT
188  case 0x1FB72:
189  return 0x62; // VERTICAL ONE EIGHTH BLOCK-4
190  case 0x1FB78:
191  return 0x63; // HORIZONTAL ONE EIGHTH BLOCK-4
192  case 0x1FB77:
193  return 0x64; // HORIZONTAL ONE EIGHTH BLOCK-3
194  case 0x1FB76:
195  return 0x65; // HORIZONTAL ONE EIGHTH BLOCK-2
196  case 0x1FB7A:
197  return 0x66; // HORIZONTAL ONE EIGHTH BLOCK-6
198  case 0x1FB71:
199  return 0x67; // VERTICAL ONE EIGHTH BLOCK-3
200  case 0x1FB74:
201  return 0x68; // VERTICAL ONE EIGHTH BLOCK-6
202  case 0x256E:
203  return 0x69; // BOX DRAWINGS LIGHT ARC DOWN AND LEFT
204  case 0x2570:
205  return 0x6A; // BOX DRAWINGS LIGHT ARC UP AND RIGHT
206  case 0x256F:
207  return 0x6B; // BOX DRAWINGS LIGHT ARC UP AND LEFT
208  case 0x1FB7C:
209  return 0x6C; // LEFT AND LOWER ONE EIGHTH BLOCK
210  case 0x2572:
211  return 0x6D; // BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER
212  // RIGHT
213  case 0x2571:
214  return 0x6E; // BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER
215  // LEFT
216  case 0x1FB7D:
217  return 0x6F; // LEFT AND UPPER ONE EIGHTH BLOCK
218  case 0x1FB7E:
219  return 0x70; // RIGHT AND UPPER ONE EIGHTH BLOCK
220  case 0x2022:
221  case 0x25CF:
222  return 0x71; // BULLET (or 0x25CF BLACK CIRCLE)
223  case 0x1FB7B:
224  return 0x72; // HORIZONTAL ONE EIGHTH BLOCK-7
225  case 0x2665:
226  return 0x73; // BLACK HEART SUIT
227  case 0x1FB70:
228  return 0x74; // VERTICAL ONE EIGHTH BLOCK-2
229  case 0x256D:
230  return 0x75; // BOX DRAWINGS LIGHT ARC DOWN AND RIGHT
231  case 0x2573:
232  return 0x76; // BOX DRAWINGS LIGHT DIAGONAL CROSS
233  case 0x25CB:
234  case 0x25E6:
235  return 0x77; // WHITE CIRCLE (or 0x25E6 WHITE BULLET)
236  case 0x2663:
237  return 0x78; // BLACK CLUB SUIT
238  case 0x1FB75:
239  return 0x79; // VERTICAL ONE EIGHTH BLOCK-7
240  case 0x2666:
241  return 0x7A; // BLACK DIAMOND SUIT
242  case 0x253C:
243  return 0x7B; // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
244  case 0x1FB8C:
245  return 0x7C; // LEFT HALF MEDIUM SHADE
246  case 0x2502:
247  return 0x7D; // BOX DRAWINGS LIGHT VERTICAL
248  case 0x03C0:
249  return 0x7E; // GREEK SMALL LETTER PI
250  case 0x25E5:
251  return 0x7F; // BLACK UPPER RIGHT TRIANGLE
252  case 0x00A0:
253  return 0xA0; // NO-BREAK SPACE
254  case 0x258C:
255  return 0xA1; // LEFT HALF BLOCK
256  case 0x2584:
257  return 0xA2; // LOWER HALF BLOCK
258  case 0x2594:
259  return 0xA3; // UPPER ONE EIGHTH BLOCK
260  case 0x2581:
261  return 0xA4; // LOWER ONE EIGHTH BLOCK
262  case 0x258F:
263  return 0xA5; // LEFT ONE EIGHTH BLOCK
264  case 0x2592:
265  return 0xA6; // MEDIUM SHADE
266  case 0x2595:
267  return 0xA7; // RIGHT ONE EIGHTH BLOCK
268  case 0x1FB8F:
269  return 0xA8; // LOWER HALF MEDIUM SHADE
270  case 0x25E4:
271  return 0xA9; // BLACK UPPER LEFT TRIANGLE
272  case 0x1FB87:
273  return 0xAA; // RIGHT ONE QUARTER BLOCK
274  case 0x251C:
275  return 0xAB; // BOX DRAWINGS LIGHT VERTICAL AND RIGHT
276  case 0x2597:
277  return 0xAC; // QUADRANT LOWER RIGHT
278  case 0x2514:
279  return 0xAD; // BOX DRAWINGS LIGHT UP AND RIGHT
280  case 0x2510:
281  return 0xAE; // BOX DRAWINGS LIGHT DOWN AND LEFT
282  case 0x2582:
283  return 0xAF; // LOWER ONE QUARTER BLOCK
284  case 0x250C:
285  return 0xB0; // BOX DRAWINGS LIGHT DOWN AND RIGHT
286  case 0x2534:
287  return 0xB1; // BOX DRAWINGS LIGHT UP AND HORIZONTAL
288  case 0x252C:
289  return 0xB2; // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
290  case 0x2524:
291  return 0xB3; // BOX DRAWINGS LIGHT VERTICAL AND LEFT
292  case 0x258E:
293  return 0xB4; // LEFT ONE QUARTER BLOCK
294  case 0x258D:
295  return 0xB5; // LEFT THREE EIGHTHS BLOCK
296  case 0x1FB88:
297  return 0xB6; // RIGHT THREE EIGHTHS BLOCK
298  case 0x1FB82:
299  return 0xB7; // UPPER ONE QUARTER BLOCK
300  case 0x1FB83:
301  return 0xB8; // UPPER THREE EIGHTHS BLOCK
302  case 0x2583:
303  return 0xB9; // LOWER THREE EIGHTHS BLOCK
304  case 0x1FB7F:
305  return 0xBA; // RIGHT AND LOWER ONE EIGHTH BLOCK
306  case 0x2596:
307  return 0xBB; // QUADRANT LOWER LEFT
308  case 0x259D:
309  return 0xBC; // QUADRANT UPPER RIGHT
310  case 0x2518:
311  return 0xBD; // BOX DRAWINGS LIGHT UP AND LEFT
312  case 0x2598:
313  return 0xBE; // QUADRANT UPPER LEFT
314  case 0x259A:
315  return 0xBF; // QUADRANT UPPER LEFT AND LOWER RIGHT
316  }
317  }
318 };
319 
320 template <size_t N> struct ShiftedString {
321  char Str[N]{};
322 
323  constexpr ShiftedString(char const (&Src)[N]) {
324  for (size_t I = 0; I < N; ++I) {
325  if (Src[I] >= 0x80)
326  throw "use U prefix for unicode string literals";
327  Str[I] = TranslateUnicode(Src[I]);
328  }
329  }
330 
331  constexpr ShiftedString(char16_t const (&Src)[N]) {
332  for (size_t I = 0; I < N; ++I) {
333  if (Src[I] >= 0xD800 && Src[I] <= 0xDFFF)
334  throw "use U prefix for unicode string literals";
335  Str[I] = TranslateUnicode(Src[I]);
336  }
337  }
338 
339  constexpr ShiftedString(char32_t const (&Src)[N]) {
340  for (size_t I = 0; I < N; ++I)
341  Str[I] = TranslateUnicode(Src[I]);
342  }
343 
344  constexpr char TranslateUnicode(char32_t C) {
345  switch (C) {
346  default:
347  throw "Unsupported";
348 
349  // C0 control codes are uninterpreted.
350  case 0x0000 ... 0x001f:
351  return C;
352 
353  // Name: Map from Commodore 64/128 (interchange) alternate character set
354  // to Unicode
355 
356  // Date: 2018 October 11
357 
358  // Original Author: Rebecca Bettencourt <support@kreativekorp.com>
359 
360  case 0x0020:
361  return 0x20; // SPACE
362  case 0x0021:
363  return 0x21; // EXCLAMATION MARK
364  case 0x0022:
365  return 0x22; // QUOTATION MARK
366  case 0x0023:
367  return 0x23; // NUMBER SIGN
368  case 0x0024:
369  return 0x24; // DOLLAR SIGN
370  case 0x0025:
371  return 0x25; // PERCENT SIGN
372  case 0x0026:
373  return 0x26; // AMPERSAND
374  case 0x0027:
375  return 0x27; // APOSTROPHE
376  case 0x0028:
377  return 0x28; // LEFT PARENTHESIS
378  case 0x0029:
379  return 0x29; // RIGHT PARENTHESIS
380  case 0x002A:
381  return 0x2A; // ASTERISK
382  case 0x002B:
383  return 0x2B; // PLUS SIGN
384  case 0x002C:
385  return 0x2C; // COMMA
386  case 0x002D:
387  return 0x2D; // HYPHEN-MINUS
388  case 0x002E:
389  return 0x2E; // FULL STOP
390  case 0x002F:
391  return 0x2F; // SOLIDUS
392  case 0x0030:
393  return 0x30; // DIGIT ZERO
394  case 0x0031:
395  return 0x31; // DIGIT ONE
396  case 0x0032:
397  return 0x32; // DIGIT TWO
398  case 0x0033:
399  return 0x33; // DIGIT THREE
400  case 0x0034:
401  return 0x34; // DIGIT FOUR
402  case 0x0035:
403  return 0x35; // DIGIT FIVE
404  case 0x0036:
405  return 0x36; // DIGIT SIX
406  case 0x0037:
407  return 0x37; // DIGIT SEVEN
408  case 0x0038:
409  return 0x38; // DIGIT EIGHT
410  case 0x0039:
411  return 0x39; // DIGIT NINE
412  case 0x003A:
413  return 0x3A; // COLON
414  case 0x003B:
415  return 0x3B; // SEMICOLON
416  case 0x003C:
417  return 0x3C; // LESS-THAN SIGN
418  case 0x003D:
419  return 0x3D; // EQUALS SIGN
420  case 0x003E:
421  return 0x3E; // GREATER-THAN SIGN
422  case 0x003F:
423  return 0x3F; // QUESTION MARK
424  case 0x0040:
425  return 0x40; // COMMERCIAL AT
426  case 0x0061:
427  return 0x41; // LATIN SMALL LETTER A
428  case 0x0062:
429  return 0x42; // LATIN SMALL LETTER B
430  case 0x0063:
431  return 0x43; // LATIN SMALL LETTER C
432  case 0x0064:
433  return 0x44; // LATIN SMALL LETTER D
434  case 0x0065:
435  return 0x45; // LATIN SMALL LETTER E
436  case 0x0066:
437  return 0x46; // LATIN SMALL LETTER F
438  case 0x0067:
439  return 0x47; // LATIN SMALL LETTER G
440  case 0x0068:
441  return 0x48; // LATIN SMALL LETTER H
442  case 0x0069:
443  return 0x49; // LATIN SMALL LETTER I
444  case 0x006A:
445  return 0x4A; // LATIN SMALL LETTER J
446  case 0x006B:
447  return 0x4B; // LATIN SMALL LETTER K
448  case 0x006C:
449  return 0x4C; // LATIN SMALL LETTER L
450  case 0x006D:
451  return 0x4D; // LATIN SMALL LETTER M
452  case 0x006E:
453  return 0x4E; // LATIN SMALL LETTER N
454  case 0x006F:
455  return 0x4F; // LATIN SMALL LETTER O
456  case 0x0070:
457  return 0x50; // LATIN SMALL LETTER P
458  case 0x0071:
459  return 0x51; // LATIN SMALL LETTER Q
460  case 0x0072:
461  return 0x52; // LATIN SMALL LETTER R
462  case 0x0073:
463  return 0x53; // LATIN SMALL LETTER S
464  case 0x0074:
465  return 0x54; // LATIN SMALL LETTER T
466  case 0x0075:
467  return 0x55; // LATIN SMALL LETTER U
468  case 0x0076:
469  return 0x56; // LATIN SMALL LETTER V
470  case 0x0077:
471  return 0x57; // LATIN SMALL LETTER W
472  case 0x0078:
473  return 0x58; // LATIN SMALL LETTER X
474  case 0x0079:
475  return 0x59; // LATIN SMALL LETTER Y
476  case 0x007A:
477  return 0x5A; // LATIN SMALL LETTER Z
478  case 0x005B:
479  return 0x5B; // LEFT SQUARE BRACKET
480  case 0x00A3:
481  return 0x5C; // POUND SIGN
482  case 0x005D:
483  return 0x5D; // RIGHT SQUARE BRACKET
484  case 0x2191:
485  return 0x5E; // UPWARDS ARROW
486  case 0x2190:
487  return 0x5F; // LEFTWARDS ARROW
488  case 0x2500:
489  return 0x60; // BOX DRAWINGS LIGHT HORIZONTAL
490  case 0x0041:
491  return 0x61; // LATIN CAPITAL LETTER A
492  case 0x0042:
493  return 0x62; // LATIN CAPITAL LETTER B
494  case 0x0043:
495  return 0x63; // LATIN CAPITAL LETTER C
496  case 0x0044:
497  return 0x64; // LATIN CAPITAL LETTER D
498  case 0x0045:
499  return 0x65; // LATIN CAPITAL LETTER E
500  case 0x0046:
501  return 0x66; // LATIN CAPITAL LETTER F
502  case 0x0047:
503  return 0x67; // LATIN CAPITAL LETTER G
504  case 0x0048:
505  return 0x68; // LATIN CAPITAL LETTER H
506  case 0x0049:
507  return 0x69; // LATIN CAPITAL LETTER I
508  case 0x004A:
509  return 0x6A; // LATIN CAPITAL LETTER J
510  case 0x004B:
511  return 0x6B; // LATIN CAPITAL LETTER K
512  case 0x004C:
513  return 0x6C; // LATIN CAPITAL LETTER L
514  case 0x004D:
515  return 0x6D; // LATIN CAPITAL LETTER M
516  case 0x004E:
517  return 0x6E; // LATIN CAPITAL LETTER N
518  case 0x004F:
519  return 0x6F; // LATIN CAPITAL LETTER O
520  case 0x0050:
521  return 0x70; // LATIN CAPITAL LETTER P
522  case 0x0051:
523  return 0x71; // LATIN CAPITAL LETTER Q
524  case 0x0052:
525  return 0x72; // LATIN CAPITAL LETTER R
526  case 0x0053:
527  return 0x73; // LATIN CAPITAL LETTER S
528  case 0x0054:
529  return 0x74; // LATIN CAPITAL LETTER T
530  case 0x0055:
531  return 0x75; // LATIN CAPITAL LETTER U
532  case 0x0056:
533  return 0x76; // LATIN CAPITAL LETTER V
534  case 0x0057:
535  return 0x77; // LATIN CAPITAL LETTER W
536  case 0x0058:
537  return 0x78; // LATIN CAPITAL LETTER X
538  case 0x0059:
539  return 0x79; // LATIN CAPITAL LETTER Y
540  case 0x005A:
541  return 0x7A; // LATIN CAPITAL LETTER Z
542  case 0x253C:
543  return 0x7B; // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
544  case 0x1FB8C:
545  return 0x7C; // LEFT HALF MEDIUM SHADE
546  case 0x2502:
547  return 0x7D; // BOX DRAWINGS LIGHT VERTICAL
548  case 0x1FB96:
549  return 0x7E; // INVERSE CHECKER BOARD FILL
550  case 0x1FB98:
551  return 0x7F; // UPPER LEFT TO LOWER RIGHT FILL
552  case 0x00A0:
553  return 0xA0; // NO-BREAK SPACE
554  case 0x258C:
555  return 0xA1; // LEFT HALF BLOCK
556  case 0x2584:
557  return 0xA2; // LOWER HALF BLOCK
558  case 0x2594:
559  return 0xA3; // UPPER ONE EIGHTH BLOCK
560  case 0x2581:
561  return 0xA4; // LOWER ONE EIGHTH BLOCK
562  case 0x258F:
563  return 0xA5; // LEFT ONE EIGHTH BLOCK
564  case 0x2592:
565  return 0xA6; // MEDIUM SHADE
566  case 0x2595:
567  return 0xA7; // RIGHT ONE EIGHTH BLOCK
568  case 0x1FB8F:
569  return 0xA8; // LOWER HALF MEDIUM SHADE
570  case 0x1FB99:
571  return 0xA9; // UPPER RIGHT TO LOWER LEFT FILL
572  case 0x1FB87:
573  return 0xAA; // RIGHT ONE QUARTER BLOCK
574  case 0x251C:
575  return 0xAB; // BOX DRAWINGS LIGHT VERTICAL AND RIGHT
576  case 0x2597:
577  return 0xAC; // QUADRANT LOWER RIGHT
578  case 0x2514:
579  return 0xAD; // BOX DRAWINGS LIGHT UP AND RIGHT
580  case 0x2510:
581  return 0xAE; // BOX DRAWINGS LIGHT DOWN AND LEFT
582  case 0x2582:
583  return 0xAF; // LOWER ONE QUARTER BLOCK
584  case 0x250C:
585  return 0xB0; // BOX DRAWINGS LIGHT DOWN AND RIGHT
586  case 0x2534:
587  return 0xB1; // BOX DRAWINGS LIGHT UP AND HORIZONTAL
588  case 0x252C:
589  return 0xB2; // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
590  case 0x2524:
591  return 0xB3; // BOX DRAWINGS LIGHT VERTICAL AND LEFT
592  case 0x258E:
593  return 0xB4; // LEFT ONE QUARTER BLOCK
594  case 0x258D:
595  return 0xB5; // LEFT THREE EIGHTHS BLOCK
596  case 0x1FB88:
597  return 0xB6; // RIGHT THREE EIGHTHS BLOCK
598  case 0x1FB82:
599  return 0xB7; // UPPER ONE QUARTER BLOCK
600  case 0x1FB83:
601  return 0xB8; // UPPER THREE EIGHTHS BLOCK
602  case 0x2583:
603  return 0xB9; // LOWER THREE EIGHTHS BLOCK
604  case 0x2713:
605  return 0xBA; // CHECK MARK
606  case 0x2596:
607  return 0xBB; // QUADRANT LOWER LEFT
608  case 0x259D:
609  return 0xBC; // QUADRANT UPPER RIGHT
610  case 0x2518:
611  return 0xBD; // BOX DRAWINGS LIGHT UP AND LEFT
612  case 0x2598:
613  return 0xBE; // QUADRANT UPPER LEFT
614  case 0x259A:
615  return 0xBF; // QUADRANT UPPER LEFT AND LOWER RIGHT
616  }
617  };
618 };
619 
620 template <size_t N> struct UnshiftedVideoString {
621  char Str[N]{};
622 
623  constexpr UnshiftedVideoString(char const (&Src)[N]) {
624  for (size_t I = 0; I < N; ++I) {
625  if (Src[I] >= 0x80)
626  throw "use U prefix for unicode string literals";
627  Str[I] = TranslateUnicode(Src[I]);
628  }
629  }
630 
631  constexpr UnshiftedVideoString(char16_t const (&Src)[N]) {
632  for (size_t I = 0; I < N; ++I) {
633  if (Src[I] >= 0xD800 && Src[I] <= 0xDFFF)
634  throw "use U prefix for unicode string literals";
635  Str[I] = TranslateUnicode(Src[I]);
636  }
637  }
638 
639  constexpr UnshiftedVideoString(char32_t const (&Src)[N]) {
640  for (size_t I = 0; I < N; ++I)
641  Str[I] = TranslateUnicode(Src[I]);
642  }
643 
644  constexpr char TranslateUnicode(char32_t C) {
645  switch (C) {
646  default:
647  throw "Unsupported";
648 
649  // Preserve NUL
650  case 0x0000:
651  return 0x00;
652 
653  // Name: Map from Commodore 64/128 (video) primary character set to
654  // Unicode
655 
656  // Date: 2018 April 20
657 
658  // Author: Rebecca Bettencourt <support@kreativekorp.com>
659 
660  case 0x0040:
661  return 0x00; // COMMERCIAL AT
662  case 0x0041:
663  return 0x01; // LATIN CAPITAL LETTER A
664  case 0x0042:
665  return 0x02; // LATIN CAPITAL LETTER B
666  case 0x0043:
667  return 0x03; // LATIN CAPITAL LETTER C
668  case 0x0044:
669  return 0x04; // LATIN CAPITAL LETTER D
670  case 0x0045:
671  return 0x05; // LATIN CAPITAL LETTER E
672  case 0x0046:
673  return 0x06; // LATIN CAPITAL LETTER F
674  case 0x0047:
675  return 0x07; // LATIN CAPITAL LETTER G
676  case 0x0048:
677  return 0x08; // LATIN CAPITAL LETTER H
678  case 0x0049:
679  return 0x09; // LATIN CAPITAL LETTER I
680  case 0x004A:
681  return 0x0A; // LATIN CAPITAL LETTER J
682  case 0x004B:
683  return 0x0B; // LATIN CAPITAL LETTER K
684  case 0x004C:
685  return 0x0C; // LATIN CAPITAL LETTER L
686  case 0x004D:
687  return 0x0D; // LATIN CAPITAL LETTER M
688  case 0x004E:
689  return 0x0E; // LATIN CAPITAL LETTER N
690  case 0x004F:
691  return 0x0F; // LATIN CAPITAL LETTER O
692  case 0x0050:
693  return 0x10; // LATIN CAPITAL LETTER P
694  case 0x0051:
695  return 0x11; // LATIN CAPITAL LETTER Q
696  case 0x0052:
697  return 0x12; // LATIN CAPITAL LETTER R
698  case 0x0053:
699  return 0x13; // LATIN CAPITAL LETTER S
700  case 0x0054:
701  return 0x14; // LATIN CAPITAL LETTER T
702  case 0x0055:
703  return 0x15; // LATIN CAPITAL LETTER U
704  case 0x0056:
705  return 0x16; // LATIN CAPITAL LETTER V
706  case 0x0057:
707  return 0x17; // LATIN CAPITAL LETTER W
708  case 0x0058:
709  return 0x18; // LATIN CAPITAL LETTER X
710  case 0x0059:
711  return 0x19; // LATIN CAPITAL LETTER Y
712  case 0x005A:
713  return 0x1A; // LATIN CAPITAL LETTER Z
714  case 0x005B:
715  return 0x1B; // LEFT SQUARE BRACKET
716  case 0x00A3:
717  return 0x1C; // POUND SIGN
718  case 0x005D:
719  return 0x1D; // RIGHT SQUARE BRACKET
720  case 0x2191:
721  return 0x1E; // UPWARDS ARROW
722  case 0x2190:
723  return 0x1F; // LEFTWARDS ARROW
724  case 0x0020:
725  return 0x20; // SPACE
726  case 0x0021:
727  return 0x21; // EXCLAMATION MARK
728  case 0x0022:
729  return 0x22; // QUOTATION MARK
730  case 0x0023:
731  return 0x23; // NUMBER SIGN
732  case 0x0024:
733  return 0x24; // DOLLAR SIGN
734  case 0x0025:
735  return 0x25; // PERCENT SIGN
736  case 0x0026:
737  return 0x26; // AMPERSAND
738  case 0x0027:
739  return 0x27; // APOSTROPHE
740  case 0x0028:
741  return 0x28; // LEFT PARENTHESIS
742  case 0x0029:
743  return 0x29; // RIGHT PARENTHESIS
744  case 0x002A:
745  return 0x2A; // ASTERISK
746  case 0x002B:
747  return 0x2B; // PLUS SIGN
748  case 0x002C:
749  return 0x2C; // COMMA
750  case 0x002D:
751  return 0x2D; // HYPHEN-MINUS
752  case 0x002E:
753  return 0x2E; // FULL STOP
754  case 0x002F:
755  return 0x2F; // SOLIDUS
756  case 0x0030:
757  return 0x30; // DIGIT ZERO
758  case 0x0031:
759  return 0x31; // DIGIT ONE
760  case 0x0032:
761  return 0x32; // DIGIT TWO
762  case 0x0033:
763  return 0x33; // DIGIT THREE
764  case 0x0034:
765  return 0x34; // DIGIT FOUR
766  case 0x0035:
767  return 0x35; // DIGIT FIVE
768  case 0x0036:
769  return 0x36; // DIGIT SIX
770  case 0x0037:
771  return 0x37; // DIGIT SEVEN
772  case 0x0038:
773  return 0x38; // DIGIT EIGHT
774  case 0x0039:
775  return 0x39; // DIGIT NINE
776  case 0x003A:
777  return 0x3A; // COLON
778  case 0x003B:
779  return 0x3B; // SEMICOLON
780  case 0x003C:
781  return 0x3C; // LESS-THAN SIGN
782  case 0x003D:
783  return 0x3D; // EQUALS SIGN
784  case 0x003E:
785  return 0x3E; // GREATER-THAN SIGN
786  case 0x003F:
787  return 0x3F; // QUESTION MARK
788  case 0x2500:
789  return 0x40; // BOX DRAWINGS LIGHT HORIZONTAL
790  case 0x2660:
791  return 0x41; // BLACK SPADE SUIT
792  case 0x1FB72:
793  return 0x42; // VERTICAL ONE EIGHTH BLOCK-4
794  case 0x1FB78:
795  return 0x43; // HORIZONTAL ONE EIGHTH BLOCK-4
796  case 0x1FB77:
797  return 0x44; // HORIZONTAL ONE EIGHTH BLOCK-3
798  case 0x1FB76:
799  return 0x45; // HORIZONTAL ONE EIGHTH BLOCK-2
800  case 0x1FB7A:
801  return 0x46; // HORIZONTAL ONE EIGHTH BLOCK-6
802  case 0x1FB71:
803  return 0x47; // VERTICAL ONE EIGHTH BLOCK-3
804  case 0x1FB74:
805  return 0x48; // VERTICAL ONE EIGHTH BLOCK-6
806  case 0x256E:
807  return 0x49; // BOX DRAWINGS LIGHT ARC DOWN AND LEFT
808  case 0x2570:
809  return 0x4A; // BOX DRAWINGS LIGHT ARC UP AND RIGHT
810  case 0x256F:
811  return 0x4B; // BOX DRAWINGS LIGHT ARC UP AND LEFT
812  case 0x1FB7C:
813  return 0x4C; // LEFT AND LOWER ONE EIGHTH BLOCK
814  case 0x2572:
815  return 0x4D; // BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT
816  case 0x2571:
817  return 0x4E; // BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT
818  case 0x1FB7D:
819  return 0x4F; // LEFT AND UPPER ONE EIGHTH BLOCK
820  case 0x1FB7E:
821  return 0x50; // RIGHT AND UPPER ONE EIGHTH BLOCK
822  case 0x2022:
823  case 0x25CF:
824  return 0x51; // BULLET (or 0x25CF BLACK CIRCLE)
825  case 0x1FB7B:
826  return 0x52; // HORIZONTAL ONE EIGHTH BLOCK-7
827  case 0x2665:
828  return 0x53; // BLACK HEART SUIT
829  case 0x1FB70:
830  return 0x54; // VERTICAL ONE EIGHTH BLOCK-2
831  case 0x256D:
832  return 0x55; // BOX DRAWINGS LIGHT ARC DOWN AND RIGHT
833  case 0x2573:
834  return 0x56; // BOX DRAWINGS LIGHT DIAGONAL CROSS
835  case 0x25CB:
836  case 0x25E6:
837  return 0x57; // WHITE CIRCLE (or 0x25E6 WHITE BULLET)
838  case 0x2663:
839  return 0x58; // BLACK CLUB SUIT
840  case 0x1FB75:
841  return 0x59; // VERTICAL ONE EIGHTH BLOCK-7
842  case 0x2666:
843  return 0x5A; // BLACK DIAMOND SUIT
844  case 0x253C:
845  return 0x5B; // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
846  case 0x1FB8C:
847  return 0x5C; // LEFT HALF MEDIUM SHADE
848  case 0x2502:
849  return 0x5D; // BOX DRAWINGS LIGHT VERTICAL
850  case 0x03C0:
851  return 0x5E; // GREEK SMALL LETTER PI
852  case 0x25E5:
853  return 0x5F; // BLACK UPPER RIGHT TRIANGLE
854  case 0x00A0:
855  return 0x60; // NO-BREAK SPACE
856  case 0x258C:
857  return 0x61; // LEFT HALF BLOCK
858  case 0x2584:
859  return 0x62; // LOWER HALF BLOCK
860  case 0x2594:
861  return 0x63; // UPPER ONE EIGHTH BLOCK
862  case 0x2581:
863  return 0x64; // LOWER ONE EIGHTH BLOCK
864  case 0x258F:
865  return 0x65; // LEFT ONE EIGHTH BLOCK
866  case 0x2592:
867  return 0x66; // MEDIUM SHADE
868  case 0x2595:
869  return 0x67; // RIGHT ONE EIGHTH BLOCK
870  case 0x1FB8F:
871  return 0x68; // LOWER HALF MEDIUM SHADE
872  case 0x25E4:
873  return 0x69; // BLACK UPPER LEFT TRIANGLE
874  case 0x1FB87:
875  return 0x6A; // RIGHT ONE QUARTER BLOCK
876  case 0x251C:
877  return 0x6B; // BOX DRAWINGS LIGHT VERTICAL AND RIGHT
878  case 0x2597:
879  return 0x6C; // QUADRANT LOWER RIGHT
880  case 0x2514:
881  return 0x6D; // BOX DRAWINGS LIGHT UP AND RIGHT
882  case 0x2510:
883  return 0x6E; // BOX DRAWINGS LIGHT DOWN AND LEFT
884  case 0x2582:
885  return 0x6F; // LOWER ONE QUARTER BLOCK
886  case 0x250C:
887  return 0x70; // BOX DRAWINGS LIGHT DOWN AND RIGHT
888  case 0x2534:
889  return 0x71; // BOX DRAWINGS LIGHT UP AND HORIZONTAL
890  case 0x252C:
891  return 0x72; // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
892  case 0x2524:
893  return 0x73; // BOX DRAWINGS LIGHT VERTICAL AND LEFT
894  case 0x258E:
895  return 0x74; // LEFT ONE QUARTER BLOCK
896  case 0x258D:
897  return 0x75; // LEFT THREE EIGHTHS BLOCK
898  case 0x1FB88:
899  return 0x76; // RIGHT THREE EIGHTHS BLOCK
900  case 0x1FB82:
901  return 0x77; // UPPER ONE QUARTER BLOCK
902  case 0x1FB83:
903  return 0x78; // UPPER THREE EIGHTHS BLOCK
904  case 0x2583:
905  return 0x79; // LOWER THREE EIGHTHS BLOCK
906  case 0x1FB7F:
907  return 0x7A; // RIGHT AND LOWER ONE EIGHTH BLOCK
908  case 0x2596:
909  return 0x7B; // QUADRANT LOWER LEFT
910  case 0x259D:
911  return 0x7C; // QUADRANT UPPER RIGHT
912  case 0x2518:
913  return 0x7D; // BOX DRAWINGS LIGHT UP AND LEFT
914  case 0x2598:
915  return 0x7E; // QUADRANT UPPER LEFT
916  case 0x259A:
917  return 0x7F; // QUADRANT UPPER LEFT AND LOWER RIGHT
918  case 0x25D8:
919  return 0xD1; // INVERSE BULLET
920  case 0x25D9:
921  return 0xD7; // INVERSE WHITE CIRCLE
922  case 0x1FB94:
923  return 0xDC; // LEFT HALF INVERSE MEDIUM SHADE AND RIGHT HALF BLOCK
924  case 0x25E3:
925  return 0xDF; // BLACK LOWER LEFT TRIANGLE
926  case 0x2588:
927  return 0xE0; // FULL BLOCK
928  case 0x2590:
929  return 0xE1; // RIGHT HALF BLOCK
930  case 0x2580:
931  return 0xE2; // UPPER HALF BLOCK
932  case 0x2587:
933  return 0xE3; // LOWER SEVEN EIGHTHS BLOCK
934  case 0x1FB86:
935  return 0xE4; // UPPER SEVEN EIGHTHS BLOCK
936  case 0x1FB8B:
937  return 0xE5; // RIGHT SEVEN EIGHTHS BLOCK
938  case 0x1FB90:
939  return 0xE6; // INVERSE MEDIUM SHADE
940  case 0x2589:
941  return 0xE7; // LEFT SEVEN EIGHTHS BLOCK
942  case 0x1FB91:
943  return 0xE8; // UPPER HALF BLOCK AND LOWER HALF INVERSE MEDIUM SHADE
944  case 0x25E2:
945  return 0xE9; // BLACK LOWER RIGHT TRIANGLE
946  case 0x258A:
947  return 0xEA; // LEFT THREE QUARTERS BLOCK
948  case 0x259B:
949  return 0xEC; // QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER LEFT
950  case 0x1FB85:
951  return 0xEF; // UPPER THREE QUARTERS BLOCK
952  case 0x1FB8A:
953  return 0xF4; // RIGHT THREE QUARTERS BLOCK
954  case 0x1FB89:
955  return 0xF5; // RIGHT FIVE EIGHTHS BLOCK
956  case 0x258B:
957  return 0xF6; // LEFT FIVE EIGHTHS BLOCK
958  case 0x2586:
959  return 0xF7; // LOWER THREE QUARTERS BLOCK
960  case 0x2585:
961  return 0xF8; // LOWER FIVE EIGHTHS BLOCK
962  case 0x1FB84:
963  return 0xF9; // UPPER FIVE EIGHTHS BLOCK
964  case 0x259C:
965  return 0xFB; // QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER RIGHT
966  case 0x2599:
967  return 0xFC; // QUADRANT UPPER LEFT AND LOWER LEFT AND LOWER RIGHT
968  case 0x259F:
969  return 0xFE; // QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT
970  case 0x259E:
971  return 0xFF; // QUADRANT UPPER RIGHT AND LOWER LEFT
972  }
973  }
974 };
975 
976 template <size_t N> struct UnshiftedReverseVideoString {
977  char Str[N]{};
978 
979  constexpr UnshiftedReverseVideoString(char const (&Src)[N]) {
980  for (size_t I = 0; I < N; ++I) {
981  if (Src[I] >= 0x80)
982  throw "use U prefix for unicode string literals";
983  Str[I] = TranslateUnicode(Src[I]);
984  }
985  }
986 
987  constexpr UnshiftedReverseVideoString(char16_t const (&Src)[N]) {
988  for (size_t I = 0; I < N; ++I) {
989  if (Src[I] >= 0xD800 && Src[I] <= 0xDFFF)
990  throw "use U prefix for unicode string literals";
991  Str[I] = TranslateUnicode(Src[I]);
992  }
993  }
994 
995  constexpr UnshiftedReverseVideoString(char32_t const (&Src)[N]) {
996  for (size_t I = 0; I < N; ++I)
997  Str[I] = TranslateUnicode(Src[I]);
998  }
999 
1000  constexpr char TranslateUnicode(char32_t C) {
1001  switch (C) {
1002  default:
1003  throw "Unsupported";
1004 
1005  // Preserve NUL
1006  case 0x0000:
1007  return 0x00;
1008 
1009  // Name: Map from Commodore 64/128 (video) primary character set to
1010  // Unicode
1011 
1012  // Date: 2018 April 20
1013 
1014  // Author: Rebecca Bettencourt <support@kreativekorp.com>
1015 
1016  case 0x25D8:
1017  return 0x51; // INVERSE BULLET
1018  case 0x25D9:
1019  return 0x57; // INVERSE WHITE CIRCLE
1020  case 0x25E3:
1021  return 0x5F; // BLACK LOWER LEFT TRIANGLE
1022  case 0x2588:
1023  return 0x60; // FULL BLOCK
1024  case 0x2590:
1025  return 0x61; // RIGHT HALF BLOCK
1026  case 0x2580:
1027  return 0x62; // UPPER HALF BLOCK
1028  case 0x2587:
1029  return 0x63; // LOWER SEVEN EIGHTHS BLOCK
1030  case 0x1FB86:
1031  return 0x64; // UPPER SEVEN EIGHTHS BLOCK
1032  case 0x1FB8B:
1033  return 0x65; // RIGHT SEVEN EIGHTHS BLOCK
1034  case 0x1FB90:
1035  return 0x66; // INVERSE MEDIUM SHADE
1036  case 0x2589:
1037  return 0x67; // LEFT SEVEN EIGHTHS BLOCK
1038  case 0x1FB91:
1039  return 0x68; // UPPER HALF BLOCK AND LOWER HALF INVERSE MEDIUM SHADE
1040  case 0x25E2:
1041  return 0x69; // BLACK LOWER RIGHT TRIANGLE
1042  case 0x258A:
1043  return 0x6A; // LEFT THREE QUARTERS BLOCK
1044  case 0x259B:
1045  return 0x6C; // QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER LEFT
1046  case 0x1FB85:
1047  return 0x6F; // UPPER THREE QUARTERS BLOCK
1048  case 0x1FB8A:
1049  return 0x74; // RIGHT THREE QUARTERS BLOCK
1050  case 0x1FB89:
1051  return 0x75; // RIGHT FIVE EIGHTHS BLOCK
1052  case 0x258B:
1053  return 0x76; // LEFT FIVE EIGHTHS BLOCK
1054  case 0x2586:
1055  return 0x77; // LOWER THREE QUARTERS BLOCK
1056  case 0x2585:
1057  return 0x78; // LOWER FIVE EIGHTHS BLOCK
1058  case 0x1FB84:
1059  return 0x79; // UPPER FIVE EIGHTHS BLOCK
1060  case 0x259C:
1061  return 0x7B; // QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER RIGHT
1062  case 0x2599:
1063  return 0x7C; // QUADRANT UPPER LEFT AND LOWER LEFT AND LOWER RIGHT
1064  case 0x259F:
1065  return 0x7E; // QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT
1066  case 0x259E:
1067  return 0x7F; // QUADRANT UPPER RIGHT AND LOWER LEFT
1068  case 0x0040:
1069  return 0x80; // COMMERCIAL AT
1070  case 0x1FB94:
1071  return 0x5C; // LEFT HALF INVERSE MEDIUM SHADE AND RIGHT HALF BLOCK
1072  case 0x0041:
1073  return 0x81; // LATIN CAPITAL LETTER A
1074  case 0x0042:
1075  return 0x82; // LATIN CAPITAL LETTER B
1076  case 0x0043:
1077  return 0x83; // LATIN CAPITAL LETTER C
1078  case 0x0044:
1079  return 0x84; // LATIN CAPITAL LETTER D
1080  case 0x0045:
1081  return 0x85; // LATIN CAPITAL LETTER E
1082  case 0x0046:
1083  return 0x86; // LATIN CAPITAL LETTER F
1084  case 0x0047:
1085  return 0x87; // LATIN CAPITAL LETTER G
1086  case 0x0048:
1087  return 0x88; // LATIN CAPITAL LETTER H
1088  case 0x0049:
1089  return 0x89; // LATIN CAPITAL LETTER I
1090  case 0x004A:
1091  return 0x8A; // LATIN CAPITAL LETTER J
1092  case 0x004B:
1093  return 0x8B; // LATIN CAPITAL LETTER K
1094  case 0x004C:
1095  return 0x8C; // LATIN CAPITAL LETTER L
1096  case 0x004D:
1097  return 0x8D; // LATIN CAPITAL LETTER M
1098  case 0x004E:
1099  return 0x8E; // LATIN CAPITAL LETTER N
1100  case 0x004F:
1101  return 0x8F; // LATIN CAPITAL LETTER O
1102  case 0x0050:
1103  return 0x90; // LATIN CAPITAL LETTER P
1104  case 0x0051:
1105  return 0x91; // LATIN CAPITAL LETTER Q
1106  case 0x0052:
1107  return 0x92; // LATIN CAPITAL LETTER R
1108  case 0x0053:
1109  return 0x93; // LATIN CAPITAL LETTER S
1110  case 0x0054:
1111  return 0x94; // LATIN CAPITAL LETTER T
1112  case 0x0055:
1113  return 0x95; // LATIN CAPITAL LETTER U
1114  case 0x0056:
1115  return 0x96; // LATIN CAPITAL LETTER V
1116  case 0x0057:
1117  return 0x97; // LATIN CAPITAL LETTER W
1118  case 0x0058:
1119  return 0x98; // LATIN CAPITAL LETTER X
1120  case 0x0059:
1121  return 0x99; // LATIN CAPITAL LETTER Y
1122  case 0x005A:
1123  return 0x9A; // LATIN CAPITAL LETTER Z
1124  case 0x005B:
1125  return 0x9B; // LEFT SQUARE BRACKET
1126  case 0x00A3:
1127  return 0x9C; // POUND SIGN
1128  case 0x005D:
1129  return 0x9D; // RIGHT SQUARE BRACKET
1130  case 0x2191:
1131  return 0x9E; // UPWARDS ARROW
1132  case 0x2190:
1133  return 0x9F; // LEFTWARDS ARROW
1134  case 0x0020:
1135  return 0xA0; // SPACE
1136  case 0x0021:
1137  return 0xA1; // EXCLAMATION MARK
1138  case 0x0022:
1139  return 0xA2; // QUOTATION MARK
1140  case 0x0023:
1141  return 0xA3; // NUMBER SIGN
1142  case 0x0024:
1143  return 0xA4; // DOLLAR SIGN
1144  case 0x0025:
1145  return 0xA5; // PERCENT SIGN
1146  case 0x0026:
1147  return 0xA6; // AMPERSAND
1148  case 0x0027:
1149  return 0xA7; // APOSTROPHE
1150  case 0x0028:
1151  return 0xA8; // LEFT PARENTHESIS
1152  case 0x0029:
1153  return 0xA9; // RIGHT PARENTHESIS
1154  case 0x002A:
1155  return 0xAA; // ASTERISK
1156  case 0x002B:
1157  return 0xAB; // PLUS SIGN
1158  case 0x002C:
1159  return 0xAC; // COMMA
1160  case 0x002D:
1161  return 0xAD; // HYPHEN-MINUS
1162  case 0x002E:
1163  return 0xAE; // FULL STOP
1164  case 0x002F:
1165  return 0xAF; // SOLIDUS
1166  case 0x0030:
1167  return 0xB0; // DIGIT ZERO
1168  case 0x0031:
1169  return 0xB1; // DIGIT ONE
1170  case 0x0032:
1171  return 0xB2; // DIGIT TWO
1172  case 0x0033:
1173  return 0xB3; // DIGIT THREE
1174  case 0x0034:
1175  return 0xB4; // DIGIT FOUR
1176  case 0x0035:
1177  return 0xB5; // DIGIT FIVE
1178  case 0x0036:
1179  return 0xB6; // DIGIT SIX
1180  case 0x0037:
1181  return 0xB7; // DIGIT SEVEN
1182  case 0x0038:
1183  return 0xB8; // DIGIT EIGHT
1184  case 0x0039:
1185  return 0xB9; // DIGIT NINE
1186  case 0x003A:
1187  return 0xBA; // COLON
1188  case 0x003B:
1189  return 0xBB; // SEMICOLON
1190  case 0x003C:
1191  return 0xBC; // LESS-THAN SIGN
1192  case 0x003D:
1193  return 0xBD; // EQUALS SIGN
1194  case 0x003E:
1195  return 0xBE; // GREATER-THAN SIGN
1196  case 0x003F:
1197  return 0xBF; // QUESTION MARK
1198  case 0x2500:
1199  return 0xC0; // BOX DRAWINGS LIGHT HORIZONTAL
1200  case 0x2660:
1201  return 0xC1; // BLACK SPADE SUIT
1202  case 0x1FB72:
1203  return 0xC2; // VERTICAL ONE EIGHTH BLOCK-4
1204  case 0x1FB78:
1205  return 0xC3; // HORIZONTAL ONE EIGHTH BLOCK-4
1206  case 0x1FB77:
1207  return 0xC4; // HORIZONTAL ONE EIGHTH BLOCK-3
1208  case 0x1FB76:
1209  return 0xC5; // HORIZONTAL ONE EIGHTH BLOCK-2
1210  case 0x1FB7A:
1211  return 0xC6; // HORIZONTAL ONE EIGHTH BLOCK-6
1212  case 0x1FB71:
1213  return 0xC7; // VERTICAL ONE EIGHTH BLOCK-3
1214  case 0x1FB74:
1215  return 0xC8; // VERTICAL ONE EIGHTH BLOCK-6
1216  case 0x256E:
1217  return 0xC9; // BOX DRAWINGS LIGHT ARC DOWN AND LEFT
1218  case 0x2570:
1219  return 0xCA; // BOX DRAWINGS LIGHT ARC UP AND RIGHT
1220  case 0x256F:
1221  return 0xCB; // BOX DRAWINGS LIGHT ARC UP AND LEFT
1222  case 0x1FB7C:
1223  return 0xCC; // LEFT AND LOWER ONE EIGHTH BLOCK
1224  case 0x2572:
1225  return 0xCD; // BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT
1226  case 0x2571:
1227  return 0xCE; // BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT
1228  case 0x1FB7D:
1229  return 0xCF; // LEFT AND UPPER ONE EIGHTH BLOCK
1230  case 0x1FB7E:
1231  return 0xD0; // RIGHT AND UPPER ONE EIGHTH BLOCK
1232  case 0x2022:
1233  case 0x25CF:
1234  return 0xD1; // BULLET (or 0x25CF BLACK CIRCLE)
1235  case 0x1FB7B:
1236  return 0xD2; // HORIZONTAL ONE EIGHTH BLOCK-7
1237  case 0x2665:
1238  return 0xD3; // BLACK HEART SUIT
1239  case 0x1FB70:
1240  return 0xD4; // VERTICAL ONE EIGHTH BLOCK-2
1241  case 0x256D:
1242  return 0xD5; // BOX DRAWINGS LIGHT ARC DOWN AND RIGHT
1243  case +0x2573:
1244  return 0xD6; // BOX DRAWINGS LIGHT DIAGONAL CROSS
1245  case 0x25CB:
1246  case 0x25E6:
1247  return 0xD7; // WHITE CIRCLE (or 0x25E6 WHITE BULLET)
1248  case 0x2663:
1249  return 0xD8; // BLACK CLUB SUIT
1250  case 0x1FB75:
1251  return 0xD9; // VERTICAL ONE EIGHTH BLOCK-7
1252  case 0x2666:
1253  return 0xDA; // BLACK DIAMOND SUIT
1254  case 0x253C:
1255  return 0xDB; // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
1256  case 0x1FB8C:
1257  return 0xDC; // LEFT HALF MEDIUM SHADE
1258  case 0x2502:
1259  return 0xDD; // BOX DRAWINGS LIGHT VERTICAL
1260  case 0x03C0:
1261  return 0xDE; // GREEK SMALL LETTER PI
1262  case 0x25E5:
1263  return 0xDF; // BLACK UPPER RIGHT TRIANGLE
1264  case 0x00A0:
1265  return 0xE0; // NO-BREAK SPACE
1266  case 0x258C:
1267  return 0xE1; // LEFT HALF BLOCK
1268  case 0x2584:
1269  return 0xE2; // LOWER HALF BLOCK
1270  case 0x2594:
1271  return 0xE3; // UPPER ONE EIGHTH BLOCK
1272  case 0x2581:
1273  return 0xE4; // LOWER ONE EIGHTH BLOCK
1274  case 0x258F:
1275  return 0xE5; // LEFT ONE EIGHTH BLOCK
1276  case 0x2592:
1277  return 0xE6; // MEDIUM SHADE
1278  case 0x2595:
1279  return 0xE7; // RIGHT ONE EIGHTH BLOCK
1280  case 0x1FB8F:
1281  return 0xE8; // LOWER HALF MEDIUM SHADE
1282  case 0x25E4:
1283  return 0xE9; // BLACK UPPER LEFT TRIANGLE
1284  case 0x1FB87:
1285  return 0xEA; // RIGHT ONE QUARTER BLOCK
1286  case 0x251C:
1287  return 0xEB; // BOX DRAWINGS LIGHT VERTICAL AND RIGHT
1288  case 0x2597:
1289  return 0xEC; // QUADRANT LOWER RIGHT
1290  case 0x2514:
1291  return 0xED; // BOX DRAWINGS LIGHT UP AND RIGHT
1292  case 0x2510:
1293  return 0xEE; // BOX DRAWINGS LIGHT DOWN AND LEFT
1294  case 0x2582:
1295  return 0xEF; // LOWER ONE QUARTER BLOCK
1296  case 0x250C:
1297  return 0xF0; // BOX DRAWINGS LIGHT DOWN AND RIGHT
1298  case 0x2534:
1299  return 0xF1; // BOX DRAWINGS LIGHT UP AND HORIZONTAL
1300  case 0x252C:
1301  return 0xF2; // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
1302  case 0x2524:
1303  return 0xF3; // BOX DRAWINGS LIGHT VERTICAL AND LEFT
1304  case 0x258E:
1305  return 0xF4; // LEFT ONE QUARTER BLOCK
1306  case 0x258D:
1307  return 0xF5; // LEFT THREE EIGHTHS BLOCK
1308  case 0x1FB88:
1309  return 0xF6; // RIGHT THREE EIGHTHS BLOCK
1310  case 0x1FB82:
1311  return 0xF7; // UPPER ONE QUARTER BLOCK
1312  case 0x1FB83:
1313  return 0xF8; // UPPER THREE EIGHTHS BLOCK
1314  case 0x2583:
1315  return 0xF9; // LOWER THREE EIGHTHS BLOCK
1316  case 0x1FB7F:
1317  return 0xFA; // RIGHT AND LOWER ONE EIGHTH BLOCK
1318  case 0x2596:
1319  return 0xFB; // QUADRANT LOWER LEFT
1320  case 0x259D:
1321  return 0xFC; // QUADRANT UPPER RIGHT
1322  case 0x2518:
1323  return 0xFD; // BOX DRAWINGS LIGHT UP AND LEFT
1324  case 0x2598:
1325  return 0xFE; // QUADRANT UPPER LEFT
1326  case 0x259A:
1327  return 0xFF; // QUADRANT UPPER LEFT AND LOWER RIGHT
1328  }
1329  }
1330 };
1331 
1332 template <size_t N> struct ShiftedVideoString {
1333  char Str[N]{};
1334 
1335  constexpr ShiftedVideoString(char const (&Src)[N]) {
1336  for (size_t I = 0; I < N; ++I) {
1337  if (Src[I] >= 0x80)
1338  throw "use U prefix for unicode string literals";
1339  Str[I] = TranslateUnicode(Src[I]);
1340  }
1341  }
1342 
1343  constexpr ShiftedVideoString(char16_t const (&Src)[N]) {
1344  for (size_t I = 0; I < N; ++I) {
1345  if (Src[I] >= 0xD800 && Src[I] <= 0xDFFF)
1346  throw "use U prefix for unicode string literals";
1347  Str[I] = TranslateUnicode(Src[I]);
1348  }
1349  }
1350 
1351  constexpr ShiftedVideoString(char32_t const (&Src)[N]) {
1352  for (size_t I = 0; I < N; ++I)
1353  Str[I] = TranslateUnicode(Src[I]);
1354  }
1355 
1356  constexpr char TranslateUnicode(char32_t C) {
1357  switch (C) {
1358  default:
1359  throw "Unsupported";
1360 
1361  // Preserve NUL
1362  case 0x0000:
1363  return 0x00;
1364 
1365  // Name: Map from Commodore 64/128 (video) alternate character set to
1366  // Unicode
1367 
1368  // Date: 2018 October 11
1369 
1370  // Author: Rebecca Bettencourt <support@kreativekorp.com>
1371 
1372  case 0x0040:
1373  return 0x00; // COMMERCIAL AT
1374  case 0x0061:
1375  return 0x01; // LATIN SMALL LETTER A
1376  case 0x0062:
1377  return 0x02; // LATIN SMALL LETTER B
1378  case 0x0063:
1379  return 0x03; // LATIN SMALL LETTER C
1380  case 0x0064:
1381  return 0x04; // LATIN SMALL LETTER D
1382  case 0x0065:
1383  return 0x05; // LATIN SMALL LETTER E
1384  case 0x0066:
1385  return 0x06; // LATIN SMALL LETTER F
1386  case 0x0067:
1387  return 0x07; // LATIN SMALL LETTER G
1388  case 0x0068:
1389  return 0x08; // LATIN SMALL LETTER H
1390  case 0x0069:
1391  return 0x09; // LATIN SMALL LETTER I
1392  case 0x006A:
1393  return 0x0A; // LATIN SMALL LETTER J
1394  case 0x006B:
1395  return 0x0B; // LATIN SMALL LETTER K
1396  case 0x006C:
1397  return 0x0C; // LATIN SMALL LETTER L
1398  case 0x006D:
1399  return 0x0D; // LATIN SMALL LETTER M
1400  case 0x006E:
1401  return 0x0E; // LATIN SMALL LETTER N
1402  case 0x006F:
1403  return 0x0F; // LATIN SMALL LETTER O
1404  case 0x0070:
1405  return 0x10; // LATIN SMALL LETTER P
1406  case 0x0071:
1407  return 0x11; // LATIN SMALL LETTER Q
1408  case 0x0072:
1409  return 0x12; // LATIN SMALL LETTER R
1410  case 0x0073:
1411  return 0x13; // LATIN SMALL LETTER S
1412  case 0x0074:
1413  return 0x14; // LATIN SMALL LETTER T
1414  case 0x0075:
1415  return 0x15; // LATIN SMALL LETTER U
1416  case 0x0076:
1417  return 0x16; // LATIN SMALL LETTER V
1418  case 0x0077:
1419  return 0x17; // LATIN SMALL LETTER W
1420  case 0x0078:
1421  return 0x18; // LATIN SMALL LETTER X
1422  case 0x0079:
1423  return 0x19; // LATIN SMALL LETTER Y
1424  case 0x007A:
1425  return 0x1A; // LATIN SMALL LETTER Z
1426  case 0x005B:
1427  return 0x1B; // LEFT SQUARE BRACKET
1428  case 0x00A3:
1429  return 0x1C; // POUND SIGN
1430  case 0x005D:
1431  return 0x1D; // RIGHT SQUARE BRACKET
1432  case 0x2191:
1433  return 0x1E; // UPWARDS ARROW
1434  case 0x2190:
1435  return 0x1F; // LEFTWARDS ARROW
1436  case 0x0020:
1437  return 0x20; // SPACE
1438  case 0x0021:
1439  return 0x21; // EXCLAMATION MARK
1440  case 0x0022:
1441  return 0x22; // QUOTATION MARK
1442  case 0x0023:
1443  return 0x23; // NUMBER SIGN
1444  case 0x0024:
1445  return 0x24; // DOLLAR SIGN
1446  case 0x0025:
1447  return 0x25; // PERCENT SIGN
1448  case 0x0026:
1449  return 0x26; // AMPERSAND
1450  case 0x0027:
1451  return 0x27; // APOSTROPHE
1452  case 0x0028:
1453  return 0x28; // LEFT PARENTHESIS
1454  case 0x0029:
1455  return 0x29; // RIGHT PARENTHESIS
1456  case 0x002A:
1457  return 0x2A; // ASTERISK
1458  case 0x002B:
1459  return 0x2B; // PLUS SIGN
1460  case 0x002C:
1461  return 0x2C; // COMMA
1462  case 0x002D:
1463  return 0x2D; // HYPHEN-MINUS
1464  case 0x002E:
1465  return 0x2E; // FULL STOP
1466  case 0x002F:
1467  return 0x2F; // SOLIDUS
1468  case 0x0030:
1469  return 0x30; // DIGIT ZERO
1470  case 0x0031:
1471  return 0x31; // DIGIT ONE
1472  case 0x0032:
1473  return 0x32; // DIGIT TWO
1474  case 0x0033:
1475  return 0x33; // DIGIT THREE
1476  case 0x0034:
1477  return 0x34; // DIGIT FOUR
1478  case 0x0035:
1479  return 0x35; // DIGIT FIVE
1480  case 0x0036:
1481  return 0x36; // DIGIT SIX
1482  case 0x0037:
1483  return 0x37; // DIGIT SEVEN
1484  case 0x0038:
1485  return 0x38; // DIGIT EIGHT
1486  case 0x0039:
1487  return 0x39; // DIGIT NINE
1488  case 0x003A:
1489  return 0x3A; // COLON
1490  case 0x003B:
1491  return 0x3B; // SEMICOLON
1492  case 0x003C:
1493  return 0x3C; // LESS-THAN SIGN
1494  case 0x003D:
1495  return 0x3D; // EQUALS SIGN
1496  case 0x003E:
1497  return 0x3E; // GREATER-THAN SIGN
1498  case 0x003F:
1499  return 0x3F; // QUESTION MARK
1500  case 0x2500:
1501  return 0x40; // BOX DRAWINGS LIGHT HORIZONTAL
1502  case 0x0041:
1503  return 0x41; // LATIN CAPITAL LETTER A
1504  case 0x0042:
1505  return 0x42; // LATIN CAPITAL LETTER B
1506  case 0x0043:
1507  return 0x43; // LATIN CAPITAL LETTER C
1508  case 0x0044:
1509  return 0x44; // LATIN CAPITAL LETTER D
1510  case 0x0045:
1511  return 0x45; // LATIN CAPITAL LETTER E
1512  case 0x0046:
1513  return 0x46; // LATIN CAPITAL LETTER F
1514  case 0x0047:
1515  return 0x47; // LATIN CAPITAL LETTER G
1516  case 0x0048:
1517  return 0x48; // LATIN CAPITAL LETTER H
1518  case 0x0049:
1519  return 0x49; // LATIN CAPITAL LETTER I
1520  case 0x004A:
1521  return 0x4A; // LATIN CAPITAL LETTER J
1522  case 0x004B:
1523  return 0x4B; // LATIN CAPITAL LETTER K
1524  case 0x004C:
1525  return 0x4C; // LATIN CAPITAL LETTER L
1526  case 0x004D:
1527  return 0x4D; // LATIN CAPITAL LETTER M
1528  case 0x004E:
1529  return 0x4E; // LATIN CAPITAL LETTER N
1530  case 0x004F:
1531  return 0x4F; // LATIN CAPITAL LETTER O
1532  case 0x0050:
1533  return 0x50; // LATIN CAPITAL LETTER P
1534  case 0x0051:
1535  return 0x51; // LATIN CAPITAL LETTER Q
1536  case 0x0052:
1537  return 0x52; // LATIN CAPITAL LETTER R
1538  case 0x0053:
1539  return 0x53; // LATIN CAPITAL LETTER S
1540  case 0x0054:
1541  return 0x54; // LATIN CAPITAL LETTER T
1542  case 0x0055:
1543  return 0x55; // LATIN CAPITAL LETTER U
1544  case 0x0056:
1545  return 0x56; // LATIN CAPITAL LETTER V
1546  case 0x0057:
1547  return 0x57; // LATIN CAPITAL LETTER W
1548  case 0x0058:
1549  return 0x58; // LATIN CAPITAL LETTER X
1550  case 0x0059:
1551  return 0x59; // LATIN CAPITAL LETTER Y
1552  case 0x005A:
1553  return 0x5A; // LATIN CAPITAL LETTER Z
1554  case 0x253C:
1555  return 0x5B; // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
1556  case 0x1FB8C:
1557  return 0x5C; // LEFT HALF MEDIUM SHADE
1558  case 0x2502:
1559  return 0x5D; // BOX DRAWINGS LIGHT VERTICAL
1560  case 0x1FB96:
1561  return 0x5E; // INVERSE CHECKER BOARD FILL
1562  case 0x1FB98:
1563  return 0x5F; // UPPER LEFT TO LOWER RIGHT FILL
1564  case 0x00A0:
1565  return 0x60; // NO-BREAK SPACE
1566  case 0x258C:
1567  return 0x61; // LEFT HALF BLOCK
1568  case 0x2584:
1569  return 0x62; // LOWER HALF BLOCK
1570  case 0x2594:
1571  return 0x63; // UPPER ONE EIGHTH BLOCK
1572  case 0x2581:
1573  return 0x64; // LOWER ONE EIGHTH BLOCK
1574  case 0x258F:
1575  return 0x65; // LEFT ONE EIGHTH BLOCK
1576  case 0x2592:
1577  return 0x66; // MEDIUM SHADE
1578  case 0x2595:
1579  return 0x67; // RIGHT ONE EIGHTH BLOCK
1580  case 0x1FB8F:
1581  return 0x68; // LOWER HALF MEDIUM SHADE
1582  case 0x1FB99:
1583  return 0x69; // UPPER RIGHT TO LOWER LEFT FILL
1584  case 0x1FB87:
1585  return 0x6A; // RIGHT ONE QUARTER BLOCK
1586  case 0x251C:
1587  return 0x6B; // BOX DRAWINGS LIGHT VERTICAL AND RIGHT
1588  case 0x2597:
1589  return 0x6C; // QUADRANT LOWER RIGHT
1590  case 0x2514:
1591  return 0x6D; // BOX DRAWINGS LIGHT UP AND RIGHT
1592  case 0x2510:
1593  return 0x6E; // BOX DRAWINGS LIGHT DOWN AND LEFT
1594  case 0x2582:
1595  return 0x6F; // LOWER ONE QUARTER BLOCK
1596  case 0x250C:
1597  return 0x70; // BOX DRAWINGS LIGHT DOWN AND RIGHT
1598  case 0x2534:
1599  return 0x71; // BOX DRAWINGS LIGHT UP AND HORIZONTAL
1600  case 0x252C:
1601  return 0x72; // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
1602  case 0x2524:
1603  return 0x73; // BOX DRAWINGS LIGHT VERTICAL AND LEFT
1604  case 0x258E:
1605  return 0x74; // LEFT ONE QUARTER BLOCK
1606  case 0x258D:
1607  return 0x75; // LEFT THREE EIGHTHS BLOCK
1608  case 0x1FB88:
1609  return 0x76; // RIGHT THREE EIGHTHS BLOCK
1610  case 0x1FB82:
1611  return 0x77; // UPPER ONE QUARTER BLOCK
1612  case 0x1FB83:
1613  return 0x78; // UPPER THREE EIGHTHS BLOCK
1614  case 0x2583:
1615  return 0x79; // LOWER THREE EIGHTHS BLOCK
1616  case 0x2713:
1617  return 0x7A; // CHECK MARK
1618  case 0x2596:
1619  return 0x7B; // QUADRANT LOWER LEFT
1620  case 0x259D:
1621  return 0x7C; // QUADRANT UPPER RIGHT
1622  case 0x2518:
1623  return 0x7D; // BOX DRAWINGS LIGHT UP AND LEFT
1624  case 0x2598:
1625  return 0x7E; // QUADRANT UPPER LEFT
1626  case 0x259A:
1627  return 0x7F; // QUADRANT UPPER LEFT AND LOWER RIGHT
1628  case 0x1FB94:
1629  return 0xDC; // LEFT HALF INVERSE MEDIUM SHADE AND RIGHT HALF BLOCK
1630  case 0x1FB95:
1631  return 0xDE; // CHECKER BOARD FILL
1632  case 0x2588:
1633  return 0xE0; // FULL BLOCK
1634  case 0x2590:
1635  return 0xE1; // RIGHT HALF BLOCK
1636  case 0x2580:
1637  return 0xE2; // UPPER HALF BLOCK
1638  case 0x2587:
1639  return 0xE3; // LOWER SEVEN EIGHTHS BLOCK
1640  case 0x1FB86:
1641  return 0xE4; // UPPER SEVEN EIGHTHS BLOCK
1642  case 0x1FB8B:
1643  return 0xE5; // RIGHT SEVEN EIGHTHS BLOCK
1644  case 0x1FB90:
1645  return 0xE6; // INVERSE MEDIUM SHADE
1646  case 0x2589:
1647  return 0xE7; // LEFT SEVEN EIGHTHS BLOCK
1648  case 0x1FB91:
1649  return 0xE8; // UPPER HALF BLOCK AND LOWER HALF INVERSE MEDIUM SHADE
1650  case 0x258A:
1651  return 0xEA; // LEFT THREE QUARTERS BLOCK
1652  case 0x259B:
1653  return 0xEC; // QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER LEFT
1654  case 0x1FB85:
1655  return 0xEF; // UPPER THREE QUARTERS BLOCK
1656  case 0x1FB8A:
1657  return 0xF4; // RIGHT THREE QUARTERS BLOCK
1658  case 0x1FB89:
1659  return 0xF5; // RIGHT FIVE EIGHTHS BLOCK
1660  case 0x258B:
1661  return 0xF6; // LEFT FIVE EIGHTHS BLOCK
1662  case 0x2586:
1663  return 0xF7; // LOWER THREE QUARTERS BLOCK
1664  case 0x2585:
1665  return 0xF8; // LOWER FIVE EIGHTHS BLOCK
1666  case 0x1FB84:
1667  return 0xF9; // UPPER FIVE EIGHTHS BLOCK
1668  case 0x1FBB1:
1669  return 0xFA; // INVERSE CHECK MARK
1670  case 0x259C:
1671  return 0xFB; // QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER RIGHT
1672  case 0x2599:
1673  return 0xFC; // QUADRANT UPPER LEFT AND LOWER LEFT AND LOWER RIGHT
1674  case 0x259F:
1675  return 0xFE; // QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT
1676  case 0x259E:
1677  return 0xFF; // QUADRANT UPPER RIGHT AND LOWER LEFT
1678  }
1679  }
1680 };
1681 
1682 template <size_t N> struct ShiftedReverseVideoString {
1683  char Str[N]{};
1684 
1685  constexpr ShiftedReverseVideoString(char const (&Src)[N]) {
1686  for (size_t I = 0; I < N; ++I) {
1687  if (Src[I] >= 0x80)
1688  throw "use U prefix for unicode string literals";
1689  Str[I] = TranslateUnicode(Src[I]);
1690  }
1691  }
1692 
1693  constexpr ShiftedReverseVideoString(char16_t const (&Src)[N]) {
1694  for (size_t I = 0; I < N; ++I) {
1695  if (Src[I] >= 0xD800 && Src[I] <= 0xDFFF)
1696  throw "use U prefix for unicode string literals";
1697  Str[I] = TranslateUnicode(Src[I]);
1698  }
1699  }
1700 
1701  constexpr ShiftedReverseVideoString(char32_t const (&Src)[N]) {
1702  for (size_t I = 0; I < N; ++I)
1703  Str[I] = TranslateUnicode(Src[I]);
1704  }
1705 
1706  constexpr char TranslateUnicode(char32_t C) {
1707  switch (C) {
1708  default:
1709  throw "Unsupported";
1710 
1711  // Preserve NUL
1712  case 0x0000:
1713  return 0x00;
1714 
1715  // Name: Map from Commodore 64/128 (video) alternate character set to
1716  // Unicode
1717 
1718  // Date: 2018 October 11
1719 
1720  // Author: Rebecca Bettencourt <support@kreativekorp.com>
1721 
1722  case 0x1FB94:
1723  return 0x5C; // LEFT HALF INVERSE MEDIUM SHADE AND RIGHT HALF BLOCK
1724  case 0x1FB95:
1725  return 0x5E; // CHECKER BOARD FILL
1726  case 0x2588:
1727  return 0x60; // FULL BLOCK
1728  case 0x2590:
1729  return 0x61; // RIGHT HALF BLOCK
1730  case 0x2580:
1731  return 0x62; // UPPER HALF BLOCK
1732  case 0x2587:
1733  return 0x63; // LOWER SEVEN EIGHTHS BLOCK
1734  case 0x1FB86:
1735  return 0x64; // UPPER SEVEN EIGHTHS BLOCK
1736  case 0x1FB8B:
1737  return 0x65; // RIGHT SEVEN EIGHTHS BLOCK
1738  case 0x1FB90:
1739  return 0x66; // INVERSE MEDIUM SHADE
1740  case 0x2589:
1741  return 0x67; // LEFT SEVEN EIGHTHS BLOCK
1742  case 0x1FB91:
1743  return 0x68; // UPPER HALF BLOCK AND LOWER HALF INVERSE MEDIUM SHADE
1744  case 0x258A:
1745  return 0x6A; // LEFT THREE QUARTERS BLOCK
1746  case 0x259B:
1747  return 0x6C; // QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER LEFT
1748  case 0x1FB85:
1749  return 0x6F; // UPPER THREE QUARTERS BLOCK
1750  case 0x1FB8A:
1751  return 0x74; // RIGHT THREE QUARTERS BLOCK
1752  case 0x1FB89:
1753  return 0x75; // RIGHT FIVE EIGHTHS BLOCK
1754  case 0x258B:
1755  return 0x76; // LEFT FIVE EIGHTHS BLOCK
1756  case 0x2586:
1757  return 0x77; // LOWER THREE QUARTERS BLOCK
1758  case 0x2585:
1759  return 0x78; // LOWER FIVE EIGHTHS BLOCK
1760  case 0x1FB84:
1761  return 0x79; // UPPER FIVE EIGHTHS BLOCK
1762  case 0x1FBB1:
1763  return 0x7A; // INVERSE CHECK MARK
1764  case 0x259C:
1765  return 0x7B; // QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER RIGHT
1766  case 0x2599:
1767  return 0x7C; // QUADRANT UPPER LEFT AND LOWER LEFT AND LOWER RIGHT
1768  case 0x259F:
1769  return 0x7E; // QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT
1770  case 0x259E:
1771  return 0x7F; // QUADRANT UPPER RIGHT AND LOWER LEFT
1772  case 0x0040:
1773  return 0x80; // COMMERCIAL AT
1774  case 0x0061:
1775  return 0x81; // LATIN SMALL LETTER A
1776  case 0x0062:
1777  return 0x82; // LATIN SMALL LETTER B
1778  case 0x0063:
1779  return 0x83; // LATIN SMALL LETTER C
1780  case 0x0064:
1781  return 0x84; // LATIN SMALL LETTER D
1782  case 0x0065:
1783  return 0x85; // LATIN SMALL LETTER E
1784  case 0x0066:
1785  return 0x86; // LATIN SMALL LETTER F
1786  case 0x0067:
1787  return 0x87; // LATIN SMALL LETTER G
1788  case 0x0068:
1789  return 0x88; // LATIN SMALL LETTER H
1790  case 0x0069:
1791  return 0x89; // LATIN SMALL LETTER I
1792  case 0x006A:
1793  return 0x8A; // LATIN SMALL LETTER J
1794  case 0x006B:
1795  return 0x8B; // LATIN SMALL LETTER K
1796  case 0x006C:
1797  return 0x8C; // LATIN SMALL LETTER L
1798  case 0x006D:
1799  return 0x8D; // LATIN SMALL LETTER M
1800  case 0x006E:
1801  return 0x8E; // LATIN SMALL LETTER N
1802  case 0x006F:
1803  return 0x8F; // LATIN SMALL LETTER O
1804  case 0x0070:
1805  return 0x90; // LATIN SMALL LETTER P
1806  case 0x0071:
1807  return 0x91; // LATIN SMALL LETTER Q
1808  case 0x0072:
1809  return 0x92; // LATIN SMALL LETTER R
1810  case 0x0073:
1811  return 0x93; // LATIN SMALL LETTER S
1812  case 0x0074:
1813  return 0x94; // LATIN SMALL LETTER T
1814  case 0x0075:
1815  return 0x95; // LATIN SMALL LETTER U
1816  case 0x0076:
1817  return 0x96; // LATIN SMALL LETTER V
1818  case 0x0077:
1819  return 0x97; // LATIN SMALL LETTER W
1820  case 0x0078:
1821  return 0x98; // LATIN SMALL LETTER X
1822  case 0x0079:
1823  return 0x99; // LATIN SMALL LETTER Y
1824  case 0x007A:
1825  return 0x9A; // LATIN SMALL LETTER Z
1826  case 0x005B:
1827  return 0x9B; // LEFT SQUARE BRACKET
1828  case 0x00A3:
1829  return 0x9C; // POUND SIGN
1830  case 0x005D:
1831  return 0x9D; // RIGHT SQUARE BRACKET
1832  case 0x2191:
1833  return 0x9E; // UPWARDS ARROW
1834  case 0x2190:
1835  return 0x9F; // LEFTWARDS ARROW
1836  case 0x0020:
1837  return 0xA0; // SPACE
1838  case 0x0021:
1839  return 0xA1; // EXCLAMATION MARK
1840  case 0x0022:
1841  return 0xA2; // QUOTATION MARK
1842  case 0x0023:
1843  return 0xA3; // NUMBER SIGN
1844  case 0x0024:
1845  return 0xA4; // DOLLAR SIGN
1846  case 0x0025:
1847  return 0xA5; // PERCENT SIGN
1848  case 0x0026:
1849  return 0xA6; // AMPERSAND
1850  case 0x0027:
1851  return 0xA7; // APOSTROPHE
1852  case 0x0028:
1853  return 0xA8; // LEFT PARENTHESIS
1854  case 0x0029:
1855  return 0xA9; // RIGHT PARENTHESIS
1856  case 0x002A:
1857  return 0xAA; // ASTERISK
1858  case 0x002B:
1859  return 0xAB; // PLUS SIGN
1860  case 0x002C:
1861  return 0xAC; // COMMA
1862  case 0x002D:
1863  return 0xAD; // HYPHEN-MINUS
1864  case 0x002E:
1865  return 0xAE; // FULL STOP
1866  case 0x002F:
1867  return 0xAF; // SOLIDUS
1868  case 0x0030:
1869  return 0xB0; // DIGIT ZERO
1870  case 0x0031:
1871  return 0xB1; // DIGIT ONE
1872  case 0x0032:
1873  return 0xB2; // DIGIT TWO
1874  case 0x0033:
1875  return 0xB3; // DIGIT THREE
1876  case 0x0034:
1877  return 0xB4; // DIGIT FOUR
1878  case 0x0035:
1879  return 0xB5; // DIGIT FIVE
1880  case 0x0036:
1881  return 0xB6; // DIGIT SIX
1882  case 0x0037:
1883  return 0xB7; // DIGIT SEVEN
1884  case 0x0038:
1885  return 0xB8; // DIGIT EIGHT
1886  case 0x0039:
1887  return 0xB9; // DIGIT NINE
1888  case 0x003A:
1889  return 0xBA; // COLON
1890  case 0x003B:
1891  return 0xBB; // SEMICOLON
1892  case 0x003C:
1893  return 0xBC; // LESS-THAN SIGN
1894  case 0x003D:
1895  return 0xBD; // EQUALS SIGN
1896  case 0x003E:
1897  return 0xBE; // GREATER-THAN SIGN
1898  case 0x003F:
1899  return 0xBF; // QUESTION MARK
1900  case 0x2500:
1901  return 0xC0; // BOX DRAWINGS LIGHT HORIZONTAL
1902  case 0x0041:
1903  return 0xC1; // LATIN CAPITAL LETTER A
1904  case 0x0042:
1905  return 0xC2; // LATIN CAPITAL LETTER B
1906  case 0x0043:
1907  return 0xC3; // LATIN CAPITAL LETTER C
1908  case 0x0044:
1909  return 0xC4; // LATIN CAPITAL LETTER D
1910  case 0x0045:
1911  return 0xC5; // LATIN CAPITAL LETTER E
1912  case 0x0046:
1913  return 0xC6; // LATIN CAPITAL LETTER F
1914  case 0x0047:
1915  return 0xC7; // LATIN CAPITAL LETTER G
1916  case 0x0048:
1917  return 0xC8; // LATIN CAPITAL LETTER H
1918  case 0x0049:
1919  return 0xC9; // LATIN CAPITAL LETTER I
1920  case 0x004A:
1921  return 0xCA; // LATIN CAPITAL LETTER J
1922  case 0x004B:
1923  return 0xCB; // LATIN CAPITAL LETTER K
1924  case 0x004C:
1925  return 0xCC; // LATIN CAPITAL LETTER L
1926  case 0x004D:
1927  return 0xCD; // LATIN CAPITAL LETTER M
1928  case 0x004E:
1929  return 0xCE; // LATIN CAPITAL LETTER N
1930  case 0x004F:
1931  return 0xCF; // LATIN CAPITAL LETTER O
1932  case 0x0050:
1933  return 0xD0; // LATIN CAPITAL LETTER P
1934  case 0x0051:
1935  return 0xD1; // LATIN CAPITAL LETTER Q
1936  case 0x0052:
1937  return 0xD2; // LATIN CAPITAL LETTER R
1938  case 0x0053:
1939  return 0xD3; // LATIN CAPITAL LETTER S
1940  case 0x0054:
1941  return 0xD4; // LATIN CAPITAL LETTER T
1942  case 0x0055:
1943  return 0xD5; // LATIN CAPITAL LETTER U
1944  case 0x0056:
1945  return 0xD6; // LATIN CAPITAL LETTER V
1946  case 0x0057:
1947  return 0xD7; // LATIN CAPITAL LETTER W
1948  case 0x0058:
1949  return 0xD8; // LATIN CAPITAL LETTER X
1950  case 0x0059:
1951  return 0xD9; // LATIN CAPITAL LETTER Y
1952  case 0x005A:
1953  return 0xDA; // LATIN CAPITAL LETTER Z
1954  case 0x253C:
1955  return 0xDB; // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
1956  case 0x1FB8C:
1957  return 0xDC; // LEFT HALF MEDIUM SHADE
1958  case 0x2502:
1959  return 0xDD; // BOX DRAWINGS LIGHT VERTICAL
1960  case 0x1FB96:
1961  return 0xDE; // INVERSE CHECKER BOARD FILL
1962  case 0x1FB98:
1963  return 0xDF; // UPPER LEFT TO LOWER RIGHT FILL
1964  case 0x00A0:
1965  return 0xE0; // NO-BREAK SPACE
1966  case 0x258C:
1967  return 0xE1; // LEFT HALF BLOCK
1968  case 0x2584:
1969  return 0xE2; // LOWER HALF BLOCK
1970  case 0x2594:
1971  return 0xE3; // UPPER ONE EIGHTH BLOCK
1972  case 0x2581:
1973  return 0xE4; // LOWER ONE EIGHTH BLOCK
1974  case 0x258F:
1975  return 0xE5; // LEFT ONE EIGHTH BLOCK
1976  case 0x2592:
1977  return 0xE6; // MEDIUM SHADE
1978  case 0x2595:
1979  return 0xE7; // RIGHT ONE EIGHTH BLOCK
1980  case 0x1FB8F:
1981  return 0xE8; // LOWER HALF MEDIUM SHADE
1982  case 0x1FB99:
1983  return 0xE9; // UPPER RIGHT TO LOWER LEFT FILL
1984  case 0x1FB87:
1985  return 0xEA; // RIGHT ONE QUARTER BLOCK
1986  case 0x251C:
1987  return 0xEB; // BOX DRAWINGS LIGHT VERTICAL AND RIGHT
1988  case 0x2597:
1989  return 0xEC; // QUADRANT LOWER RIGHT
1990  case 0x2514:
1991  return 0xED; // BOX DRAWINGS LIGHT UP AND RIGHT
1992  case 0x2510:
1993  return 0xEE; // BOX DRAWINGS LIGHT DOWN AND LEFT
1994  case 0x2582:
1995  return 0xEF; // LOWER ONE QUARTER BLOCK
1996  case 0x250C:
1997  return 0xF0; // BOX DRAWINGS LIGHT DOWN AND RIGHT
1998  case 0x2534:
1999  return 0xF1; // BOX DRAWINGS LIGHT UP AND HORIZONTAL
2000  case 0x252C:
2001  return 0xF2; // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
2002  case 0x2524:
2003  return 0xF3; // BOX DRAWINGS LIGHT VERTICAL AND LEFT
2004  case 0x258E:
2005  return 0xF4; // LEFT ONE QUARTER BLOCK
2006  case 0x258D:
2007  return 0xF5; // LEFT THREE EIGHTHS BLOCK
2008  case 0x1FB88:
2009  return 0xF6; // RIGHT THREE EIGHTHS BLOCK
2010  case 0x1FB82:
2011  return 0xF7; // UPPER ONE QUARTER BLOCK
2012  case 0x1FB83:
2013  return 0xF8; // UPPER THREE EIGHTHS BLOCK
2014  case 0x2583:
2015  return 0xF9; // LOWER THREE EIGHTHS BLOCK
2016  case 0x2713:
2017  return 0xFA; // CHECK MARK
2018  case 0x2596:
2019  return 0xFB; // QUADRANT LOWER LEFT
2020  case 0x259D:
2021  return 0xFC; // QUADRANT UPPER RIGHT
2022  case 0x2518:
2023  return 0xFD; // BOX DRAWINGS LIGHT UP AND LEFT
2024  case 0x2598:
2025  return 0xFE; // QUADRANT UPPER LEFT
2026  case 0x259A:
2027  return 0xFF; // QUADRANT UPPER LEFT AND LOWER RIGHT
2028  }
2029  }
2030 };
2031 
2032 template <size_t N> struct ISO885915String {
2033  char Str[N]{};
2034 
2035  constexpr ISO885915String(char const (&Src)[N]) {
2036  for (size_t I = 0; I < N; ++I) {
2037  if (Src[I] >= 0x80)
2038  throw "use U prefix for unicode string literals";
2039  Str[I] = TranslateUnicode(Src[I]);
2040  }
2041  }
2042 
2043  constexpr ISO885915String(char16_t const (&Src)[N]) {
2044  for (size_t I = 0; I < N; ++I) {
2045  if (Src[I] >= 0xD800 && Src[I] <= 0xDFFF)
2046  throw "use U prefix for unicode string literals";
2047  Str[I] = TranslateUnicode(Src[I]);
2048  }
2049  }
2050 
2051  constexpr ISO885915String(char32_t const (&Src)[N]) {
2052  for (size_t I = 0; I < N; ++I)
2053  Str[I] = TranslateUnicode(Src[I]);
2054  }
2055 
2056  constexpr char TranslateUnicode(char32_t C) {
2057  switch (C) {
2058  default:
2059  throw "Unsupported";
2060 
2061  // C0 and C1 control codes are uninterpreted.
2062  case 0x0000 ... 0x001f:
2063  case 0x0080 ... 0x009f:
2064  return C;
2065 
2066  // Name: ISO/IEC 8859-15:1999 to Unicode
2067 
2068  // Date: 1999 July 27
2069 
2070  // Original Authors: Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>
2071  // Ken Whistler <ken@unicode.org>
2072 
2073  case 0x0020:
2074  return 0x20; // SPACE
2075  case 0x0021:
2076  return 0x21; // EXCLAMATION MARK
2077  case 0x0022:
2078  return 0x22; // QUOTATION MARK
2079  case 0x0023:
2080  return 0x23; // NUMBER SIGN
2081  case 0x0024:
2082  return 0x24; // DOLLAR SIGN
2083  case 0x0025:
2084  return 0x25; // PERCENT SIGN
2085  case 0x0026:
2086  return 0x26; // AMPERSAND
2087  case 0x0027:
2088  return 0x27; // APOSTROPHE
2089  case 0x0028:
2090  return 0x28; // LEFT PARENTHESIS
2091  case 0x0029:
2092  return 0x29; // RIGHT PARENTHESIS
2093  case 0x002A:
2094  return 0x2A; // ASTERISK
2095  case 0x002B:
2096  return 0x2B; // PLUS SIGN
2097  case 0x002C:
2098  return 0x2C; // COMMA
2099  case 0x002D:
2100  return 0x2D; // HYPHEN-MINUS
2101  case 0x002E:
2102  return 0x2E; // FULL STOP
2103  case 0x002F:
2104  return 0x2F; // SOLIDUS
2105  case 0x0030:
2106  return 0x30; // DIGIT ZERO
2107  case 0x0031:
2108  return 0x31; // DIGIT ONE
2109  case 0x0032:
2110  return 0x32; // DIGIT TWO
2111  case 0x0033:
2112  return 0x33; // DIGIT THREE
2113  case 0x0034:
2114  return 0x34; // DIGIT FOUR
2115  case 0x0035:
2116  return 0x35; // DIGIT FIVE
2117  case 0x0036:
2118  return 0x36; // DIGIT SIX
2119  case 0x0037:
2120  return 0x37; // DIGIT SEVEN
2121  case 0x0038:
2122  return 0x38; // DIGIT EIGHT
2123  case 0x0039:
2124  return 0x39; // DIGIT NINE
2125  case 0x003A:
2126  return 0x3A; // COLON
2127  case 0x003B:
2128  return 0x3B; // SEMICOLON
2129  case 0x003C:
2130  return 0x3C; // LESS-THAN SIGN
2131  case 0x003D:
2132  return 0x3D; // EQUALS SIGN
2133  case 0x003E:
2134  return 0x3E; // GREATER-THAN SIGN
2135  case 0x003F:
2136  return 0x3F; // QUESTION MARK
2137  case 0x0040:
2138  return 0x40; // COMMERCIAL AT
2139  case 0x0041:
2140  return 0x41; // LATIN CAPITAL LETTER A
2141  case 0x0042:
2142  return 0x42; // LATIN CAPITAL LETTER B
2143  case 0x0043:
2144  return 0x43; // LATIN CAPITAL LETTER C
2145  case 0x0044:
2146  return 0x44; // LATIN CAPITAL LETTER D
2147  case 0x0045:
2148  return 0x45; // LATIN CAPITAL LETTER E
2149  case 0x0046:
2150  return 0x46; // LATIN CAPITAL LETTER F
2151  case 0x0047:
2152  return 0x47; // LATIN CAPITAL LETTER G
2153  case 0x0048:
2154  return 0x48; // LATIN CAPITAL LETTER H
2155  case 0x0049:
2156  return 0x49; // LATIN CAPITAL LETTER I
2157  case 0x004A:
2158  return 0x4A; // LATIN CAPITAL LETTER J
2159  case 0x004B:
2160  return 0x4B; // LATIN CAPITAL LETTER K
2161  case 0x004C:
2162  return 0x4C; // LATIN CAPITAL LETTER L
2163  case 0x004D:
2164  return 0x4D; // LATIN CAPITAL LETTER M
2165  case 0x004E:
2166  return 0x4E; // LATIN CAPITAL LETTER N
2167  case 0x004F:
2168  return 0x4F; // LATIN CAPITAL LETTER O
2169  case 0x0050:
2170  return 0x50; // LATIN CAPITAL LETTER P
2171  case 0x0051:
2172  return 0x51; // LATIN CAPITAL LETTER Q
2173  case 0x0052:
2174  return 0x52; // LATIN CAPITAL LETTER R
2175  case 0x0053:
2176  return 0x53; // LATIN CAPITAL LETTER S
2177  case 0x0054:
2178  return 0x54; // LATIN CAPITAL LETTER T
2179  case 0x0055:
2180  return 0x55; // LATIN CAPITAL LETTER U
2181  case 0x0056:
2182  return 0x56; // LATIN CAPITAL LETTER V
2183  case 0x0057:
2184  return 0x57; // LATIN CAPITAL LETTER W
2185  case 0x0058:
2186  return 0x58; // LATIN CAPITAL LETTER X
2187  case 0x0059:
2188  return 0x59; // LATIN CAPITAL LETTER Y
2189  case 0x005A:
2190  return 0x5A; // LATIN CAPITAL LETTER Z
2191  case 0x005B:
2192  return 0x5B; // LEFT SQUARE BRACKET
2193  case 0x005C:
2194  return 0x5C; // REVERSE SOLIDUS
2195  case 0x005D:
2196  return 0x5D; // RIGHT SQUARE BRACKET
2197  case 0x005E:
2198  return 0x5E; // CIRCUMFLEX ACCENT
2199  case 0x005F:
2200  return 0x5F; // LOW LINE
2201  case 0x0060:
2202  return 0x60; // GRAVE ACCENT
2203  case 0x0061:
2204  return 0x61; // LATIN SMALL LETTER A
2205  case 0x0062:
2206  return 0x62; // LATIN SMALL LETTER B
2207  case 0x0063:
2208  return 0x63; // LATIN SMALL LETTER C
2209  case 0x0064:
2210  return 0x64; // LATIN SMALL LETTER D
2211  case 0x0065:
2212  return 0x65; // LATIN SMALL LETTER E
2213  case 0x0066:
2214  return 0x66; // LATIN SMALL LETTER F
2215  case 0x0067:
2216  return 0x67; // LATIN SMALL LETTER G
2217  case 0x0068:
2218  return 0x68; // LATIN SMALL LETTER H
2219  case 0x0069:
2220  return 0x69; // LATIN SMALL LETTER I
2221  case 0x006A:
2222  return 0x6A; // LATIN SMALL LETTER J
2223  case 0x006B:
2224  return 0x6B; // LATIN SMALL LETTER K
2225  case 0x006C:
2226  return 0x6C; // LATIN SMALL LETTER L
2227  case 0x006D:
2228  return 0x6D; // LATIN SMALL LETTER M
2229  case 0x006E:
2230  return 0x6E; // LATIN SMALL LETTER N
2231  case 0x006F:
2232  return 0x6F; // LATIN SMALL LETTER O
2233  case 0x0070:
2234  return 0x70; // LATIN SMALL LETTER P
2235  case 0x0071:
2236  return 0x71; // LATIN SMALL LETTER Q
2237  case 0x0072:
2238  return 0x72; // LATIN SMALL LETTER R
2239  case 0x0073:
2240  return 0x73; // LATIN SMALL LETTER S
2241  case 0x0074:
2242  return 0x74; // LATIN SMALL LETTER T
2243  case 0x0075:
2244  return 0x75; // LATIN SMALL LETTER U
2245  case 0x0076:
2246  return 0x76; // LATIN SMALL LETTER V
2247  case 0x0077:
2248  return 0x77; // LATIN SMALL LETTER W
2249  case 0x0078:
2250  return 0x78; // LATIN SMALL LETTER X
2251  case 0x0079:
2252  return 0x79; // LATIN SMALL LETTER Y
2253  case 0x007A:
2254  return 0x7A; // LATIN SMALL LETTER Z
2255  case 0x007B:
2256  return 0x7B; // LEFT CURLY BRACKET
2257  case 0x007C:
2258  return 0x7C; // VERTICAL LINE
2259  case 0x007D:
2260  return 0x7D; // RIGHT CURLY BRACKET
2261  case 0x007E:
2262  return 0x7E; // TILDE
2263  case 0x007F:
2264  return 0x7F; // DELETE
2265  case 0x00A0:
2266  return 0xA0; // NO-BREAK SPACE
2267  case 0x00A1:
2268  return 0xA1; // INVERTED EXCLAMATION MARK
2269  case 0x00A2:
2270  return 0xA2; // CENT SIGN
2271  case 0x00A3:
2272  return 0xA3; // POUND SIGN
2273  case 0x20AC:
2274  return 0xA4; // EURO SIGN
2275  case 0x00A5:
2276  return 0xA5; // YEN SIGN
2277  case 0x0160:
2278  return 0xA6; // LATIN CAPITAL LETTER S WITH CARON
2279  case 0x00A7:
2280  return 0xA7; // SECTION SIGN
2281  case 0x0161:
2282  return 0xA8; // LATIN SMALL LETTER S WITH CARON
2283  case 0x00A9:
2284  return 0xA9; // COPYRIGHT SIGN
2285  case 0x00AA:
2286  return 0xAA; // FEMININE ORDINAL INDICATOR
2287  case 0x00AB:
2288  return 0xAB; // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
2289  case 0x00AC:
2290  return 0xAC; // NOT SIGN
2291  case 0x00AD:
2292  return 0xAD; // SOFT HYPHEN
2293  case 0x00AE:
2294  return 0xAE; // REGISTERED SIGN
2295  case 0x00AF:
2296  return 0xAF; // MACRON
2297  case 0x00B0:
2298  return 0xB0; // DEGREE SIGN
2299  case 0x00B1:
2300  return 0xB1; // PLUS-MINUS SIGN
2301  case 0x00B2:
2302  return 0xB2; // SUPERSCRIPT TWO
2303  case 0x00B3:
2304  return 0xB3; // SUPERSCRIPT THREE
2305  case 0x017D:
2306  return 0xB4; // LATIN CAPITAL LETTER Z WITH CARON
2307  case 0x00B5:
2308  return 0xB5; // MICRO SIGN
2309  case 0x00B6:
2310  return 0xB6; // PILCROW SIGN
2311  case 0x00B7:
2312  return 0xB7; // MIDDLE DOT
2313  case 0x017E:
2314  return 0xB8; // LATIN SMALL LETTER Z WITH CARON
2315  case 0x00B9:
2316  return 0xB9; // SUPERSCRIPT ONE
2317  case 0x00BA:
2318  return 0xBA; // MASCULINE ORDINAL INDICATOR
2319  case 0x00BB:
2320  return 0xBB; // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
2321  case 0x0152:
2322  return 0xBC; // LATIN CAPITAL LIGATURE OE
2323  case 0x0153:
2324  return 0xBD; // LATIN SMALL LIGATURE OE
2325  case 0x0178:
2326  return 0xBE; // LATIN CAPITAL LETTER Y WITH DIAERESIS
2327  case 0x00BF:
2328  return 0xBF; // INVERTED QUESTION MARK
2329  case 0x00C0:
2330  return 0xC0; // LATIN CAPITAL LETTER A WITH GRAVE
2331  case 0x00C1:
2332  return 0xC1; // LATIN CAPITAL LETTER A WITH ACUTE
2333  case 0x00C2:
2334  return 0xC2; // LATIN CAPITAL LETTER A WITH CIRCUMFLEX
2335  case 0x00C3:
2336  return 0xC3; // LATIN CAPITAL LETTER A WITH TILDE
2337  case 0x00C4:
2338  return 0xC4; // LATIN CAPITAL LETTER A WITH DIAERESIS
2339  case 0x00C5:
2340  return 0xC5; // LATIN CAPITAL LETTER A WITH RING ABOVE
2341  case 0x00C6:
2342  return 0xC6; // LATIN CAPITAL LETTER AE
2343  case 0x00C7:
2344  return 0xC7; // LATIN CAPITAL LETTER C WITH CEDILLA
2345  case 0x00C8:
2346  return 0xC8; // LATIN CAPITAL LETTER E WITH GRAVE
2347  case 0x00C9:
2348  return 0xC9; // LATIN CAPITAL LETTER E WITH ACUTE
2349  case 0x00CA:
2350  return 0xCA; // LATIN CAPITAL LETTER E WITH CIRCUMFLEX
2351  case 0x00CB:
2352  return 0xCB; // LATIN CAPITAL LETTER E WITH DIAERESIS
2353  case 0x00CC:
2354  return 0xCC; // LATIN CAPITAL LETTER I WITH GRAVE
2355  case 0x00CD:
2356  return 0xCD; // LATIN CAPITAL LETTER I WITH ACUTE
2357  case 0x00CE:
2358  return 0xCE; // LATIN CAPITAL LETTER I WITH CIRCUMFLEX
2359  case 0x00CF:
2360  return 0xCF; // LATIN CAPITAL LETTER I WITH DIAERESIS
2361  case 0x00D0:
2362  return 0xD0; // LATIN CAPITAL LETTER ETH
2363  case 0x00D1:
2364  return 0xD1; // LATIN CAPITAL LETTER N WITH TILDE
2365  case 0x00D2:
2366  return 0xD2; // LATIN CAPITAL LETTER O WITH GRAVE
2367  case 0x00D3:
2368  return 0xD3; // LATIN CAPITAL LETTER O WITH ACUTE
2369  case 0x00D4:
2370  return 0xD4; // LATIN CAPITAL LETTER O WITH CIRCUMFLEX
2371  case 0x00D5:
2372  return 0xD5; // LATIN CAPITAL LETTER O WITH TILDE
2373  case 0x00D6:
2374  return 0xD6; // LATIN CAPITAL LETTER O WITH DIAERESIS
2375  case 0x00D7:
2376  return 0xD7; // MULTIPLICATION SIGN
2377  case 0x00D8:
2378  return 0xD8; // LATIN CAPITAL LETTER O WITH STROKE
2379  case 0x00D9:
2380  return 0xD9; // LATIN CAPITAL LETTER U WITH GRAVE
2381  case 0x00DA:
2382  return 0xDA; // LATIN CAPITAL LETTER U WITH ACUTE
2383  case 0x00DB:
2384  return 0xDB; // LATIN CAPITAL LETTER U WITH CIRCUMFLEX
2385  case 0x00DC:
2386  return 0xDC; // LATIN CAPITAL LETTER U WITH DIAERESIS
2387  case 0x00DD:
2388  return 0xDD; // LATIN CAPITAL LETTER Y WITH ACUTE
2389  case 0x00DE:
2390  return 0xDE; // LATIN CAPITAL LETTER THORN
2391  case 0x00DF:
2392  return 0xDF; // LATIN SMALL LETTER SHARP S
2393  case 0x00E0:
2394  return 0xE0; // LATIN SMALL LETTER A WITH GRAVE
2395  case 0x00E1:
2396  return 0xE1; // LATIN SMALL LETTER A WITH ACUTE
2397  case 0x00E2:
2398  return 0xE2; // LATIN SMALL LETTER A WITH CIRCUMFLEX
2399  case 0x00E3:
2400  return 0xE3; // LATIN SMALL LETTER A WITH TILDE
2401  case 0x00E4:
2402  return 0xE4; // LATIN SMALL LETTER A WITH DIAERESIS
2403  case 0x00E5:
2404  return 0xE5; // LATIN SMALL LETTER A WITH RING ABOVE
2405  case 0x00E6:
2406  return 0xE6; // LATIN SMALL LETTER AE
2407  case 0x00E7:
2408  return 0xE7; // LATIN SMALL LETTER C WITH CEDILLA
2409  case 0x00E8:
2410  return 0xE8; // LATIN SMALL LETTER E WITH GRAVE
2411  case 0x00E9:
2412  return 0xE9; // LATIN SMALL LETTER E WITH ACUTE
2413  case 0x00EA:
2414  return 0xEA; // LATIN SMALL LETTER E WITH CIRCUMFLEX
2415  case 0x00EB:
2416  return 0xEB; // LATIN SMALL LETTER E WITH DIAERESIS
2417  case 0x00EC:
2418  return 0xEC; // LATIN SMALL LETTER I WITH GRAVE
2419  case 0x00ED:
2420  return 0xED; // LATIN SMALL LETTER I WITH ACUTE
2421  case 0x00EE:
2422  return 0xEE; // LATIN SMALL LETTER I WITH CIRCUMFLEX
2423  case 0x00EF:
2424  return 0xEF; // LATIN SMALL LETTER I WITH DIAERESIS
2425  case 0x00F0:
2426  return 0xF0; // LATIN SMALL LETTER ETH
2427  case 0x00F1:
2428  return 0xF1; // LATIN SMALL LETTER N WITH TILDE
2429  case 0x00F2:
2430  return 0xF2; // LATIN SMALL LETTER O WITH GRAVE
2431  case 0x00F3:
2432  return 0xF3; // LATIN SMALL LETTER O WITH ACUTE
2433  case 0x00F4:
2434  return 0xF4; // LATIN SMALL LETTER O WITH CIRCUMFLEX
2435  case 0x00F5:
2436  return 0xF5; // LATIN SMALL LETTER O WITH TILDE
2437  case 0x00F6:
2438  return 0xF6; // LATIN SMALL LETTER O WITH DIAERESIS
2439  case 0x00F7:
2440  return 0xF7; // DIVISION SIGN
2441  case 0x00F8:
2442  return 0xF8; // LATIN SMALL LETTER O WITH STROKE
2443  case 0x00F9:
2444  return 0xF9; // LATIN SMALL LETTER U WITH GRAVE
2445  case 0x00FA:
2446  return 0xFA; // LATIN SMALL LETTER U WITH ACUTE
2447  case 0x00FB:
2448  return 0xFB; // LATIN SMALL LETTER U WITH CIRCUMFLEX
2449  case 0x00FC:
2450  return 0xFC; // LATIN SMALL LETTER U WITH DIAERESIS
2451  case 0x00FD:
2452  return 0xFD; // LATIN SMALL LETTER Y WITH ACUTE
2453  case 0x00FE:
2454  return 0xFE; // LATIN SMALL LETTER THORN
2455  case 0x00FF:
2456  return 0xFF; // LATIN SMALL LETTER Y WITH DIAERESIS
2457  }
2458  }
2459 };
2460 
2461 } // namespace charset_impl
2462 
2463 template <charset_impl::UnshiftedString S> constexpr auto operator""_u() {
2464  return S.Str;
2465 }
2466 
2467 template <charset_impl::ShiftedString S> constexpr auto operator""_s() {
2468  return S.Str;
2469 }
2470 
2471 template <charset_impl::UnshiftedVideoString S> constexpr auto operator""_uv() {
2472  return S.Str;
2473 }
2474 
2475 template <charset_impl::UnshiftedReverseVideoString S>
2476 constexpr auto operator""_urv() {
2477  return S.Str;
2478 }
2479 
2480 template <charset_impl::ShiftedVideoString S> constexpr auto operator""_sv() {
2481  return S.Str;
2482 }
2483 
2484 template <charset_impl::ShiftedReverseVideoString S>
2485 constexpr auto operator""_srv() {
2486  return S.Str;
2487 }
2488 
2489 template <charset_impl::ISO885915String S> constexpr auto operator""_i() {
2490  return S.Str;
2491 }
2492 
2493 #endif // not _CHARSET_H
2494 #endif // __cplusplus >= 202002L
cstddef