Beispiel #1
0
 public ZText(byte[] memory)
 {
     this.memory                    = memory;
     this.alphabetTable             = new AlphabetTable(memory);
     this.version                   = Header.ReadVersion(memory);
     this.builder                   = new StringBuilder();
     this.abbreviationAlphabetTable = new AlphabetTable(memory);
     this.abbreviationBuilder       = new StringBuilder();
 }
Beispiel #2
0
        private string ZWordsAsString(ushort[] zwords, ZTextFlags flags, AlphabetTable alphabetTable, StringBuilder builder)
        {
            var zchars = ZWordsToZChars(zwords);

            builder.Clear();
            if (builder.Capacity < zchars.Length)
            {
                builder.Capacity = zchars.Length;
            }

            alphabetTable.FullReset();

            var i = 0;

            while (i < zchars.Length)
            {
                var zchar = zchars[i];

                if (zchar == 0)
                {
                    builder.Append(' ');
                }
                else if (zchar >= 1 && zchar <= 3)
                {
                    if (version == 1 || (version == 2 && zchar >= 2))
                    {
                        switch (zchar)
                        {
                        case 1:
                            builder.Append('\n');
                            break;

                        case 2:
                            alphabetTable.Shift();
                            break;

                        case 3:
                            alphabetTable.DoubleShift();
                            break;
                        }
                    }
                    else // abbeviations
                    {
                        if ((flags & ZTextFlags.AllowAbbreviations) == 0)
                        {
                            throw new InvalidOperationException("Encountered ZSCII code for an illegal abbreviation.");
                        }

                        if (i + 1 < zchars.Length)
                        {
                            var abbreviationCode   = zchars[++i];
                            var abbreviationIndex  = (32 * (zchar - 1)) + abbreviationCode;
                            var abbreviationZWords = ReadAbbreviation(memory, abbreviationIndex);
                            var abbreviationText   = ZWordsAsString(abbreviationZWords, ZTextFlags.None, abbreviationAlphabetTable, abbreviationBuilder);
                            builder.Append(abbreviationText);
                        }
                    }
                }
                else if (zchar == 4)
                {
                    if (version <= 2)
                    {
                        alphabetTable.ShiftLock();
                    }
                    else
                    {
                        alphabetTable.Shift();
                    }
                }
                else if (zchar == 5)
                {
                    if (version <= 2)
                    {
                        alphabetTable.DoubleShiftLock();
                    }
                    else
                    {
                        alphabetTable.DoubleShift();
                    }
                }
                else if (zchar == 6 && alphabetTable.CurrentAlphabet == 2)
                {
                    // If this is character 6 in A2, it's a multibyte ZSCII character
                    // Note that it can be legal for the stream to end in the middle of a
                    // multi-byte ZSCII character (i.e. in the dictionary table). In that case,
                    // the value is discared or an exception is thrown if that behavior
                    // isn't allowed.

                    // The alphabet table must be reset to ensure that the next zcode
                    // after the multi-byte ZSCII character uses the correct alphabet.
                    alphabetTable.Reset();

                    if (i + 2 < zchars.Length)
                    {
                        var zscii1 = zchars[++i];
                        var zscii2 = zchars[++i];
                        var zscii  = ((zscii1 & 0x1f) << 5) | zscii2;
                        builder.Append((char)zscii);
                    }
                    else
                    {
                        if ((flags & ZTextFlags.AllowIncompleteMultibyteChars) == 0)
                        {
                            throw new InvalidOperationException("Encountered illegal incomplete multi-byte ZSCII character.");
                        }
                    }
                }
                else if (zchar > 31)
                {
                    throw new InvalidOperationException("Unexpected ZSCII character value: " + zchar + ". Legal values are from 0 to 31.");
                }
                else
                {
                    builder.Append(alphabetTable.ReadChar(zchar));
                }

                i++;
            }

            return(builder.ToString());
        }