To decide whether letters are upper or lower case, and convert between the two.


§1. Char Is Of Case. The following decides whether a character c belongs to case case, where 0 means lower case and 1 means upper. c is interpreted according to the character casing chart in "UnicodeData.i6t", which means, it will be ZSCII for the Z-machine and Unicode for Glulx.

[ CharIsOfCase c case
    i tab min max len par;
    if (c<'A') rfalse;
    if (case == 0) {
        if ((c >= 'a') && (c <= 'z')) rtrue;
        tab = CharCasingChart0;
    } else {
        if ((c >= 'A') && (c <= 'Z')) rtrue;
        tab = CharCasingChart1;
    }
    if (c<128) rfalse;
    while (tab-->i) {
        min = tab-->i; i++;
        len = tab-->i; i++;
        i++;
        par = 0;
        if (len<0) { par = 1; len = -len; }
        if (c < min) rfalse;
        if (c < min+len) {
            if (par) { if ((c-min) % 2 == 0) rtrue; }
            else { rtrue; }
        }
    }
    rfalse;
];

§2. Char To Case. And the following converts character c to the desired case, or returns it unchanged if it is not a letter with variant casings.

[ CharToCase c case
    i tab min max len par del f;
    if (c<'A') return c;
    if (case == 1) {
        if ((c >= 'a') && (c <= 'z')) return c-32;
        tab = CharCasingChart0;
    } else {
        if ((c >= 'A') && (c <= 'Z')) return c+32;
        tab = CharCasingChart1;
    }
    if (c<128) return c;
    while (tab-->i) {
        min = tab-->i; i++;
        len = tab-->i; i++;
        del = tab-->i; i++;
        par = 0;
        if (len<0) { par = 1; len = -len; }
        if (c < min) return c;
        if (c < min+len) {
            f = false;
            if (par) { if ((c-min) % 2 == 0) f = true; }
            else { f = true; }
            if (f) {
                if (del == UNIC_NCT) return c;
                return c+del;
            }
        }
    }
    return c;
];

§3. DigitToValue. This takes a ZSCII or Unicode character code and returns its value as a digit, or returns \(-1\) if it isn't a digit.

[ DigitToValue c base n;
    if (base == 0) {
        n = c-'0';
        if ((n<0) || (n>9)) return -1;
        return n;
    }
    if ((c >= '0') && (c <= '9')) n = c - '0';
    else if ((c >= 'a') && (c <= 'z')) n = c - 'a' + 10;
    else if ((c >= 'A') && (c <= 'Z')) n = c - 'A' + 10;
    else return -1;
    if (n < base) return n;
    return -1;
];

§4. Testing. Not actually used: simply for testing the tables.

[ CharTestCases case i j;
    for (i=32: i<$E0: i++) {
        if ((i>=127) && (i<155)) continue;
        print i, " - ", (char) i, " -";
        if (CharIsOfCase(i, 0)) print "  lower";
        if (CharIsOfCase(i, 1)) print "  upper";
        j = CharToCase(i, 0); if (j ~= i) print "  tolower: ", (char) j;
        j = CharToCase(i, 1); if (j ~= i) print "  toupper: ", (char) j;
        print "^";
    }
];