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 VIC-20 (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 RIGHT
212  case 0x2571:
213  return 0x6E; // BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT
214  case 0x1FB7D:
215  return 0x6F; // LEFT AND UPPER ONE EIGHTH BLOCK
216  case 0x1FB7E:
217  return 0x70; // RIGHT AND UPPER ONE EIGHTH BLOCK
218  case 0x2022:
219  return 0x71; // BULLET (or 0x25CF BLACK CIRCLE)
220  case 0x1FB7B:
221  return 0x72; // HORIZONTAL ONE EIGHTH BLOCK-7
222  case 0x2665:
223  return 0x73; // BLACK HEART SUIT
224  case 0x1FB70:
225  return 0x74; // VERTICAL ONE EIGHTH BLOCK-2
226  case 0x256D:
227  return 0x75; // BOX DRAWINGS LIGHT ARC DOWN AND RIGHT
228  case 0x2573:
229  return 0x76; // BOX DRAWINGS LIGHT DIAGONAL CROSS
230  case 0x25CB:
231  return 0x77; // WHITE CIRCLE (or 0x25E6 WHITE BULLET)
232  case 0x2663:
233  return 0x78; // BLACK CLUB SUIT
234  case 0x1FB75:
235  return 0x79; // VERTICAL ONE EIGHTH BLOCK-7
236  case 0x2666:
237  return 0x7A; // BLACK DIAMOND SUIT
238  case 0x253C:
239  return 0x7B; // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
240  case 0x1FB8C:
241  return 0x7C; // LEFT HALF MEDIUM SHADE
242  case 0x2502:
243  return 0x7D; // BOX DRAWINGS LIGHT VERTICAL
244  case 0x03C0:
245  return 0x7E; // GREEK SMALL LETTER PI
246  case 0x25E5:
247  return 0x7F; // BLACK UPPER RIGHT TRIANGLE
248  case 0x00A0:
249  return 0xA0; // NO-BREAK SPACE
250  case 0x258C:
251  return 0xA1; // LEFT HALF BLOCK
252  case 0x2584:
253  return 0xA2; // LOWER HALF BLOCK
254  case 0x2581:
255  return 0xA4; // LOWER ONE EIGHTH BLOCK
256  case 0x258F:
257  return 0xA5; // LEFT ONE EIGHTH BLOCK
258  case 0x2592:
259  return 0xA6; // MEDIUM SHADE
260  case 0x2595:
261  return 0xA7; // RIGHT ONE EIGHTH BLOCK
262  case 0x1FB8F:
263  return 0xA8; // LOWER HALF MEDIUM SHADE
264  case 0x25E4:
265  return 0xA9; // BLACK UPPER LEFT TRIANGLE
266  case 0x1FB87:
267  return 0xAA; // RIGHT ONE QUARTER BLOCK
268  case 0x251C:
269  return 0xAB; // BOX DRAWINGS LIGHT VERTICAL AND RIGHT
270  case 0x2597:
271  return 0xAC; // QUADRANT LOWER RIGHT
272  case 0x2514:
273  return 0xAD; // BOX DRAWINGS LIGHT UP AND RIGHT
274  case 0x2510:
275  return 0xAE; // BOX DRAWINGS LIGHT DOWN AND LEFT
276  case 0x2582:
277  return 0xAF; // LOWER ONE QUARTER BLOCK
278  case 0x250C:
279  return 0xB0; // BOX DRAWINGS LIGHT DOWN AND RIGHT
280  case 0x2534:
281  return 0xB1; // BOX DRAWINGS LIGHT UP AND HORIZONTAL
282  case 0x252C:
283  return 0xB2; // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
284  case 0x2524:
285  return 0xB3; // BOX DRAWINGS LIGHT VERTICAL AND LEFT
286  case 0x258E:
287  return 0xB4; // LEFT ONE QUARTER BLOCK
288  case 0x258D:
289  return 0xB5; // LEFT THREE EIGHTHS BLOCK
290  case 0x1FB88:
291  return 0xB6; // RIGHT THREE EIGHTHS BLOCK
292  case 0x1FB82:
293  return 0xB7; // UPPER ONE QUARTER BLOCK
294  case 0x1FB83:
295  return 0xB8; // UPPER THREE EIGHTHS BLOCK
296  case 0x2583:
297  return 0xB9; // LOWER THREE EIGHTHS BLOCK
298  case 0x1FB7F:
299  return 0xBA; // RIGHT AND LOWER ONE EIGHTH BLOCK
300  case 0x2596:
301  return 0xBB; // QUADRANT LOWER LEFT
302  case 0x259D:
303  return 0xBC; // QUADRANT UPPER RIGHT
304  case 0x2518:
305  return 0xBD; // BOX DRAWINGS LIGHT UP AND LEFT
306  case 0x2598:
307  return 0xBE; // QUADRANT UPPER LEFT
308  case 0x259A:
309  return 0xBF; // QUADRANT UPPER LEFT AND LOWER RIGHT
310  case 0x2594:
311  return 0xE3; // UPPER ONE EIGHTH BLOCK
312  }
313  }
314 };
315 
316 template <size_t N> struct ShiftedString {
317  char Str[N]{};
318 
319  constexpr ShiftedString(char const (&Src)[N]) {
320  for (size_t I = 0; I < N; ++I) {
321  if (Src[I] >= 0x80)
322  throw "use U prefix for unicode string literals";
323  Str[I] = TranslateUnicode(Src[I]);
324  }
325  }
326 
327  constexpr ShiftedString(char16_t const (&Src)[N]) {
328  for (size_t I = 0; I < N; ++I) {
329  if (Src[I] >= 0xD800 && Src[I] <= 0xDFFF)
330  throw "use U prefix for unicode string literals";
331  Str[I] = TranslateUnicode(Src[I]);
332  }
333  }
334 
335  constexpr ShiftedString(char32_t const (&Src)[N]) {
336  for (size_t I = 0; I < N; ++I)
337  Str[I] = TranslateUnicode(Src[I]);
338  }
339 
340  constexpr char TranslateUnicode(char32_t C) {
341  switch (C) {
342  default:
343  throw "Unsupported";
344 
345  // C0 control codes are uninterpreted.
346  case 0x0000 ... 0x001f:
347  return C;
348 
349  // Name: Map from Commodore VIC-20 (interchange) alternate character set
350  // to Unicode
351 
352  // Date: 2018 October 11
353 
354  // Original Author: Rebecca Bettencourt <support@kreativekorp.com>
355 
356  case 0x0020:
357  return 0x20; // SPACE
358  case 0x0021:
359  return 0x21; // EXCLAMATION MARK
360  case 0x0022:
361  return 0x22; // QUOTATION MARK
362  case 0x0023:
363  return 0x23; // NUMBER SIGN
364  case 0x0024:
365  return 0x24; // DOLLAR SIGN
366  case 0x0025:
367  return 0x25; // PERCENT SIGN
368  case 0x0026:
369  return 0x26; // AMPERSAND
370  case 0x0027:
371  return 0x27; // APOSTROPHE
372  case 0x0028:
373  return 0x28; // LEFT PARENTHESIS
374  case 0x0029:
375  return 0x29; // RIGHT PARENTHESIS
376  case 0x002A:
377  return 0x2A; // ASTERISK
378  case 0x002B:
379  return 0x2B; // PLUS SIGN
380  case 0x002C:
381  return 0x2C; // COMMA
382  case 0x002D:
383  return 0x2D; // HYPHEN-MINUS
384  case 0x002E:
385  return 0x2E; // FULL STOP
386  case 0x002F:
387  return 0x2F; // SOLIDUS
388  case 0x0030:
389  return 0x30; // DIGIT ZERO
390  case 0x0031:
391  return 0x31; // DIGIT ONE
392  case 0x0032:
393  return 0x32; // DIGIT TWO
394  case 0x0033:
395  return 0x33; // DIGIT THREE
396  case 0x0034:
397  return 0x34; // DIGIT FOUR
398  case 0x0035:
399  return 0x35; // DIGIT FIVE
400  case 0x0036:
401  return 0x36; // DIGIT SIX
402  case 0x0037:
403  return 0x37; // DIGIT SEVEN
404  case 0x0038:
405  return 0x38; // DIGIT EIGHT
406  case 0x0039:
407  return 0x39; // DIGIT NINE
408  case 0x003A:
409  return 0x3A; // COLON
410  case 0x003B:
411  return 0x3B; // SEMICOLON
412  case 0x003C:
413  return 0x3C; // LESS-THAN SIGN
414  case 0x003D:
415  return 0x3D; // EQUALS SIGN
416  case 0x003E:
417  return 0x3E; // GREATER-THAN SIGN
418  case 0x003F:
419  return 0x3F; // QUESTION MARK
420  case 0x0040:
421  return 0x40; // COMMERCIAL AT
422  case 0x0061:
423  return 0x41; // LATIN SMALL LETTER A
424  case 0x0062:
425  return 0x42; // LATIN SMALL LETTER B
426  case 0x0063:
427  return 0x43; // LATIN SMALL LETTER C
428  case 0x0064:
429  return 0x44; // LATIN SMALL LETTER D
430  case 0x0065:
431  return 0x45; // LATIN SMALL LETTER E
432  case 0x0066:
433  return 0x46; // LATIN SMALL LETTER F
434  case 0x0067:
435  return 0x47; // LATIN SMALL LETTER G
436  case 0x0068:
437  return 0x48; // LATIN SMALL LETTER H
438  case 0x0069:
439  return 0x49; // LATIN SMALL LETTER I
440  case 0x006A:
441  return 0x4A; // LATIN SMALL LETTER J
442  case 0x006B:
443  return 0x4B; // LATIN SMALL LETTER K
444  case 0x006C:
445  return 0x4C; // LATIN SMALL LETTER L
446  case 0x006D:
447  return 0x4D; // LATIN SMALL LETTER M
448  case 0x006E:
449  return 0x4E; // LATIN SMALL LETTER N
450  case 0x006F:
451  return 0x4F; // LATIN SMALL LETTER O
452  case 0x0070:
453  return 0x50; // LATIN SMALL LETTER P
454  case 0x0071:
455  return 0x51; // LATIN SMALL LETTER Q
456  case 0x0072:
457  return 0x52; // LATIN SMALL LETTER R
458  case 0x0073:
459  return 0x53; // LATIN SMALL LETTER S
460  case 0x0074:
461  return 0x54; // LATIN SMALL LETTER T
462  case 0x0075:
463  return 0x55; // LATIN SMALL LETTER U
464  case 0x0076:
465  return 0x56; // LATIN SMALL LETTER V
466  case 0x0077:
467  return 0x57; // LATIN SMALL LETTER W
468  case 0x0078:
469  return 0x58; // LATIN SMALL LETTER X
470  case 0x0079:
471  return 0x59; // LATIN SMALL LETTER Y
472  case 0x007A:
473  return 0x5A; // LATIN SMALL LETTER Z
474  case 0x005B:
475  return 0x5B; // LEFT SQUARE BRACKET
476  case 0x00A3:
477  return 0x5C; // POUND SIGN
478  case 0x005D:
479  return 0x5D; // RIGHT SQUARE BRACKET
480  case 0x2191:
481  return 0x5E; // UPWARDS ARROW
482  case 0x2190:
483  return 0x5F; // LEFTWARDS ARROW
484  case 0x2500:
485  return 0x60; // BOX DRAWINGS LIGHT HORIZONTAL
486  case 0x0041:
487  return 0x61; // LATIN CAPITAL LETTER A
488  case 0x0042:
489  return 0x62; // LATIN CAPITAL LETTER B
490  case 0x0043:
491  return 0x63; // LATIN CAPITAL LETTER C
492  case 0x0044:
493  return 0x64; // LATIN CAPITAL LETTER D
494  case 0x0045:
495  return 0x65; // LATIN CAPITAL LETTER E
496  case 0x0046:
497  return 0x66; // LATIN CAPITAL LETTER F
498  case 0x0047:
499  return 0x67; // LATIN CAPITAL LETTER G
500  case 0x0048:
501  return 0x68; // LATIN CAPITAL LETTER H
502  case 0x0049:
503  return 0x69; // LATIN CAPITAL LETTER I
504  case 0x004A:
505  return 0x6A; // LATIN CAPITAL LETTER J
506  case 0x004B:
507  return 0x6B; // LATIN CAPITAL LETTER K
508  case 0x004C:
509  return 0x6C; // LATIN CAPITAL LETTER L
510  case 0x004D:
511  return 0x6D; // LATIN CAPITAL LETTER M
512  case 0x004E:
513  return 0x6E; // LATIN CAPITAL LETTER N
514  case 0x004F:
515  return 0x6F; // LATIN CAPITAL LETTER O
516  case 0x0050:
517  return 0x70; // LATIN CAPITAL LETTER P
518  case 0x0051:
519  return 0x71; // LATIN CAPITAL LETTER Q
520  case 0x0052:
521  return 0x72; // LATIN CAPITAL LETTER R
522  case 0x0053:
523  return 0x73; // LATIN CAPITAL LETTER S
524  case 0x0054:
525  return 0x74; // LATIN CAPITAL LETTER T
526  case 0x0055:
527  return 0x75; // LATIN CAPITAL LETTER U
528  case 0x0056:
529  return 0x76; // LATIN CAPITAL LETTER V
530  case 0x0057:
531  return 0x77; // LATIN CAPITAL LETTER W
532  case 0x0058:
533  return 0x78; // LATIN CAPITAL LETTER X
534  case 0x0059:
535  return 0x79; // LATIN CAPITAL LETTER Y
536  case 0x005A:
537  return 0x7A; // LATIN CAPITAL LETTER Z
538  case 0x253C:
539  return 0x7B; // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
540  case 0x1FB8C:
541  return 0x7C; // LEFT HALF MEDIUM SHADE
542  case 0x2502:
543  return 0x7D; // BOX DRAWINGS LIGHT VERTICAL
544  case 0x1FB95:
545  return 0x7E; // CHECKER BOARD FILL
546  case 0x1FB98:
547  return 0x7F; // UPPER LEFT TO LOWER RIGHT FILL
548  case 0x00A0:
549  return 0xA0; // NO-BREAK SPACE
550  case 0x258C:
551  return 0xA1; // LEFT HALF BLOCK
552  case 0x2584:
553  return 0xA2; // LOWER HALF BLOCK
554  case 0x2594:
555  return 0xA3; // UPPER ONE EIGHTH BLOCK
556  case 0x2581:
557  return 0xA4; // LOWER ONE EIGHTH BLOCK
558  case 0x258F:
559  return 0xA5; // LEFT ONE EIGHTH BLOCK
560  case 0x2592:
561  return 0xA6; // MEDIUM SHADE
562  case 0x2595:
563  return 0xA7; // RIGHT ONE EIGHTH BLOCK
564  case 0x1FB8F:
565  return 0xA8; // LOWER HALF MEDIUM SHADE
566  case 0x1FB99:
567  return 0xA9; // UPPER RIGHT TO LOWER LEFT FILL
568  case 0x1FB87:
569  return 0xAA; // RIGHT ONE QUARTER BLOCK
570  case 0x251C:
571  return 0xAB; // BOX DRAWINGS LIGHT VERTICAL AND RIGHT
572  case 0x2597:
573  return 0xAC; // QUADRANT LOWER RIGHT
574  case 0x2514:
575  return 0xAD; // BOX DRAWINGS LIGHT UP AND RIGHT
576  case 0x2510:
577  return 0xAE; // BOX DRAWINGS LIGHT DOWN AND LEFT
578  case 0x2582:
579  return 0xAF; // LOWER ONE QUARTER BLOCK
580  case 0x250C:
581  return 0xB0; // BOX DRAWINGS LIGHT DOWN AND RIGHT
582  case 0x2534:
583  return 0xB1; // BOX DRAWINGS LIGHT UP AND HORIZONTAL
584  case 0x252C:
585  return 0xB2; // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
586  case 0x2524:
587  return 0xB3; // BOX DRAWINGS LIGHT VERTICAL AND LEFT
588  case 0x258E:
589  return 0xB4; // LEFT ONE QUARTER BLOCK
590  case 0x258D:
591  return 0xB5; // LEFT THREE EIGHTHS BLOCK
592  case 0x1FB88:
593  return 0xB6; // RIGHT THREE EIGHTHS BLOCK
594  case 0x1FB82:
595  return 0xB7; // UPPER ONE QUARTER BLOCK
596  case 0x1FB83:
597  return 0xB8; // UPPER THREE EIGHTHS BLOCK
598  case 0x2583:
599  return 0xB9; // LOWER THREE EIGHTHS BLOCK
600  case 0x2713:
601  return 0xBA; // CHECK MARK
602  case 0x2596:
603  return 0xBB; // QUADRANT LOWER LEFT
604  case 0x259D:
605  return 0xBC; // QUADRANT UPPER RIGHT
606  case 0x2518:
607  return 0xBD; // BOX DRAWINGS LIGHT UP AND LEFT
608  case 0x2598:
609  return 0xBE; // QUADRANT UPPER LEFT
610  case 0x259A:
611  return 0xBF; // QUADRANT UPPER LEFT AND LOWER RIGHT
612  }
613  };
614 };
615 
616 template <size_t N> struct UnshiftedVideoString {
617  char Str[N]{};
618 
619  constexpr UnshiftedVideoString(char const (&Src)[N]) {
620  for (size_t I = 0; I < N; ++I) {
621  if (Src[I] >= 0x80)
622  throw "use U prefix for unicode string literals";
623  Str[I] = TranslateUnicode(Src[I]);
624  }
625  }
626 
627  constexpr UnshiftedVideoString(char16_t const (&Src)[N]) {
628  for (size_t I = 0; I < N; ++I) {
629  if (Src[I] >= 0xD800 && Src[I] <= 0xDFFF)
630  throw "use U prefix for unicode string literals";
631  Str[I] = TranslateUnicode(Src[I]);
632  }
633  }
634 
635  constexpr UnshiftedVideoString(char32_t const (&Src)[N]) {
636  for (size_t I = 0; I < N; ++I)
637  Str[I] = TranslateUnicode(Src[I]);
638  }
639 
640  constexpr char TranslateUnicode(char32_t C) {
641  switch (C) {
642  default:
643  throw "Unsupported";
644 
645  // Preserve NUL
646  case 0x0000:
647  return 0x00;
648 
649  // Name: Map from Commodore VIC-20 (video) primary character set to
650  // Unicode
651 
652  // Date: 2018 April 20
653 
654  // Author: Rebecca Bettencourt <support@kreativekorp.com>
655 
656  case 0x0040:
657  return 0x00; // COMMERCIAL AT
658  case 0x0041:
659  return 0x01; // LATIN CAPITAL LETTER A
660  case 0x0042:
661  return 0x02; // LATIN CAPITAL LETTER B
662  case 0x0043:
663  return 0x03; // LATIN CAPITAL LETTER C
664  case 0x0044:
665  return 0x04; // LATIN CAPITAL LETTER D
666  case 0x0045:
667  return 0x05; // LATIN CAPITAL LETTER E
668  case 0x0046:
669  return 0x06; // LATIN CAPITAL LETTER F
670  case 0x0047:
671  return 0x07; // LATIN CAPITAL LETTER G
672  case 0x0048:
673  return 0x08; // LATIN CAPITAL LETTER H
674  case 0x0049:
675  return 0x09; // LATIN CAPITAL LETTER I
676  case 0x004A:
677  return 0x0A; // LATIN CAPITAL LETTER J
678  case 0x004B:
679  return 0x0B; // LATIN CAPITAL LETTER K
680  case 0x004C:
681  return 0x0C; // LATIN CAPITAL LETTER L
682  case 0x004D:
683  return 0x0D; // LATIN CAPITAL LETTER M
684  case 0x004E:
685  return 0x0E; // LATIN CAPITAL LETTER N
686  case 0x004F:
687  return 0x0F; // LATIN CAPITAL LETTER O
688  case 0x0050:
689  return 0x10; // LATIN CAPITAL LETTER P
690  case 0x0051:
691  return 0x11; // LATIN CAPITAL LETTER Q
692  case 0x0052:
693  return 0x12; // LATIN CAPITAL LETTER R
694  case 0x0053:
695  return 0x13; // LATIN CAPITAL LETTER S
696  case 0x0054:
697  return 0x14; // LATIN CAPITAL LETTER T
698  case 0x0055:
699  return 0x15; // LATIN CAPITAL LETTER U
700  case 0x0056:
701  return 0x16; // LATIN CAPITAL LETTER V
702  case 0x0057:
703  return 0x17; // LATIN CAPITAL LETTER W
704  case 0x0058:
705  return 0x18; // LATIN CAPITAL LETTER X
706  case 0x0059:
707  return 0x19; // LATIN CAPITAL LETTER Y
708  case 0x005A:
709  return 0x1A; // LATIN CAPITAL LETTER Z
710  case 0x005B:
711  return 0x1B; // LEFT SQUARE BRACKET
712  case 0x00A3:
713  return 0x1C; // POUND SIGN
714  case 0x005D:
715  return 0x1D; // RIGHT SQUARE BRACKET
716  case 0x2191:
717  return 0x1E; // UPWARDS ARROW
718  case 0x2190:
719  return 0x1F; // LEFTWARDS ARROW
720  case 0x0020:
721  return 0x20; // SPACE
722  case 0x0021:
723  return 0x21; // EXCLAMATION MARK
724  case 0x0022:
725  return 0x22; // QUOTATION MARK
726  case 0x0023:
727  return 0x23; // NUMBER SIGN
728  case 0x0024:
729  return 0x24; // DOLLAR SIGN
730  case 0x0025:
731  return 0x25; // PERCENT SIGN
732  case 0x0026:
733  return 0x26; // AMPERSAND
734  case 0x0027:
735  return 0x27; // APOSTROPHE
736  case 0x0028:
737  return 0x28; // LEFT PARENTHESIS
738  case 0x0029:
739  return 0x29; // RIGHT PARENTHESIS
740  case 0x002A:
741  return 0x2A; // ASTERISK
742  case 0x002B:
743  return 0x2B; // PLUS SIGN
744  case 0x002C:
745  return 0x2C; // COMMA
746  case 0x002D:
747  return 0x2D; // HYPHEN-MINUS
748  case 0x002E:
749  return 0x2E; // FULL STOP
750  case 0x002F:
751  return 0x2F; // SOLIDUS
752  case 0x0030:
753  return 0x30; // DIGIT ZERO
754  case 0x0031:
755  return 0x31; // DIGIT ONE
756  case 0x0032:
757  return 0x32; // DIGIT TWO
758  case 0x0033:
759  return 0x33; // DIGIT THREE
760  case 0x0034:
761  return 0x34; // DIGIT FOUR
762  case 0x0035:
763  return 0x35; // DIGIT FIVE
764  case 0x0036:
765  return 0x36; // DIGIT SIX
766  case 0x0037:
767  return 0x37; // DIGIT SEVEN
768  case 0x0038:
769  return 0x38; // DIGIT EIGHT
770  case 0x0039:
771  return 0x39; // DIGIT NINE
772  case 0x003A:
773  return 0x3A; // COLON
774  case 0x003B:
775  return 0x3B; // SEMICOLON
776  case 0x003C:
777  return 0x3C; // LESS-THAN SIGN
778  case 0x003D:
779  return 0x3D; // EQUALS SIGN
780  case 0x003E:
781  return 0x3E; // GREATER-THAN SIGN
782  case 0x003F:
783  return 0x3F; // QUESTION MARK
784  case 0x2500:
785  return 0x40; // BOX DRAWINGS LIGHT HORIZONTAL
786  case 0x2660:
787  return 0x41; // BLACK SPADE SUIT
788  case 0x1FB72:
789  return 0x42; // VERTICAL ONE EIGHTH BLOCK-4
790  case 0x1FB78:
791  return 0x43; // HORIZONTAL ONE EIGHTH BLOCK-4
792  case 0x1FB77:
793  return 0x44; // HORIZONTAL ONE EIGHTH BLOCK-3
794  case 0x1FB76:
795  return 0x45; // HORIZONTAL ONE EIGHTH BLOCK-2
796  case 0x1FB7A:
797  return 0x46; // HORIZONTAL ONE EIGHTH BLOCK-6
798  case 0x1FB71:
799  return 0x47; // VERTICAL ONE EIGHTH BLOCK-3
800  case 0x1FB74:
801  return 0x48; // VERTICAL ONE EIGHTH BLOCK-6
802  case 0x256E:
803  return 0x49; // BOX DRAWINGS LIGHT ARC DOWN AND LEFT
804  case 0x2570:
805  return 0x4A; // BOX DRAWINGS LIGHT ARC UP AND RIGHT
806  case 0x256F:
807  return 0x4B; // BOX DRAWINGS LIGHT ARC UP AND LEFT
808  case 0x1FB7C:
809  return 0x4C; // LEFT AND LOWER ONE EIGHTH BLOCK
810  case 0x2572:
811  return 0x4D; // BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT
812  case 0x2571:
813  return 0x4E; // BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT
814  case 0x1FB7D:
815  return 0x4F; // LEFT AND UPPER ONE EIGHTH BLOCK
816  case 0x1FB7E:
817  return 0x50; // RIGHT AND UPPER ONE EIGHTH BLOCK
818  case 0x2022:
819  return 0x51; // BULLET (or 0x25CF BLACK CIRCLE)
820  case 0x1FB7B:
821  return 0x52; // HORIZONTAL ONE EIGHTH BLOCK-7
822  case 0x2665:
823  return 0x53; // BLACK HEART SUIT
824  case 0x1FB70:
825  return 0x54; // VERTICAL ONE EIGHTH BLOCK-2
826  case 0x256D:
827  return 0x55; // BOX DRAWINGS LIGHT ARC DOWN AND RIGHT
828  case 0x2573:
829  return 0x56; // BOX DRAWINGS LIGHT DIAGONAL CROSS
830  case 0x25CB:
831  return 0x57; // WHITE CIRCLE (or 0x25E6 WHITE BULLET)
832  case 0x2663:
833  return 0x58; // BLACK CLUB SUIT
834  case 0x1FB75:
835  return 0x59; // VERTICAL ONE EIGHTH BLOCK-7
836  case 0x2666:
837  return 0x5A; // BLACK DIAMOND SUIT
838  case 0x253C:
839  return 0x5B; // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
840  case 0x1FB8C:
841  return 0x5C; // LEFT HALF MEDIUM SHADE
842  case 0x2502:
843  return 0x5D; // BOX DRAWINGS LIGHT VERTICAL
844  case 0x03C0:
845  return 0x5E; // GREEK SMALL LETTER PI
846  case 0x25E5:
847  return 0x5F; // BLACK UPPER RIGHT TRIANGLE
848  case 0x00A0:
849  return 0x60; // NO-BREAK SPACE
850  case 0x258C:
851  return 0x61; // LEFT HALF BLOCK
852  case 0x2584:
853  return 0x62; // LOWER HALF BLOCK
854  case 0x2594:
855  return 0x63; // UPPER ONE EIGHTH BLOCK
856  case 0x2581:
857  return 0x64; // LOWER ONE EIGHTH BLOCK
858  case 0x258F:
859  return 0x65; // LEFT ONE EIGHTH BLOCK
860  case 0x2592:
861  return 0x66; // MEDIUM SHADE
862  case 0x2595:
863  return 0x67; // RIGHT ONE EIGHTH BLOCK
864  case 0x1FB8F:
865  return 0x68; // LOWER HALF MEDIUM SHADE
866  case 0x25E4:
867  return 0x69; // BLACK UPPER LEFT TRIANGLE
868  case 0x1FB87:
869  return 0x6A; // RIGHT ONE QUARTER BLOCK
870  case 0x251C:
871  return 0x6B; // BOX DRAWINGS LIGHT VERTICAL AND RIGHT
872  case 0x2597:
873  return 0x6C; // QUADRANT LOWER RIGHT
874  case 0x2514:
875  return 0x6D; // BOX DRAWINGS LIGHT UP AND RIGHT
876  case 0x2510:
877  return 0x6E; // BOX DRAWINGS LIGHT DOWN AND LEFT
878  case 0x2582:
879  return 0x6F; // LOWER ONE QUARTER BLOCK
880  case 0x250C:
881  return 0x70; // BOX DRAWINGS LIGHT DOWN AND RIGHT
882  case 0x2534:
883  return 0x71; // BOX DRAWINGS LIGHT UP AND HORIZONTAL
884  case 0x252C:
885  return 0x72; // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
886  case 0x2524:
887  return 0x73; // BOX DRAWINGS LIGHT VERTICAL AND LEFT
888  case 0x258E:
889  return 0x74; // LEFT ONE QUARTER BLOCK
890  case 0x258D:
891  return 0x75; // LEFT THREE EIGHTHS BLOCK
892  case 0x1FB88:
893  return 0x76; // RIGHT THREE EIGHTHS BLOCK
894  case 0x1FB82:
895  return 0x77; // UPPER ONE QUARTER BLOCK
896  case 0x1FB83:
897  return 0x78; // UPPER THREE EIGHTHS BLOCK
898  case 0x2583:
899  return 0x79; // LOWER THREE EIGHTHS BLOCK
900  case 0x1FB7F:
901  return 0x7A; // RIGHT AND LOWER ONE EIGHTH BLOCK
902  case 0x2596:
903  return 0x7B; // QUADRANT LOWER LEFT
904  case 0x259D:
905  return 0x7C; // QUADRANT UPPER RIGHT
906  case 0x2518:
907  return 0x7D; // BOX DRAWINGS LIGHT UP AND LEFT
908  case 0x2598:
909  return 0x7E; // QUADRANT UPPER LEFT
910  case 0x259A:
911  return 0x7F; // QUADRANT UPPER LEFT AND LOWER RIGHT
912  case 0x25D8:
913  return 0xD1; // INVERSE BULLET
914  case 0x25D9:
915  return 0xD7; // INVERSE WHITE CIRCLE
916  case 0x1FB94:
917  return 0xDC; // LEFT HALF INVERSE MEDIUM SHADE AND RIGHT HALF BLOCK
918  case 0x25E3:
919  return 0xDF; // BLACK LOWER LEFT TRIANGLE
920  case 0x2588:
921  return 0xE0; // FULL BLOCK
922  case 0x2590:
923  return 0xE1; // RIGHT HALF BLOCK
924  case 0x2580:
925  return 0xE2; // UPPER HALF BLOCK
926  case 0x2587:
927  return 0xE3; // LOWER SEVEN EIGHTHS BLOCK
928  case 0x1FB86:
929  return 0xE4; // UPPER SEVEN EIGHTHS BLOCK
930  case 0x1FB8B:
931  return 0xE5; // RIGHT SEVEN EIGHTHS BLOCK
932  case 0x1FB90:
933  return 0xE6; // INVERSE MEDIUM SHADE
934  case 0x2589:
935  return 0xE7; // LEFT SEVEN EIGHTHS BLOCK
936  case 0x1FB91:
937  return 0xE8; // UPPER HALF BLOCK AND LOWER HALF INVERSE MEDIUM SHADE
938  case 0x25E2:
939  return 0xE9; // BLACK LOWER RIGHT TRIANGLE
940  case 0x258A:
941  return 0xEA; // LEFT THREE QUARTERS BLOCK
942  case 0x259B:
943  return 0xEC; // QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER LEFT
944  case 0x1FB85:
945  return 0xEF; // UPPER THREE QUARTERS BLOCK
946  case 0x1FB8A:
947  return 0xF4; // RIGHT THREE QUARTERS BLOCK
948  case 0x1FB89:
949  return 0xF5; // RIGHT FIVE EIGHTHS BLOCK
950  case 0x258B:
951  return 0xF6; // LEFT FIVE EIGHTHS BLOCK
952  case 0x2586:
953  return 0xF7; // LOWER THREE QUARTERS BLOCK
954  case 0x2585:
955  return 0xF8; // LOWER FIVE EIGHTHS BLOCK
956  case 0x1FB84:
957  return 0xF9; // UPPER FIVE EIGHTHS BLOCK
958  case 0x259C:
959  return 0xFB; // QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER RIGHT
960  case 0x2599:
961  return 0xFC; // QUADRANT UPPER LEFT AND LOWER LEFT AND LOWER RIGHT
962  case 0x259F:
963  return 0xFE; // QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT
964  case 0x259E:
965  return 0xFF; // QUADRANT UPPER RIGHT AND LOWER LEFT
966  }
967  }
968 };
969 
970 template <size_t N> struct UnshiftedReverseVideoString {
971  char Str[N]{};
972 
973  constexpr UnshiftedReverseVideoString(char const (&Src)[N]) {
974  for (size_t I = 0; I < N; ++I) {
975  if (Src[I] >= 0x80)
976  throw "use U prefix for unicode string literals";
977  Str[I] = TranslateUnicode(Src[I]);
978  }
979  }
980 
981  constexpr UnshiftedReverseVideoString(char16_t const (&Src)[N]) {
982  for (size_t I = 0; I < N; ++I) {
983  if (Src[I] >= 0xD800 && Src[I] <= 0xDFFF)
984  throw "use U prefix for unicode string literals";
985  Str[I] = TranslateUnicode(Src[I]);
986  }
987  }
988 
989  constexpr UnshiftedReverseVideoString(char32_t const (&Src)[N]) {
990  for (size_t I = 0; I < N; ++I)
991  Str[I] = TranslateUnicode(Src[I]);
992  }
993 
994  constexpr char TranslateUnicode(char32_t C) {
995  switch (C) {
996  default:
997  throw "Unsupported";
998 
999  // Preserve NUL
1000  case 0x0000:
1001  return 0x00;
1002 
1003  // Name: Map from Commodore VIC-20 (video) primary character set to
1004  // Unicode
1005 
1006  // Date: 2018 April 20
1007 
1008  // Author: Rebecca Bettencourt <support@kreativekorp.com>
1009 
1010  case 0x0040:
1011  return 0x80; // COMMERCIAL AT, reverse video
1012  case 0x0041:
1013  return 0x81; // LATIN CAPITAL LETTER A, reverse video
1014  case 0x0042:
1015  return 0x82; // LATIN CAPITAL LETTER B, reverse video
1016  case 0x0043:
1017  return 0x83; // LATIN CAPITAL LETTER C, reverse video
1018  case 0x0044:
1019  return 0x84; // LATIN CAPITAL LETTER D, reverse video
1020  case 0x0045:
1021  return 0x85; // LATIN CAPITAL LETTER E, reverse video
1022  case 0x0046:
1023  return 0x86; // LATIN CAPITAL LETTER F, reverse video
1024  case 0x0047:
1025  return 0x87; // LATIN CAPITAL LETTER G, reverse video
1026  case 0x0048:
1027  return 0x88; // LATIN CAPITAL LETTER H, reverse video
1028  case 0x0049:
1029  return 0x89; // LATIN CAPITAL LETTER I, reverse video
1030  case 0x004A:
1031  return 0x8A; // LATIN CAPITAL LETTER J, reverse video
1032  case 0x004B:
1033  return 0x8B; // LATIN CAPITAL LETTER K, reverse video
1034  case 0x004C:
1035  return 0x8C; // LATIN CAPITAL LETTER L, reverse video
1036  case 0x004D:
1037  return 0x8D; // LATIN CAPITAL LETTER M, reverse video
1038  case 0x004E:
1039  return 0x8E; // LATIN CAPITAL LETTER N, reverse video
1040  case 0x004F:
1041  return 0x8F; // LATIN CAPITAL LETTER O, reverse video
1042  case 0x0050:
1043  return 0x90; // LATIN CAPITAL LETTER P, reverse video
1044  case 0x0051:
1045  return 0x91; // LATIN CAPITAL LETTER Q, reverse video
1046  case 0x0052:
1047  return 0x92; // LATIN CAPITAL LETTER R, reverse video
1048  case 0x0053:
1049  return 0x93; // LATIN CAPITAL LETTER S, reverse video
1050  case 0x0054:
1051  return 0x94; // LATIN CAPITAL LETTER T, reverse video
1052  case 0x0055:
1053  return 0x95; // LATIN CAPITAL LETTER U, reverse video
1054  case 0x0056:
1055  return 0x96; // LATIN CAPITAL LETTER V, reverse video
1056  case 0x0057:
1057  return 0x97; // LATIN CAPITAL LETTER W, reverse video
1058  case 0x0058:
1059  return 0x98; // LATIN CAPITAL LETTER X, reverse video
1060  case 0x0059:
1061  return 0x99; // LATIN CAPITAL LETTER Y, reverse video
1062  case 0x005A:
1063  return 0x9A; // LATIN CAPITAL LETTER Z, reverse video
1064  case 0x005B:
1065  return 0x9B; // LEFT SQUARE BRACKET, reverse video
1066  case 0x00A3:
1067  return 0x9C; // POUND SIGN, reverse video
1068  case 0x005D:
1069  return 0x9D; // RIGHT SQUARE BRACKET, reverse video
1070  case 0x2191:
1071  return 0x9E; // UPWARDS ARROW, reverse video
1072  case 0x2190:
1073  return 0x9F; // LEFTWARDS ARROW, reverse video
1074  case 0x0020:
1075  return 0xA0; // SPACE, reverse video
1076  case 0x0021:
1077  return 0xA1; // EXCLAMATION MARK, reverse video
1078  case 0x0022:
1079  return 0xA2; // QUOTATION MARK, reverse video
1080  case 0x0023:
1081  return 0xA3; // NUMBER SIGN, reverse video
1082  case 0x0024:
1083  return 0xA4; // DOLLAR SIGN, reverse video
1084  case 0x0025:
1085  return 0xA5; // PERCENT SIGN, reverse video
1086  case 0x0026:
1087  return 0xA6; // AMPERSAND, reverse video
1088  case 0x0027:
1089  return 0xA7; // APOSTROPHE, reverse video
1090  case 0x0028:
1091  return 0xA8; // LEFT PARENTHESIS, reverse video
1092  case 0x0029:
1093  return 0xA9; // RIGHT PARENTHESIS, reverse video
1094  case 0x002A:
1095  return 0xAA; // ASTERISK, reverse video
1096  case 0x002B:
1097  return 0xAB; // PLUS SIGN, reverse video
1098  case 0x002C:
1099  return 0xAC; // COMMA, reverse video
1100  case 0x002D:
1101  return 0xAD; // HYPHEN-MINUS, reverse video
1102  case 0x002E:
1103  return 0xAE; // FULL STOP, reverse video
1104  case 0x002F:
1105  return 0xAF; // SOLIDUS, reverse video
1106  case 0x0030:
1107  return 0xB0; // DIGIT ZERO, reverse video
1108  case 0x0031:
1109  return 0xB1; // DIGIT ONE, reverse video
1110  case 0x0032:
1111  return 0xB2; // DIGIT TWO, reverse video
1112  case 0x0033:
1113  return 0xB3; // DIGIT THREE, reverse video
1114  case 0x0034:
1115  return 0xB4; // DIGIT FOUR, reverse video
1116  case 0x0035:
1117  return 0xB5; // DIGIT FIVE, reverse video
1118  case 0x0036:
1119  return 0xB6; // DIGIT SIX, reverse video
1120  case 0x0037:
1121  return 0xB7; // DIGIT SEVEN, reverse video
1122  case 0x0038:
1123  return 0xB8; // DIGIT EIGHT, reverse video
1124  case 0x0039:
1125  return 0xB9; // DIGIT NINE, reverse video
1126  case 0x003A:
1127  return 0xBA; // COLON, reverse video
1128  case 0x003B:
1129  return 0xBB; // SEMICOLON, reverse video
1130  case 0x003C:
1131  return 0xBC; // LESS-THAN SIGN, reverse video
1132  case 0x003D:
1133  return 0xBD; // EQUALS SIGN, reverse video
1134  case 0x003E:
1135  return 0xBE; // GREATER-THAN SIGN, reverse video
1136  case 0x003F:
1137  return 0xBF; // QUESTION MARK, reverse video
1138  case 0x2500:
1139  return 0xC0; // BOX DRAWINGS LIGHT HORIZONTAL, reverse video
1140  case 0x2660:
1141  return 0xC1; // BLACK SPADE SUIT, reverse video
1142  case 0x1FB72:
1143  return 0xC2; // VERTICAL ONE EIGHTH BLOCK-4, reverse video
1144  case 0x1FB78:
1145  return 0xC3; // HORIZONTAL ONE EIGHTH BLOCK-4, reverse video
1146  case 0x1FB77:
1147  return 0xC4; // HORIZONTAL ONE EIGHTH BLOCK-3, reverse video
1148  case 0x1FB76:
1149  return 0xC5; // HORIZONTAL ONE EIGHTH BLOCK-2, reverse video
1150  case 0x1FB7A:
1151  return 0xC6; // HORIZONTAL ONE EIGHTH BLOCK-6, reverse video
1152  case 0x1FB71:
1153  return 0xC7; // VERTICAL ONE EIGHTH BLOCK-3, reverse video
1154  case 0x1FB74:
1155  return 0xC8; // VERTICAL ONE EIGHTH BLOCK-6, reverse video
1156  case 0x256E:
1157  return 0xC9; // BOX DRAWINGS LIGHT ARC DOWN AND LEFT, reverse video
1158  case 0x2570:
1159  return 0xCA; // BOX DRAWINGS LIGHT ARC UP AND RIGHT, reverse video
1160  case 0x256F:
1161  return 0xCB; // BOX DRAWINGS LIGHT ARC UP AND LEFT, reverse video
1162  case 0x1FB7C:
1163  return 0xCC; // LEFT AND LOWER ONE EIGHTH BLOCK, reverse video
1164  case 0x2572:
1165  return 0xCD; // BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT, reverse video
1166  case 0x2571:
1167  return 0xCE; // BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT, reverse video
1168  case 0x1FB7D:
1169  return 0xCF; // LEFT AND UPPER ONE EIGHTH BLOCK, reverse video
1170  case 0x1FB7E:
1171  return 0xD0; // RIGHT AND UPPER ONE EIGHTH BLOCK, reverse video
1172  case 0x1FB7B:
1173  return 0xD2; // HORIZONTAL ONE EIGHTH BLOCK-7, reverse video
1174  case 0x2665:
1175  return 0xD3; // BLACK HEART SUIT, reverse video
1176  case 0x1FB70:
1177  return 0xD4; // VERTICAL ONE EIGHTH BLOCK-2, reverse video
1178  case 0x256D:
1179  return 0xD5; // BOX DRAWINGS LIGHT ARC DOWN AND RIGHT, reverse video
1180  case 0x2573:
1181  return 0xD6; // BOX DRAWINGS LIGHT DIAGONAL CROSS, reverse video
1182  case 0x2663:
1183  return 0xD8; // BLACK CLUB SUIT, reverse video
1184  case 0x1FB75:
1185  return 0xD9; // VERTICAL ONE EIGHTH BLOCK-7, reverse video
1186  case 0x2666:
1187  return 0xDA; // BLACK DIAMOND SUIT, reverse video
1188  case 0x253C:
1189  return 0xDB; // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL, reverse video
1190  case 0x2502:
1191  return 0xDD; // BOX DRAWINGS LIGHT VERTICAL, reverse video
1192  case 0x03C0:
1193  return 0xDE; // GREEK SMALL LETTER PI, reverse video
1194  case 0x251C:
1195  return 0xEB; // BOX DRAWINGS LIGHT VERTICAL AND RIGHT, reverse video
1196  case 0x2514:
1197  return 0xED; // BOX DRAWINGS LIGHT UP AND RIGHT, reverse video
1198  case 0x2510:
1199  return 0xEE; // BOX DRAWINGS LIGHT DOWN AND LEFT, reverse video
1200  case 0x250C:
1201  return 0xF0; // BOX DRAWINGS LIGHT DOWN AND RIGHT, reverse video
1202  case 0x2534:
1203  return 0xF1; // BOX DRAWINGS LIGHT UP AND HORIZONTAL, reverse video
1204  case 0x252C:
1205  return 0xF2; // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL, reverse video
1206  case 0x2524:
1207  return 0xF3; // BOX DRAWINGS LIGHT VERTICAL AND LEFT, reverse video
1208  case 0x1FB7F:
1209  return 0xFA; // RIGHT AND LOWER ONE EIGHTH BLOCK, reverse video
1210  case 0x2518:
1211  return 0xFD; // BOX DRAWINGS LIGHT UP AND LEFT, reverse video
1212  }
1213  }
1214 };
1215 
1216 template <size_t N> struct ShiftedVideoString {
1217  char Str[N]{};
1218 
1219  constexpr ShiftedVideoString(char const (&Src)[N]) {
1220  for (size_t I = 0; I < N; ++I) {
1221  if (Src[I] >= 0x80)
1222  throw "use U prefix for unicode string literals";
1223  Str[I] = TranslateUnicode(Src[I]);
1224  }
1225  }
1226 
1227  constexpr ShiftedVideoString(char16_t const (&Src)[N]) {
1228  for (size_t I = 0; I < N; ++I) {
1229  if (Src[I] >= 0xD800 && Src[I] <= 0xDFFF)
1230  throw "use U prefix for unicode string literals";
1231  Str[I] = TranslateUnicode(Src[I]);
1232  }
1233  }
1234 
1235  constexpr ShiftedVideoString(char32_t const (&Src)[N]) {
1236  for (size_t I = 0; I < N; ++I)
1237  Str[I] = TranslateUnicode(Src[I]);
1238  }
1239 
1240  constexpr char TranslateUnicode(char32_t C) {
1241  switch (C) {
1242  default:
1243  throw "Unsupported";
1244 
1245  // Preserve NUL
1246  case 0x0000:
1247  return 0x00;
1248 
1249  // Name: Map from Commodore VIC-20 (video) alternate character set to
1250  // Unicode
1251 
1252  // Date: 2018 October 11
1253 
1254  // Author: Rebecca Bettencourt <support@kreativekorp.com>
1255 
1256  case 0x0040:
1257  return 0x00; // COMMERCIAL AT
1258  case 0x0061:
1259  return 0x01; // LATIN SMALL LETTER A
1260  case 0x0062:
1261  return 0x02; // LATIN SMALL LETTER B
1262  case 0x0063:
1263  return 0x03; // LATIN SMALL LETTER C
1264  case 0x0064:
1265  return 0x04; // LATIN SMALL LETTER D
1266  case 0x0065:
1267  return 0x05; // LATIN SMALL LETTER E
1268  case 0x0066:
1269  return 0x06; // LATIN SMALL LETTER F
1270  case 0x0067:
1271  return 0x07; // LATIN SMALL LETTER G
1272  case 0x0068:
1273  return 0x08; // LATIN SMALL LETTER H
1274  case 0x0069:
1275  return 0x09; // LATIN SMALL LETTER I
1276  case 0x006A:
1277  return 0x0A; // LATIN SMALL LETTER J
1278  case 0x006B:
1279  return 0x0B; // LATIN SMALL LETTER K
1280  case 0x006C:
1281  return 0x0C; // LATIN SMALL LETTER L
1282  case 0x006D:
1283  return 0x0D; // LATIN SMALL LETTER M
1284  case 0x006E:
1285  return 0x0E; // LATIN SMALL LETTER N
1286  case 0x006F:
1287  return 0x0F; // LATIN SMALL LETTER O
1288  case 0x0070:
1289  return 0x10; // LATIN SMALL LETTER P
1290  case 0x0071:
1291  return 0x11; // LATIN SMALL LETTER Q
1292  case 0x0072:
1293  return 0x12; // LATIN SMALL LETTER R
1294  case 0x0073:
1295  return 0x13; // LATIN SMALL LETTER S
1296  case 0x0074:
1297  return 0x14; // LATIN SMALL LETTER T
1298  case 0x0075:
1299  return 0x15; // LATIN SMALL LETTER U
1300  case 0x0076:
1301  return 0x16; // LATIN SMALL LETTER V
1302  case 0x0077:
1303  return 0x17; // LATIN SMALL LETTER W
1304  case 0x0078:
1305  return 0x18; // LATIN SMALL LETTER X
1306  case 0x0079:
1307  return 0x19; // LATIN SMALL LETTER Y
1308  case 0x007A:
1309  return 0x1A; // LATIN SMALL LETTER Z
1310  case 0x005B:
1311  return 0x1B; // LEFT SQUARE BRACKET
1312  case 0x00A3:
1313  return 0x1C; // POUND SIGN
1314  case 0x005D:
1315  return 0x1D; // RIGHT SQUARE BRACKET
1316  case 0x2191:
1317  return 0x1E; // UPWARDS ARROW
1318  case 0x2190:
1319  return 0x1F; // LEFTWARDS ARROW
1320  case 0x0020:
1321  return 0x20; // SPACE
1322  case 0x0021:
1323  return 0x21; // EXCLAMATION MARK
1324  case 0x0022:
1325  return 0x22; // QUOTATION MARK
1326  case 0x0023:
1327  return 0x23; // NUMBER SIGN
1328  case 0x0024:
1329  return 0x24; // DOLLAR SIGN
1330  case 0x0025:
1331  return 0x25; // PERCENT SIGN
1332  case 0x0026:
1333  return 0x26; // AMPERSAND
1334  case 0x0027:
1335  return 0x27; // APOSTROPHE
1336  case 0x0028:
1337  return 0x28; // LEFT PARENTHESIS
1338  case 0x0029:
1339  return 0x29; // RIGHT PARENTHESIS
1340  case 0x002A:
1341  return 0x2A; // ASTERISK
1342  case 0x002B:
1343  return 0x2B; // PLUS SIGN
1344  case 0x002C:
1345  return 0x2C; // COMMA
1346  case 0x002D:
1347  return 0x2D; // HYPHEN-MINUS
1348  case 0x002E:
1349  return 0x2E; // FULL STOP
1350  case 0x002F:
1351  return 0x2F; // SOLIDUS
1352  case 0x0030:
1353  return 0x30; // DIGIT ZERO
1354  case 0x0031:
1355  return 0x31; // DIGIT ONE
1356  case 0x0032:
1357  return 0x32; // DIGIT TWO
1358  case 0x0033:
1359  return 0x33; // DIGIT THREE
1360  case 0x0034:
1361  return 0x34; // DIGIT FOUR
1362  case 0x0035:
1363  return 0x35; // DIGIT FIVE
1364  case 0x0036:
1365  return 0x36; // DIGIT SIX
1366  case 0x0037:
1367  return 0x37; // DIGIT SEVEN
1368  case 0x0038:
1369  return 0x38; // DIGIT EIGHT
1370  case 0x0039:
1371  return 0x39; // DIGIT NINE
1372  case 0x003A:
1373  return 0x3A; // COLON
1374  case 0x003B:
1375  return 0x3B; // SEMICOLON
1376  case 0x003C:
1377  return 0x3C; // LESS-THAN SIGN
1378  case 0x003D:
1379  return 0x3D; // EQUALS SIGN
1380  case 0x003E:
1381  return 0x3E; // GREATER-THAN SIGN
1382  case 0x003F:
1383  return 0x3F; // QUESTION MARK
1384  case 0x2500:
1385  return 0x40; // BOX DRAWINGS LIGHT HORIZONTAL
1386  case 0x0041:
1387  return 0x41; // LATIN CAPITAL LETTER A
1388  case 0x0042:
1389  return 0x42; // LATIN CAPITAL LETTER B
1390  case 0x0043:
1391  return 0x43; // LATIN CAPITAL LETTER C
1392  case 0x0044:
1393  return 0x44; // LATIN CAPITAL LETTER D
1394  case 0x0045:
1395  return 0x45; // LATIN CAPITAL LETTER E
1396  case 0x0046:
1397  return 0x46; // LATIN CAPITAL LETTER F
1398  case 0x0047:
1399  return 0x47; // LATIN CAPITAL LETTER G
1400  case 0x0048:
1401  return 0x48; // LATIN CAPITAL LETTER H
1402  case 0x0049:
1403  return 0x49; // LATIN CAPITAL LETTER I
1404  case 0x004A:
1405  return 0x4A; // LATIN CAPITAL LETTER J
1406  case 0x004B:
1407  return 0x4B; // LATIN CAPITAL LETTER K
1408  case 0x004C:
1409  return 0x4C; // LATIN CAPITAL LETTER L
1410  case 0x004D:
1411  return 0x4D; // LATIN CAPITAL LETTER M
1412  case 0x004E:
1413  return 0x4E; // LATIN CAPITAL LETTER N
1414  case 0x004F:
1415  return 0x4F; // LATIN CAPITAL LETTER O
1416  case 0x0050:
1417  return 0x50; // LATIN CAPITAL LETTER P
1418  case 0x0051:
1419  return 0x51; // LATIN CAPITAL LETTER Q
1420  case 0x0052:
1421  return 0x52; // LATIN CAPITAL LETTER R
1422  case 0x0053:
1423  return 0x53; // LATIN CAPITAL LETTER S
1424  case 0x0054:
1425  return 0x54; // LATIN CAPITAL LETTER T
1426  case 0x0055:
1427  return 0x55; // LATIN CAPITAL LETTER U
1428  case 0x0056:
1429  return 0x56; // LATIN CAPITAL LETTER V
1430  case 0x0057:
1431  return 0x57; // LATIN CAPITAL LETTER W
1432  case 0x0058:
1433  return 0x58; // LATIN CAPITAL LETTER X
1434  case 0x0059:
1435  return 0x59; // LATIN CAPITAL LETTER Y
1436  case 0x005A:
1437  return 0x5A; // LATIN CAPITAL LETTER Z
1438  case 0x253C:
1439  return 0x5B; // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
1440  case 0x1FB8C:
1441  return 0x5C; // LEFT HALF MEDIUM SHADE
1442  case 0x2502:
1443  return 0x5D; // BOX DRAWINGS LIGHT VERTICAL
1444  case 0x1FB95:
1445  return 0x5E; // CHECKER BOARD FILL
1446  case 0x1FB98:
1447  return 0x5F; // UPPER LEFT TO LOWER RIGHT FILL
1448  case 0x00A0:
1449  return 0x60; // NO-BREAK SPACE
1450  case 0x258C:
1451  return 0x61; // LEFT HALF BLOCK
1452  case 0x2584:
1453  return 0x62; // LOWER HALF BLOCK
1454  case 0x2594:
1455  return 0x63; // UPPER ONE EIGHTH BLOCK
1456  case 0x2581:
1457  return 0x64; // LOWER ONE EIGHTH BLOCK
1458  case 0x258F:
1459  return 0x65; // LEFT ONE EIGHTH BLOCK
1460  case 0x2592:
1461  return 0x66; // MEDIUM SHADE
1462  case 0x2595:
1463  return 0x67; // RIGHT ONE EIGHTH BLOCK
1464  case 0x1FB8F:
1465  return 0x68; // LOWER HALF MEDIUM SHADE
1466  case 0x1FB99:
1467  return 0x69; // UPPER RIGHT TO LOWER LEFT FILL
1468  case 0x1FB87:
1469  return 0x6A; // RIGHT ONE QUARTER BLOCK
1470  case 0x251C:
1471  return 0x6B; // BOX DRAWINGS LIGHT VERTICAL AND RIGHT
1472  case 0x2597:
1473  return 0x6C; // QUADRANT LOWER RIGHT
1474  case 0x2514:
1475  return 0x6D; // BOX DRAWINGS LIGHT UP AND RIGHT
1476  case 0x2510:
1477  return 0x6E; // BOX DRAWINGS LIGHT DOWN AND LEFT
1478  case 0x2582:
1479  return 0x6F; // LOWER ONE QUARTER BLOCK
1480  case 0x250C:
1481  return 0x70; // BOX DRAWINGS LIGHT DOWN AND RIGHT
1482  case 0x2534:
1483  return 0x71; // BOX DRAWINGS LIGHT UP AND HORIZONTAL
1484  case 0x252C:
1485  return 0x72; // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
1486  case 0x2524:
1487  return 0x73; // BOX DRAWINGS LIGHT VERTICAL AND LEFT
1488  case 0x258E:
1489  return 0x74; // LEFT ONE QUARTER BLOCK
1490  case 0x258D:
1491  return 0x75; // LEFT THREE EIGHTHS BLOCK
1492  case 0x1FB88:
1493  return 0x76; // RIGHT THREE EIGHTHS BLOCK
1494  case 0x1FB82:
1495  return 0x77; // UPPER ONE QUARTER BLOCK
1496  case 0x1FB83:
1497  return 0x78; // UPPER THREE EIGHTHS BLOCK
1498  case 0x2583:
1499  return 0x79; // LOWER THREE EIGHTHS BLOCK
1500  case 0x2713:
1501  return 0x7A; // CHECK MARK
1502  case 0x2596:
1503  return 0x7B; // QUADRANT LOWER LEFT
1504  case 0x259D:
1505  return 0x7C; // QUADRANT UPPER RIGHT
1506  case 0x2518:
1507  return 0x7D; // BOX DRAWINGS LIGHT UP AND LEFT
1508  case 0x2598:
1509  return 0x7E; // QUADRANT UPPER LEFT
1510  case 0x259A:
1511  return 0x7F; // QUADRANT UPPER LEFT AND LOWER RIGHT
1512  case 0x1FB94:
1513  return 0xDC; // LEFT HALF INVERSE MEDIUM SHADE AND RIGHT HALF BLOCK
1514  case 0x1FB96:
1515  return 0xDE; // INVERSE CHECKER BOARD FILL
1516  case 0x2588:
1517  return 0xE0; // FULL BLOCK
1518  case 0x2590:
1519  return 0xE1; // RIGHT HALF BLOCK
1520  case 0x2580:
1521  return 0xE2; // UPPER HALF BLOCK
1522  case 0x2587:
1523  return 0xE3; // LOWER SEVEN EIGHTHS BLOCK
1524  case 0x1FB86:
1525  return 0xE4; // UPPER SEVEN EIGHTHS BLOCK
1526  case 0x1FB8B:
1527  return 0xE5; // RIGHT SEVEN EIGHTHS BLOCK
1528  case 0x1FB90:
1529  return 0xE6; // INVERSE MEDIUM SHADE
1530  case 0x2589:
1531  return 0xE7; // LEFT SEVEN EIGHTHS BLOCK
1532  case 0x1FB91:
1533  return 0xE8; // UPPER HALF BLOCK AND LOWER HALF INVERSE MEDIUM SHADE
1534  case 0x258A:
1535  return 0xEA; // LEFT THREE QUARTERS BLOCK
1536  case 0x259B:
1537  return 0xEC; // QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER LEFT
1538  case 0x1FB85:
1539  return 0xEF; // UPPER THREE QUARTERS BLOCK
1540  case 0x1FB8A:
1541  return 0xF4; // RIGHT THREE QUARTERS BLOCK
1542  case 0x1FB89:
1543  return 0xF5; // RIGHT FIVE EIGHTHS BLOCK
1544  case 0x258B:
1545  return 0xF6; // LEFT FIVE EIGHTHS BLOCK
1546  case 0x2586:
1547  return 0xF7; // LOWER THREE QUARTERS BLOCK
1548  case 0x2585:
1549  return 0xF8; // LOWER FIVE EIGHTHS BLOCK
1550  case 0x1FB84:
1551  return 0xF9; // UPPER FIVE EIGHTHS BLOCK
1552  case 0x1FBB1:
1553  return 0xFA; // INVERSE CHECK MARK
1554  case 0x259C:
1555  return 0xFB; // QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER RIGHT
1556  case 0x2599:
1557  return 0xFC; // QUADRANT UPPER LEFT AND LOWER LEFT AND LOWER RIGHT
1558  case 0x259F:
1559  return 0xFE; // QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT
1560  case 0x259E:
1561  return 0xFF; // QUADRANT UPPER RIGHT AND LOWER LEFT
1562  }
1563  }
1564 };
1565 
1566 template <size_t N> struct ShiftedReverseVideoString {
1567  char Str[N]{};
1568 
1569  constexpr ShiftedReverseVideoString(char const (&Src)[N]) {
1570  for (size_t I = 0; I < N; ++I) {
1571  if (Src[I] >= 0x80)
1572  throw "use U prefix for unicode string literals";
1573  Str[I] = TranslateUnicode(Src[I]);
1574  }
1575  }
1576 
1577  constexpr ShiftedReverseVideoString(char16_t const (&Src)[N]) {
1578  for (size_t I = 0; I < N; ++I) {
1579  if (Src[I] >= 0xD800 && Src[I] <= 0xDFFF)
1580  throw "use U prefix for unicode string literals";
1581  Str[I] = TranslateUnicode(Src[I]);
1582  }
1583  }
1584 
1585  constexpr ShiftedReverseVideoString(char32_t const (&Src)[N]) {
1586  for (size_t I = 0; I < N; ++I)
1587  Str[I] = TranslateUnicode(Src[I]);
1588  }
1589 
1590  constexpr char TranslateUnicode(char32_t C) {
1591  switch (C) {
1592  default:
1593  throw "Unsupported";
1594 
1595  // Preserve NUL
1596  case 0x0000:
1597  return 0x00;
1598 
1599  // Name: Map from Commodore VIC-20 (video) alternate character set to
1600  // Unicode
1601 
1602  // Date: 2018 October 11
1603 
1604  // Author: Rebecca Bettencourt <support@kreativekorp.com>
1605 
1606  case 0x0040:
1607  return 0x80; // COMMERCIAL AT, reverse video
1608  case 0x0061:
1609  return 0x81; // LATIN SMALL LETTER A, reverse video
1610  case 0x0062:
1611  return 0x82; // LATIN SMALL LETTER B, reverse video
1612  case 0x0063:
1613  return 0x83; // LATIN SMALL LETTER C, reverse video
1614  case 0x0064:
1615  return 0x84; // LATIN SMALL LETTER D, reverse video
1616  case 0x0065:
1617  return 0x85; // LATIN SMALL LETTER E, reverse video
1618  case 0x0066:
1619  return 0x86; // LATIN SMALL LETTER F, reverse video
1620  case 0x0067:
1621  return 0x87; // LATIN SMALL LETTER G, reverse video
1622  case 0x0068:
1623  return 0x88; // LATIN SMALL LETTER H, reverse video
1624  case 0x0069:
1625  return 0x89; // LATIN SMALL LETTER I, reverse video
1626  case 0x006A:
1627  return 0x8A; // LATIN SMALL LETTER J, reverse video
1628  case 0x006B:
1629  return 0x8B; // LATIN SMALL LETTER K, reverse video
1630  case 0x006C:
1631  return 0x8C; // LATIN SMALL LETTER L, reverse video
1632  case 0x006D:
1633  return 0x8D; // LATIN SMALL LETTER M, reverse video
1634  case 0x006E:
1635  return 0x8E; // LATIN SMALL LETTER N, reverse video
1636  case 0x006F:
1637  return 0x8F; // LATIN SMALL LETTER O, reverse video
1638  case 0x0070:
1639  return 0x90; // LATIN SMALL LETTER P, reverse video
1640  case 0x0071:
1641  return 0x91; // LATIN SMALL LETTER Q, reverse video
1642  case 0x0072:
1643  return 0x92; // LATIN SMALL LETTER R, reverse video
1644  case 0x0073:
1645  return 0x93; // LATIN SMALL LETTER S, reverse video
1646  case 0x0074:
1647  return 0x94; // LATIN SMALL LETTER T, reverse video
1648  case 0x0075:
1649  return 0x95; // LATIN SMALL LETTER U, reverse video
1650  case 0x0076:
1651  return 0x96; // LATIN SMALL LETTER V, reverse video
1652  case 0x0077:
1653  return 0x97; // LATIN SMALL LETTER W, reverse video
1654  case 0x0078:
1655  return 0x98; // LATIN SMALL LETTER X, reverse video
1656  case 0x0079:
1657  return 0x99; // LATIN SMALL LETTER Y, reverse video
1658  case 0x007A:
1659  return 0x9A; // LATIN SMALL LETTER Z, reverse video
1660  case 0x005B:
1661  return 0x9B; // LEFT SQUARE BRACKET, reverse video
1662  case 0x00A3:
1663  return 0x9C; // POUND SIGN, reverse video
1664  case 0x005D:
1665  return 0x9D; // RIGHT SQUARE BRACKET, reverse video
1666  case 0x2191:
1667  return 0x9E; // UPWARDS ARROW, reverse video
1668  case 0x2190:
1669  return 0x9F; // LEFTWARDS ARROW, reverse video
1670  case 0x0020:
1671  return 0xA0; // SPACE, reverse video
1672  case 0x0021:
1673  return 0xA1; // EXCLAMATION MARK, reverse video
1674  case 0x0022:
1675  return 0xA2; // QUOTATION MARK, reverse video
1676  case 0x0023:
1677  return 0xA3; // NUMBER SIGN, reverse video
1678  case 0x0024:
1679  return 0xA4; // DOLLAR SIGN, reverse video
1680  case 0x0025:
1681  return 0xA5; // PERCENT SIGN, reverse video
1682  case 0x0026:
1683  return 0xA6; // AMPERSAND, reverse video
1684  case 0x0027:
1685  return 0xA7; // APOSTROPHE, reverse video
1686  case 0x0028:
1687  return 0xA8; // LEFT PARENTHESIS, reverse video
1688  case 0x0029:
1689  return 0xA9; // RIGHT PARENTHESIS, reverse video
1690  case 0x002A:
1691  return 0xAA; // ASTERISK, reverse video
1692  case 0x002B:
1693  return 0xAB; // PLUS SIGN, reverse video
1694  case 0x002C:
1695  return 0xAC; // COMMA, reverse video
1696  case 0x002D:
1697  return 0xAD; // HYPHEN-MINUS, reverse video
1698  case 0x002E:
1699  return 0xAE; // FULL STOP, reverse video
1700  case 0x002F:
1701  return 0xAF; // SOLIDUS, reverse video
1702  case 0x0030:
1703  return 0xB0; // DIGIT ZERO, reverse video
1704  case 0x0031:
1705  return 0xB1; // DIGIT ONE, reverse video
1706  case 0x0032:
1707  return 0xB2; // DIGIT TWO, reverse video
1708  case 0x0033:
1709  return 0xB3; // DIGIT THREE, reverse video
1710  case 0x0034:
1711  return 0xB4; // DIGIT FOUR, reverse video
1712  case 0x0035:
1713  return 0xB5; // DIGIT FIVE, reverse video
1714  case 0x0036:
1715  return 0xB6; // DIGIT SIX, reverse video
1716  case 0x0037:
1717  return 0xB7; // DIGIT SEVEN, reverse video
1718  case 0x0038:
1719  return 0xB8; // DIGIT EIGHT, reverse video
1720  case 0x0039:
1721  return 0xB9; // DIGIT NINE, reverse video
1722  case 0x003A:
1723  return 0xBA; // COLON, reverse video
1724  case 0x003B:
1725  return 0xBB; // SEMICOLON, reverse video
1726  case 0x003C:
1727  return 0xBC; // LESS-THAN SIGN, reverse video
1728  case 0x003D:
1729  return 0xBD; // EQUALS SIGN, reverse video
1730  case 0x003E:
1731  return 0xBE; // GREATER-THAN SIGN, reverse video
1732  case 0x003F:
1733  return 0xBF; // QUESTION MARK, reverse video
1734  case 0x2500:
1735  return 0xC0; // BOX DRAWINGS LIGHT HORIZONTAL, reverse video
1736  case 0x0041:
1737  return 0xC1; // LATIN CAPITAL LETTER A, reverse video
1738  case 0x0042:
1739  return 0xC2; // LATIN CAPITAL LETTER B, reverse video
1740  case 0x0043:
1741  return 0xC3; // LATIN CAPITAL LETTER C, reverse video
1742  case 0x0044:
1743  return 0xC4; // LATIN CAPITAL LETTER D, reverse video
1744  case 0x0045:
1745  return 0xC5; // LATIN CAPITAL LETTER E, reverse video
1746  case 0x0046:
1747  return 0xC6; // LATIN CAPITAL LETTER F, reverse video
1748  case 0x0047:
1749  return 0xC7; // LATIN CAPITAL LETTER G, reverse video
1750  case 0x0048:
1751  return 0xC8; // LATIN CAPITAL LETTER H, reverse video
1752  case 0x0049:
1753  return 0xC9; // LATIN CAPITAL LETTER I, reverse video
1754  case 0x004A:
1755  return 0xCA; // LATIN CAPITAL LETTER J, reverse video
1756  case 0x004B:
1757  return 0xCB; // LATIN CAPITAL LETTER K, reverse video
1758  case 0x004C:
1759  return 0xCC; // LATIN CAPITAL LETTER L, reverse video
1760  case 0x004D:
1761  return 0xCD; // LATIN CAPITAL LETTER M, reverse video
1762  case 0x004E:
1763  return 0xCE; // LATIN CAPITAL LETTER N, reverse video
1764  case 0x004F:
1765  return 0xCF; // LATIN CAPITAL LETTER O, reverse video
1766  case 0x0050:
1767  return 0xD0; // LATIN CAPITAL LETTER P, reverse video
1768  case 0x0051:
1769  return 0xD1; // LATIN CAPITAL LETTER Q, reverse video
1770  case 0x0052:
1771  return 0xD2; // LATIN CAPITAL LETTER R, reverse video
1772  case 0x0053:
1773  return 0xD3; // LATIN CAPITAL LETTER S, reverse video
1774  case 0x0054:
1775  return 0xD4; // LATIN CAPITAL LETTER T, reverse video
1776  case 0x0055:
1777  return 0xD5; // LATIN CAPITAL LETTER U, reverse video
1778  case 0x0056:
1779  return 0xD6; // LATIN CAPITAL LETTER V, reverse video
1780  case 0x0057:
1781  return 0xD7; // LATIN CAPITAL LETTER W, reverse video
1782  case 0x0058:
1783  return 0xD8; // LATIN CAPITAL LETTER X, reverse video
1784  case 0x0059:
1785  return 0xD9; // LATIN CAPITAL LETTER Y, reverse video
1786  case 0x005A:
1787  return 0xDA; // LATIN CAPITAL LETTER Z, reverse video
1788  case 0x253C:
1789  return 0xDB; // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL, reverse video
1790  case 0x2502:
1791  return 0xDD; // BOX DRAWINGS LIGHT VERTICAL, reverse video
1792  case 0x1FB98:
1793  return 0xDF; // UPPER LEFT TO LOWER RIGHT FILL, reverse video
1794  case 0x1FB99:
1795  return 0xE9; // UPPER RIGHT TO LOWER LEFT FILL, reverse video
1796  case 0x251C:
1797  return 0xEB; // BOX DRAWINGS LIGHT VERTICAL AND RIGHT, reverse video
1798  case 0x2514:
1799  return 0xED; // BOX DRAWINGS LIGHT UP AND RIGHT, reverse video
1800  case 0x2510:
1801  return 0xEE; // BOX DRAWINGS LIGHT DOWN AND LEFT, reverse video
1802  case 0x250C:
1803  return 0xF0; // BOX DRAWINGS LIGHT DOWN AND RIGHT, reverse video
1804  case 0x2534:
1805  return 0xF1; // BOX DRAWINGS LIGHT UP AND HORIZONTAL, reverse video
1806  case 0x252C:
1807  return 0xF2; // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL, reverse video
1808  case 0x2524:
1809  return 0xF3; // BOX DRAWINGS LIGHT VERTICAL AND LEFT, reverse video
1810  case 0x2518:
1811  return 0xFD; // BOX DRAWINGS LIGHT UP AND LEFT, reverse video
1812  }
1813  }
1814 };
1815 
1816 } // namespace charset_impl
1817 
1818 template <charset_impl::UnshiftedString S> constexpr auto operator""_u() {
1819  return S.Str;
1820 }
1821 template <charset_impl::ShiftedString S> constexpr auto operator""_s() {
1822  return S.Str;
1823 }
1824 
1825 template <charset_impl::UnshiftedVideoString S> constexpr auto operator""_uv() {
1826  return S.Str;
1827 }
1828 
1829 template <charset_impl::UnshiftedReverseVideoString S>
1830 constexpr auto operator""_urv() {
1831  return S.Str;
1832 }
1833 
1834 template <charset_impl::ShiftedVideoString S> constexpr auto operator""_sv() {
1835  return S.Str;
1836 }
1837 
1838 template <charset_impl::ShiftedReverseVideoString S>
1839 constexpr auto operator""_srv() {
1840  return S.Str;
1841 }
1842 
1843 #endif // not _CHARSET_H
1844 #endif // __cplusplus >= 202002L
cstddef