|
| 1 | +#include <cstdio> |
| 2 | +#include <cstdlib> |
| 3 | +#include <cwctype> |
| 4 | +#include "types.h" |
| 5 | + |
| 6 | + |
| 7 | +// http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/PC/CP850.TXT |
| 8 | +// Range 0x80-0xFF. |
| 9 | +static const wchar_t cp850Lut[128] = |
| 10 | +{ |
| 11 | + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, |
| 12 | + 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, |
| 13 | + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, |
| 14 | + 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, |
| 15 | + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, |
| 16 | + 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, |
| 17 | + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, |
| 18 | + 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, |
| 19 | + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, |
| 20 | + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, |
| 21 | + 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, |
| 22 | + 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, |
| 23 | + 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, |
| 24 | + 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0xACCE, |
| 25 | + 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, |
| 26 | + 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 |
| 27 | +}; |
| 28 | + |
| 29 | + |
| 30 | + |
| 31 | +// Make sure dosStr is big enough! |
| 32 | +static bool wchar2cp850(const wchar_t *wStr, char *dosStr) |
| 33 | +{ |
| 34 | + while(*wStr != L'\0') |
| 35 | + { |
| 36 | + const wchar_t wc = *wStr++; |
| 37 | + if(wc > 0 && wc < 128) |
| 38 | + { |
| 39 | + *dosStr++ = wc; |
| 40 | + continue; |
| 41 | + } |
| 42 | + |
| 43 | + unsigned i; |
| 44 | + for(i = 0; i < 128; i++) |
| 45 | + { |
| 46 | + if(wc == cp850Lut[i]) |
| 47 | + { |
| 48 | + *dosStr++ = 0x80 | i; |
| 49 | + break; |
| 50 | + } |
| 51 | + } |
| 52 | + |
| 53 | + if(i == 128) |
| 54 | + { |
| 55 | + fprintf(stderr, "Error: Can't convert wide character 0x%08" PRIX32 " to CP850.\n", wc); |
| 56 | + return false; |
| 57 | + } |
| 58 | + } |
| 59 | + |
| 60 | + *dosStr = '\0'; |
| 61 | + |
| 62 | + return true; |
| 63 | +} |
| 64 | + |
| 65 | +size_t convertCheckLabel(const char *const label, char *dosLabel) |
| 66 | +{ |
| 67 | + // Reserve one more char so we can detect if the label is too long. |
| 68 | + wchar_t wLabel[13]; |
| 69 | + wLabel[12] = L'\0'; |
| 70 | + const size_t wideChars = mbstowcs(wLabel, label, 12); |
| 71 | + if(wideChars == (size_t)-1) |
| 72 | + { |
| 73 | + fputs("Failed to convert label to wide characters.\n", stderr); |
| 74 | + return 0; |
| 75 | + } |
| 76 | + |
| 77 | + if(wideChars > 11) |
| 78 | + { |
| 79 | + fputs("Error: Label is too long.\n", stderr); |
| 80 | + return 0; |
| 81 | + } |
| 82 | + |
| 83 | + for(unsigned i = 0; wLabel[i] != L'\0'; i++) |
| 84 | + { |
| 85 | + if(iswlower(wLabel[i]) != 0) |
| 86 | + { |
| 87 | + fputs("Warning: Label contains lowercase characters.\n", stderr); |
| 88 | + break; |
| 89 | + } |
| 90 | + } |
| 91 | + |
| 92 | + if(!wchar2cp850(wLabel, dosLabel)) return 0; |
| 93 | + |
| 94 | + if(*dosLabel == ' ') |
| 95 | + { |
| 96 | + fputs("Error: First character in label must nut be a space.\n", stderr); |
| 97 | + return 0; |
| 98 | + } |
| 99 | + |
| 100 | + while(*dosLabel != '\0') |
| 101 | + { |
| 102 | + const unsigned char c = *dosLabel++; |
| 103 | + if(c < 0x20 || c == 0x22 || |
| 104 | + (c >= 0x2A && c <= 0x2C) || |
| 105 | + c == 0x2E || c == 0x2F || |
| 106 | + (c >= 0x3A && c <= 0x3F) || |
| 107 | + (c >= 0x5B && c <= 0x5D) || |
| 108 | + c == 0x7C) |
| 109 | + { |
| 110 | + fputs("Error: Label contains invalid characters.\n", stderr); |
| 111 | + return 0; |
| 112 | + } |
| 113 | + } |
| 114 | + |
| 115 | + return wideChars; |
| 116 | +} |
0 commit comments