//---Include---
#include "FileSystem.h"

#include <iostream>

#include "Image.h"
#include "Text.h"
#ifdef WIN32
#    include "Window.h"
#    include "Progress.h"
#    include "Globals.h"
#    include "Font.h"
#endif
#include "File.h"
#include "Logging.h"

using namespace Framework;

// LTDB File format
// Content of the LTDBPixel class from FileSystem.h
// Constructor
LTDBPixel::LTDBPixel(LTDBPixel* davor)
    : ReferenceCounter(),
      davor(davor),
      index(0),
      iR(0),
      iG(0),
      iB(0),
      iA(0),
      miR(8),
      miG(8),
      miB(8),
      miA(8),
      maxIndex(1),
      change(0),
      changeR(0),
      changeG(0),
      changeB(0),
      changeA(0),
      komp(0),
      R(0),
      G(0),
      B(0),
      A(0)
{}

// Destructor
LTDBPixel::~LTDBPixel()
{
    if (davor) davor->release();
}

// non-constant
bool LTDBPixel::addBitZuColor(
    unsigned char bit) // Adds a bit to the color values
{
    if (changeR && iR != miR) // The bit belongs to Red
    {
        R = (unsigned char)(R | ((bit & 0x1) << (7 - komp - iR)));
        ++iR;
    }
    else if (changeG && iG != miG) // The bit belongs to Green
    {
        G = (unsigned char)(G | ((bit & 0x1) << (7 - komp - iG)));
        ++iG;
    }
    else if (changeB && iB != miB) // The bit belongs to Blue
    {
        B = (unsigned char)(B | ((bit & 0x1) << (7 - komp - iB)));
        ++iB;
    }
    else if (changeA && iA != miA) // The bit belongs to Alpha
    {
        A = (unsigned char)(A | ((bit & 0x1) << (7 - komp - iA)));
        ++iA;
    }
    else // The bit belongs to the next pixel
        return false;
    return true;
}

char LTDBPixel::addByte(
    char byte, char begin) // returns end of pixel, -1 if not finished
{
    if (begin >= 8 || begin < 0) return -1;
    for (int i = begin; i < 8; ++i)
    {
        switch (index)
        {
        case 0:
            // The first bit of a pixel stores whether the
            // compression changed
            change = (bool)((byte >> (7 - i)) & 0x1);
            if (!change) // If compression doesn't change, the values
                         // from the previous pixel are inherited
            {
                if (!davor) // The file is corrupted (the first pixel cannot
                            // inherit from the previous one)
                {
#ifdef WIN32
                    MessageBox(NULL,
                        "Error, the image file is corrupted",
                        "Error",
                        MB_ICONERROR);
#endif
                    exit(0);
                }
                changeR = davor->getChangeR();
                changeG = davor->getChangeG();
                changeB = davor->getChangeB();
                changeA = davor->getChangeA();
                komp = davor->getKomp() & 7;
                miR = (char)(miR - komp), miG = (char)(miG - komp),
                miB = (char)(miB - komp), miA = (char)(miA - komp);
                if (!changeR) R = davor->getR();
                if (!changeG) G = davor->getG();
                if (!changeB) B = davor->getB();
                if (!changeA) A = davor->getA();
                maxIndex = (char)(maxIndex
                                  + (changeR + changeG + changeB + changeA)
                                        * (8 - komp)); // Determine the length
                // of the pixel in bits. Each color has 8 bits by default,
                // compression can make it smaller
            }
            else
                maxIndex
                    = (char)(maxIndex + 7); // Since the pixel doesn't inherit
                                            // values from the previous one,
                                            // it is 7 bits larger
            break;
        case 1:         // The second bit of a pixel stores either the
                        // compression type or already the color
            if (change) // The bit belongs to the 7 compression bits
                changeR = (bool)((byte >> (7 - i)) & 0x1);
            else
            {
                if (!addBitZuColor(
                        (unsigned char)(byte >> (7 - i)))) // The bit belongs to
                                                           // the color
                    return (unsigned char)i;
            }
            break;
        case 2:         // The third bit of a pixel stores either the
                        // compression type or already the color
            if (change) // The bit belongs to the 7 compression bits
                changeG = (bool)((byte >> (7 - i)) & 0x1);
            else
            {
                if (!addBitZuColor(
                        (unsigned char)(byte >> (7 - i)))) // The bit belongs to
                                                           // the color
                    return (unsigned char)i;
            }
            break;
        case 3:         // The fourth bit of a pixel stores either the
                        // compression type or already the color
            if (change) // The bit belongs to the 7 compression bits
                changeB = (bool)((byte >> (7 - i)) & 0x1);
            else
            {
                if (!addBitZuColor(
                        (unsigned char)(byte >> (7 - i)))) // The bit belongs to
                                                           // the color
                    return (unsigned char)i;
            }
            break;
        case 4:         // The fifth bit of a pixel stores either the
                        // compression type or already the color
            if (change) // The bit belongs to the 7 compression bits
                changeA = (bool)((byte >> (7 - i)) & 0x1);
            else
            {
                if (!addBitZuColor(
                        (unsigned char)(byte >> (7 - i)))) // The bit belongs to
                                                           // the color
                    return (unsigned char)i;
            }
            break;
        case 5:         // The sixth bit of a pixel stores either the
                        // compression type or already the color
            if (change) // The bit belongs to the 7 compression bits
                komp = (unsigned char)(komp
                                       | ((unsigned char)((byte >> (7 - i))
                                                          & 0x1)
                                           << 2))
                     & 7;
            else
            {
                if (!addBitZuColor(
                        (unsigned char)(byte >> (7 - i)))) // The bit belongs to
                                                           // the color
                    return (unsigned char)i;
            }
            break;
        case 6:         // The seventh bit of a pixel stores either the
                        // compression type or already the color
            if (change) // The bit belongs to the 7 compression bits
                komp = (unsigned char)(komp
                                       | ((unsigned char)((byte >> (7 - i))
                                                          & 0x1)
                                           << 1))
                     & 7;
            else
            {
                if (!addBitZuColor(
                        (unsigned char)(byte >> (7 - i)))) // The bit belongs to
                                                           // the color
                    return (unsigned char)i;
            }
            break;
        case 7:         // The eighth bit of a pixel stores either the
                        // compression type or already the color
            if (change) // The bit belongs to the 7 compression bits
            {
                komp = (unsigned char)(komp | ((byte >> (7 - i)) & 0x1)) & 7;
                // That was the last compression bit
                // Evaluate compression
                miR = (char)(miR - komp), miG = (char)(miG - komp),
                miB = (char)(miB - komp), miA = (char)(miA - komp);
                if (!changeR) R = davor->getR();
                if (!changeG) G = davor->getG();
                if (!changeB) B = davor->getB();
                if (!changeA) A = davor->getA();
                maxIndex
                    = (char)(maxIndex
                             + (changeR + changeG + changeB + changeA)
                                   * (8 - komp)); // Bit length of the pixel
            }
            else
            {
                if (!addBitZuColor(
                        (unsigned char)(byte >> (7 - i)))) // The bit belongs to
                                                           // the color
                    return (unsigned char)i;
            }
            break;
        default: // The remaining bits all store the color values of the pixel
            if (!addBitZuColor((
                    unsigned char)(byte
                                   >> (7 - i)))) // The bit belongs to the color
                return (unsigned char)i;
            break;
        }
        ++index;
        if (index >= maxIndex)
        {
            if (davor)
            {
                if (changeR) R = (unsigned char)(davor->getR() + R);
                if (changeG) G = (unsigned char)(davor->getG() + G);
                if (changeB) B = (unsigned char)(davor->getB() + B);
                if (changeA) A = (unsigned char)(davor->getA() + A);
                davor = (LTDBPixel*)davor->release();
            }
            return (char)(i + 1);
        }
    }
    return -1;
}

void LTDBPixel::setColor(int f) // sets the color of the pixel
{ // Since this function is called, the class is now to be used for saving
    // Reset values in case the class was already used for loading or saving
    index = 0, maxIndex = 1;
    change = 0, changeR = 0, changeG = 0, changeB = 0, changeA = 0, komp = 0;
    iR = 0, iG = 0, iB = 0, iA = 0;
    miR = 8, miG = 8, miB = 8, miA = 8;
    // Set color values
    R = (unsigned char)(f >> 16);
    G = (unsigned char)(f >> 8);
    B = (unsigned char)f;
    A = (unsigned char)(f >> 24);
}

void LTDBPixel::compress() // Compresses the pixel
{
    maxIndex = 1;
    if (!davor)
    { // This is the first pixel
        change = 1;
        changeR = 1;
        changeG = 1;
        changeB = 1;
        changeA = 1;
        maxIndex = (char)(maxIndex + 7);
        miR = (char)getBits(R);
        miG = (char)getBits(G);
        miB = (char)getBits(B);
        miA = (char)getBits(A);
    }
    else
    { // The difference to the previous pixel is stored
        miR = (char)getBits((char)(R - davor->getR()));
        miG = (char)getBits((char)(G - davor->getG()));
        miB = (char)getBits((char)(B - davor->getB()));
        miA = (char)getBits((char)(A - davor->getA()));
        changeR = R != davor->getR();
        changeG = G != davor->getG();
        changeB = B != davor->getB();
        changeA = A != davor->getA();
    } // Check if something changes
    if (!miR && changeR) ++miR;
    if (!miG && changeG) ++miG;
    if (!miB && changeB) ++miB;
    if (!miA && changeA) ++miA;
    int k = (miR > miG ? miR : miG);
    k = (k > miB ? k : miB);
    k = (k > miA ? k : miA);
    miR = (char)k, miG = (char)k, miB = (char)k, miA = (char)k;
    komp = (unsigned char)(8 - k) & 7;
    maxIndex = (char)(maxIndex + (changeR + changeG + changeB + changeA) * k);
    if (davor)
    {
        if (changeR != davor->getChangeR() || changeG != davor->getChangeG()
            || changeB != davor->getChangeB() || changeA != davor->getChangeA()
            || komp != davor->getKomp())
        { // Something changes
            change = 1;
            maxIndex = (char)(maxIndex + 7);
        }
        else
        { // Nothing changes
            change = 0;
        }
    }
}

bool LTDBPixel::getNextColorBit(
    char& byte, int i) // Stores the next color bit in byte
{
    unsigned char RR = R;
    unsigned char GG = G;
    unsigned char BB = B;
    unsigned char AA = A;
    if (davor)
    {
        RR = (unsigned char)(RR - davor->getR());
        GG = (unsigned char)(GG - davor->getG());
        BB = (unsigned char)(BB - davor->getB());
        AA = (unsigned char)(AA - davor->getA());
    }
    if (changeR && iR != miR) // The bit belongs to red
    {
        byte |= (char)(((RR >> (7 - komp - iR)) & 0x1) << (7 - i));
        ++iR;
    }
    else if (changeG && iG != miG) // The bit belongs to green
    {
        byte |= (char)(((GG >> (7 - komp - iG)) & 0x1) << (7 - i));
        ++iG;
    }
    else if (changeB && iB != miB) // The bit belongs to blue
    {
        byte |= (char)(((BB >> (7 - komp - iB)) & 0x1) << (7 - i));
        ++iB;
    }
    else if (changeA && iA != miA) // The bit belongs to alpha
    {
        byte |= (char)(((AA >> (7 - komp - iA)) & 0x1) << (7 - i));
        ++iA;
    }
    else // The pixel is already finished
        return false;
    return true;
}

char LTDBPixel::getNextByte(
    char& byte, int begin) // Returns the next bits, -1 if the pixel
                           // is not finished
{
    // begin specifies where to write in the byte variable
    // the function returns the end of the pixel in the byte variable
    // -1 means the pixel is not finished
    for (int i = begin; i < 8; ++i)
    {
        switch (index)
        {
        case 0: // The first bit of the pixel stores whether the
                // compression changes
            byte |= (char)(((int)change & 0x1) << (7 - i));
            break;
        case 1: // The second bit of the pixel stores either the color
                // or the compression
            if (change) // Compression
                byte |= (char)(((int)changeR & 0x1) << (7 - i));
            else // Color
            {
                if (!getNextColorBit(byte, i)) return (char)i;
            }
            break;
        case 2: // The third bit of the pixel stores either the color
                // or the compression
            if (change) // Compression
                byte |= (char)(((int)changeG & 0x1) << (7 - i));
            else // Color
            {
                if (!getNextColorBit(byte, i)) return (char)i;
            }
            break;
        case 3: // The fourth bit of the pixel stores either the color
                // or the compression
            if (change) // Compression
                byte |= (char)(((int)changeB & 0x1) << (7 - i));
            else // Color
            {
                if (!getNextColorBit(byte, i)) return (char)i;
            }
            break;
        case 4: // The fifth bit of the pixel stores either the color
                // or the compression
            if (change) // Compression
                byte |= (char)(((int)changeA & 0x1) << (7 - i));
            else // Color
            {
                if (!getNextColorBit(byte, i)) return (char)i;
            }
            break;
        case 5: // The sixth bit of the pixel stores either the color
                // or the compression
            if (change) // Compression
                byte |= (char)(((komp >> 2) & 0x1) << (7 - i));
            else // Color
            {
                if (!getNextColorBit(byte, i)) return (char)i;
            }
            break;
        case 6: // The seventh bit of the pixel stores either the color
                // or the compression
            if (change) // Compression
                byte |= (char)(((komp >> 1) & 0x1) << (7 - i));
            else // Color
            {
                if (!getNextColorBit(byte, i)) return (char)i;
            }
            break;
        case 7: // The eighth bit of the pixel stores either the color
                // or the compression
            if (change) // Compression
                byte |= (char)((komp & 0x1) << (7 - i));
            else // Color
            {
                if (!getNextColorBit(byte, i)) return (char)i;
            }
            break;
        default: // The remaining bits store the color of the pixel
            if (!getNextColorBit(byte, i)) return (char)i;
            break;
        }
        ++index;
        if (index >= maxIndex)
        {
            if (davor) davor = (LTDBPixel*)davor->release();
            return (char)(i + 1);
        }
    }
    return -1;
}

// constant
int LTDBPixel::toColor() const // returns the pixel as color
{
    return (((int)R << 16) | ((int)G << 8) | (int)B | ((int)A << 24));
}

bool LTDBPixel::getChangeR() const
{
    return changeR;
}

bool LTDBPixel::getChangeG() const
{
    return changeG;
}

bool LTDBPixel::getChangeB() const
{
    return changeB;
}

bool LTDBPixel::getChangeA() const
{
    return changeA;
}

unsigned char LTDBPixel::getKomp() const
{
    return komp;
}

unsigned char LTDBPixel::getR() const // returns red
{
    return R;
}

unsigned char LTDBPixel::getG() const // returns green
{
    return G;
}

unsigned char LTDBPixel::getB() const // returns blue
{
    return B;
}

unsigned char LTDBPixel::getA() const // returns alpha
{
    return A;
}

// Content of the LTDBFileHeader class from FileSystem.h
// Constructor
LTDBFileHeader::LTDBFileHeader()
    : ReferenceCounter(),
      bilder(new RCArray<Text>()),
      pos(new Array<__int64>()),
      bCount(0)
{}

// Destructor
LTDBFileHeader::~LTDBFileHeader()
{
    bilder->release();
    pos->release();
}

// non-constant
void LTDBFileHeader::removeImage(int i)
{
    if (i >= bCount) return;
    bilder->remove(i);
    pos->remove(i);
    --bCount;
}

void LTDBFileHeader::removeImage(Text* txt)
{
    int i = -1;
    for (int ii = 0; ii < bCount; ++ii)
    {
        Text* b = bilder->z(ii);
        if (b->isEqual(txt->getText()))
        {
            i = ii;
            break;
        }
    }
    txt->release();
    if (i == -1) return;
    bilder->remove(i);
    pos->remove(i);
    --bCount;
}

void LTDBFileHeader::addImage(Text* txt)
{
    bilder->add(txt, bCount);
    pos->add(0, bCount);
    ++bCount;
}

void LTDBFileHeader::setImagePos(int i, __int64 pos)
{
    this->pos->set(pos, i);
}

void LTDBFileHeader::setImagePos(Text* txt, __int64 pos)
{
    int i = -1;
    for (int ii = 0; ii < bCount; ++ii)
    {
        Text* b = bilder->z(ii);
        if (b->isEqual(txt->getText()))
        {
            i = ii;
            break;
        }
    }
    txt->release();
    if (i == -1) return;
    this->pos->set(pos, i);
}

void LTDBFileHeader::load(ProgressBar* f, std::ifstream* inF)
{
    if (inF->is_open() && inF->good())
    {
        char b = 0;
        inF->read(&b, 1);
        bCount = b << 8;
        inF->read(&b, 1);
        bCount |= b & 0xFF;
#ifdef WIN32
        if (f)
        {
            f->reset();
            f->setActionCount(bCount);
        }
#endif
        bilder->clear();
        pos->clear();
        for (int i = 0; i < bCount; ++i)
        {
            LTDBHeader* kpf = new LTDBHeader();
            kpf->load(inF);              // image name and half file position
            bilder->add(kpf->getTitel()); // sets title
            Point gr = kpf->getSize();
            kpf->release();
            char p[5];
            inF->read((char*)p, 5); // other half of the file position
            unsigned __int64 position
                = (((__int64)gr.x << 52) & 0xFFF0000000000000)
                | (((__int64)gr.y << 40) & 0xFFF0000000000)
                | (((__int64)p[0] << 32) & 0xFF00000000)
                | (((__int64)p[1] << 24) & 0xFF000000)
                | (((__int64)p[2] << 16) & 0xFF0000)
                | (((__int64)p[3] << 8) & 0xFF00) | ((__int64)p[4] & 0xFF);
            pos->add(position, i); // sets position
#ifdef WIN32
            if (f) f->actionPlus();
#endif
        }
    }
}

// constant
void LTDBFileHeader::save(std::ofstream* outF) const
{
    if (outF->is_open() && outF->good())
    {
        char b = (char)(bCount >> 8);
        outF->write(&b, 1);
        b = (char)bCount;
        outF->write(&b, 1);
        for (int i = 0; i < bCount; ++i)
        {
            LTDBHeader* kpf = new LTDBHeader();
            __int64 position = pos->get(i);
            kpf->Init(bilder->get(i),
                Point((int)(position >> 52), (int)(position >> 40)));
            kpf->save(outF);
            kpf->release();
            char p[] = {(char)(position >> 32),
                (char)(position >> 24),
                (char)(position >> 16),
                (char)(position >> 8),
                (char)(position)};
            outF->write((char*)p, 5);
        }
    }
}

Text* LTDBFileHeader::getImage(int i) const
{
    return bilder->get(i);
}

Text* LTDBFileHeader::zImage(int i) const
{
    return bilder->z(i);
}

__int64 LTDBFileHeader::getImagePosition(Text* txt) const
{
    int i = -1;
    for (int ii = 0; ii < bCount; ++ii)
    {
        Text* b = bilder->z(ii);
        if (b->isEqual(txt->getText()))
        {
            i = ii;
            break;
        }
    }
    txt->release();
    if (i == -1) return -1;
    return pos->get(i);
}

__int64 LTDBFileHeader::getImagePosition(int index) const
{
    return pos->get(index);
}

int LTDBFileHeader::getImageIndex(Text* txt) const
{
    int i = -1;
    for (int ii = 0; ii < bCount; ++ii)
    {
        Text* b = bilder->z(ii);
        if (b->isEqual(txt->getText()))
        {
            i = ii;
            break;
        }
    }
    txt->release();
    return i;
}

int LTDBFileHeader::getBCount() const
{
    return bCount;
}

RCArray<Text>* LTDBFileHeader::zImageListe() const
{
    return bilder;
}

// Content of the LTDBHeader class from FileSystem.h
// Constructor
LTDBHeader::LTDBHeader()
    : ReferenceCounter()
{}

// non-constant
void LTDBHeader::load(std::ifstream* f) // Loads data from a file
{
    if (f->is_open())
    {
        a = 0;
        b = 0;
        c = 0;
        char aa = 0;
        f->read(&aa, 1);
        int tl = (aa >> 4) & Bits(4);
        int BitCount = 4 + tl * 5 + 24;
        f->seekg(-1, std::ios::cur);
        int Bytes = BitCount / 8;
        if (((float)BitCount / 8.0f) != (float)Bytes) ++Bytes;
        char byte = 0;
        for (int i = 0; i < Bytes; ++i)
        {
            f->read(&byte, 1);
            setBits(i * 8, i * 8 + 8, byte);
        }
    }
}

int LTDBHeader::Init(Text* t, const Point& g) // Fills the data
{
    a = 0;
    b = 0;
    c = 0;
    int tl = t->getLength();
    if (tl > 15) tl = 15;
    char* title = new char[tl];
    int skipped = 0;
    for (int i = 0; i < tl; ++i)
    {
        title[i - skipped] = t->getText()[i];
        if (title[i - skipped] > 96 && title[i - skipped] < 123)
            title[i - skipped] = (char)(title[i - skipped] - 96);
        else if (title[i - skipped] > 64 && title[i - skipped] < 91)
            title[i - skipped] = (char)(title[i - skipped] - 64);
        else if (title[i - skipped] == SpecialCharacters::SMALL_UE
                 || title[i - skipped] == SpecialCharacters::BIG_UE)
            title[i - skipped] = 27;
        else if (title[i - skipped] == SpecialCharacters::SMALL_OE
                 || title[i - skipped] == SpecialCharacters::BIG_OE)
            title[i - skipped] = 28;
        else if (title[i - skipped] == SpecialCharacters::SMALL_AE
                 || title[i - skipped] == SpecialCharacters::BIG_AE)
            title[i - skipped] = 29;
        else if (title[i - skipped] == SpecialCharacters::SZ)
            title[i - skipped] = 30;
        else if (title[i - skipped] == '.')
            title[i - skipped] = 31;
        else
            ++skipped;
    }
    a = (__int64)((tl - skipped) & Bits(4)) << 60;
    int BeginBit = 4;
    for (int i = 0; i < tl - skipped; ++i)
    {
        BeginBit += 5;
        switch (i)
        {
        case 0:
            a |= (__int64)(title[i] & 31) << 55; // store 1st character
            break;
        case 1:
            a |= (__int64)(title[i] & 31) << 50; // store 2nd character
            break;
        case 2:
            a |= (__int64)(title[i] & 31) << 45; // store 3rd character
            break;
        case 3:
            a |= (__int64)(title[i] & 31) << 40; // store 4th character
            break;
        case 4:
            a |= (__int64)(title[i] & 31)
              << 35; // store 5th character
            break;
        case 5:
            a |= (__int64)(title[i] & 31)
              << 30; // store 6th character
            break;
        case 6:
            a |= (__int64)(title[i] & 31) << 25; // store 7th character
            break;
        case 7:
            a |= (__int64)(title[i] & 31) << 20; // store 8th character
            break;
        case 8:
            a |= (__int64)(title[i] & 31) << 15; // store 9th character
            break;
        case 9:
            a |= (__int64)(title[i] & 31) << 10; // store 10th character
            break;
        case 10:
            a |= (__int64)(title[i] & 31) << 5; // store 11th character
            break;
        case 11:
            a |= (__int64)(title[i] & 31); // store 12th character
            break;
        case 12:
            b |= (__int32)(title[i] & 31)
              << 27; // store 13th character
            break;
        case 13:
            b |= (__int32)(title[i] & 31)
              << 22; // store 14th character
            break;
        case 14:
            b |= (__int32)(title[i] & 31)
              << 17; // store 15th character
            break;
        }
    }
    __int16 grx = (short)(g.x & Bits(12));
    __int16 gry = (short)(g.y & Bits(12));
    int EndBit = BeginBit + 24;
    setBits(BeginBit, EndBit - 12, grx);
    setBits(BeginBit + 12, EndBit, gry);
    t->release();
    delete[] title;
    return skipped;
}

void LTDBHeader::setBits(int BeginBit, int EndBit, __int16 bits)
{
    if (EndBit - BeginBit > 16) EndBit = BeginBit + 16;
    if (BeginBit < 64)
    {
        if (EndBit < 64)
        {
            a |= ((__int64)bits & Bits(EndBit - BeginBit))
              << ((64 - BeginBit) - (EndBit - BeginBit));
        }
        else
        {
            a |= (((__int64)bits >> (EndBit - 64)) & Bits(64 - BeginBit));
            b |= ((__int32)bits & Bits(EndBit - 64)) << (32 - (EndBit - 64));
        }
    }
    else
    {
        if (BeginBit < 96)
        {
            if (EndBit < 96)
            {
                b |= ((__int32)bits & Bits(EndBit - BeginBit))
                  << ((96 - BeginBit) - (EndBit - BeginBit));
            }
            else
            {
                b |= (((__int32)bits >> (EndBit - 96)) & Bits(96 - BeginBit));
                c = (char)(c
                           | (((__int8)bits & Bits(EndBit - 96))
                               << (8 - (EndBit - 96))));
            }
        }
        else
        {
            c = (char)(c
                       | (((__int8)bits & Bits(EndBit - BeginBit))
                           << (8 - (EndBit - BeginBit))));
        }
    }
}

// constant
void LTDBHeader::save(
    std::ofstream* f) const // Saves data to a file
{
    if (f->is_open())
    {
        int bits = 4 /*title length*/ + getTitelLength() * 5 /*title*/
                 + 24 /*image size*/;
        int bytes = bits / 8; // byte length of the file header
        if (((float)bits / 8.0f) != (float)bytes) ++bytes;
        char c = 0;
        for (int i = 0; i < bytes; ++i)
        {
            c = (char)getBits(i * 8, i * 8 + 8);
            f->write(&c, 1);
        }
    }
}

int LTDBHeader::getTitelLength() const // returns the length of the image name
{
    return (int)(a >> 60 & Bits(4)); // The title length is stored in the first
                                     // 4 bits of the file
}

Text* LTDBHeader::getTitel() const // returns the name of the image
{
    Text* ret = new Text("");
    char c[2];
    c[1] = '\0';
    int l = getTitelLength();
    for (int i = 0; i < l; ++i)
    {
        c[0] = 0;
        switch (i)
        {
        case 0:
            c[0] = (a >> 55) & 31; // get 1st character
            break;
        case 1:
            c[0] = (a >> 50) & 31; // get 2nd character
            break;
        case 2:
            c[0] = (a >> 45) & 31; // get 3rd character
            break;
        case 3:
            c[0] = (a >> 40) & 31; // get 4th character
            break;
        case 4:
            c[0] = (a >> 35) & 31; // get 5th character
            break;
        case 5:
            c[0] = (a >> 30) & 31; // get 6th character
            break;
        case 6:
            c[0] = (a >> 25) & 31; // get 7th character
            break;
        case 7:
            c[0] = (a >> 20) & 31; // get 8th character
            break;
        case 8:
            c[0] = (a >> 15) & 31; // get 9th character
            break;
        case 9:
            c[0] = (a >> 10) & 31; // get 10th character
            break;
        case 10:
            c[0] = (a >> 5) & 31; // get 11th character
            break;
        case 11:
            c[0] = a & 31; // get 12th character
            break;
        case 12:
            c[0] = (char)((b >> 27) & 31); // get 13th character
            break;
        case 13:
            c[0] = (char)((b >> 22) & 31); // get 14th character
            break;
        case 14:
            c[0] = (char)((b >> 17) & 31); // get 15th character
            break;
        }
        if (c[0] == 27)
            c[0] = SpecialCharacters::SMALL_UE;
        else if (c[0] == 28)
            c[0] = SpecialCharacters::SMALL_OE;
        else if (c[0] == 29)
            c[0] = SpecialCharacters::SMALL_AE;
        else if (c[0] == 30)
            c[0] = SpecialCharacters::SZ;
        else if (c[0] == 31)
            c[0] = '.';
        else
            c[0] = (char)(c[0] + 96);
        ret->append(c);
    }
    return ret;
}

Point LTDBHeader::getSize() const // returns the size of the image
{
    int BeginBit = 4 /*title length*/ + getTitelLength() * 5 /*title*/;
    int EndBit = BeginBit + 24;
    __int16 grx = getBits(BeginBit, EndBit - 12);
    __int16 gry = getBits(BeginBit + 12, EndBit);
    return Point((int)(grx & Bits(12)), (int)(gry & Bits(12)));
}

__int16 LTDBHeader::getBits(int begin,
int ende) const // returns the bits from begin to ende (excluding ende)
{
    if (ende < begin) return 0;
    if (ende - begin > 16) ende = begin + 16;
    __int16 ret = 0;
    if (begin < 64)
    {
        if (ende < 64)
        {
            ret = (__int16)(a >> ((64 - begin) - (ende - begin))
                            & Bits(ende - begin));
        }
        else
        {
            ret = (__int16)((a & Bits(64 - begin)) << (ende - 64));
            ret = (__int16)(ret
                            | ((b >> (32 - (ende - 64))) & Bits(ende - 64)));
        }
    }
    else
    {
        if (begin < 96)
        {
            if (ende < 96)
            {
                ret = (__int16)(b >> ((96 - begin) - (ende - begin))
                                & Bits(ende - begin));
            }
            else
            {
                ret = (__int16)((b & Bits(96 - begin)) << (ende - 96));
                ret = (__int16)(ret
                                | ((c >> (8 - (ende - 96))) & Bits(ende - 96)));
            }
        }
        else
        {
            ret = (__int16)(c >> ((104 - begin) - (ende - begin))
                            & Bits(ende - begin));
        }
    }
    return ret;
}

// Content of the LTDBBody class from FileSystem.h
// Constructor
LTDBBody::LTDBBody()
    : ReferenceCounter(),
      gr(0, 0),
      b(new Image())
{}

LTDBBody::LTDBBody(LTDBHeader* k) // calls init
    : ReferenceCounter(),
      gr(0, 0),
      b(new Image())
{
    init(k);
}

// Destructor
LTDBBody::~LTDBBody()
{
    b->release();
}

// non-constant
void LTDBBody::init(LTDBHeader k) // Initializes, required before loading
{
    gr = k.getSize();
    int l = k.getTitelLength();
    l = 4 + l * 5 + 24;
    dateiSize = (l / 8.0 == l) ? (l / 8) : (l / 8 + 1);
}

void LTDBBody::init(LTDBHeader* k) // Initializes, required before loading
{
    gr = k->getSize();
    int l = k->getTitelLength();
    l = 4 + l * 5 + 24;
    dateiSize = (l / 8.0 == l) ? (l / 8) : (l / 8 + 1);
    k->release();
}

void LTDBBody::load(ProgressBar* zF, std::ifstream* inF) // loads the image
{
    b->newImage(gr.x, gr.y, 0xFF000000); // create new image
    int* buff = b->getBuffer();
    int Width = b->getWidth();
    char byte = 0;
    int index = 0;
    LTDBPixel* davor = 0;                 // last loaded pixel
    LTDBPixel* dieser = new LTDBPixel(0); // pixel currently being loaded
    int begin = 0; // pixel start, end position in the byte variable
#ifdef WIN32
    if (zF)
    {
        zF->reset();
        zF->setActionCount(gr.x * gr.y);
    }
#endif
    while (index < gr.x * gr.y) // for each pixel
    {
        if (!dieser) // if it is not the first pixel
            dieser = new LTDBPixel(dynamic_cast<LTDBPixel*>(davor->getThis()));
        int ende = -1;
        while (ende < 0) // load pixel
        {
            if (begin == 0) inF->read(&byte, 1);
            ende = dieser->addByte(byte, (char)begin); // evaluate byte
            begin = 0;
        }
        begin = ende;
        if (begin == 8) begin = 0;
        buff[(index % gr.x) + (index / gr.x) * Width] = dieser->toColor();
        if (davor) davor = (LTDBPixel*)davor->release();
        davor = dynamic_cast<LTDBPixel*>(dieser->getThis());
        dieser = (LTDBPixel*)dieser->release();
        ++index;
#ifdef WIN32
        if (zF) zF->actionPlus();
#endif
    }
    if (davor) davor = (LTDBPixel*)davor->release();
}

void LTDBBody::setImage(Image* b) // sets the image to be saved
{
    this->b->release();
    this->b = b;
}

// constant
void LTDBBody::save(
    ProgressBar* zF, std::ofstream* outF) const // saves image
{
    if (outF->is_open())
    {
        LTDBPixel* letzter = 0; // Last saved pixel
        LTDBPixel* dieser
            = new LTDBPixel(0); // The pixel currently being saved
        int begin = 0,
            ende = 0;  // pixel start, end position in the byte variable
        char byte = 0; // The next byte of the file
        bool w = 0;
#ifdef WIN32
        if (zF)
        {
            zF->reset();
            zF->setActionCount(gr.x * gr.y);
        }
#endif
        int* pBuff = b->getBuffer();
        for (int i = 0; i < gr.x * gr.y; ++i) // for each pixel
        {
            if (!dieser) // if it is not the first pixel
                dieser = new LTDBPixel(
                    dynamic_cast<LTDBPixel*>(letzter->getThis()));
            dieser->setColor(pBuff[i]); // set pixel color
            dieser->compress();     // compress pixel
            ende = -1;
            while (ende < 0) // fill byte
            {
                ende = dieser->getNextByte(byte, begin);
                begin = 0;
                w = 0;
                if (ende == -1 || ende == 8) // save byte
                {
                    outF->write(&byte, 1);
                    w = 1;
                    byte = 0;
                }
            } // pixel finished
            begin = ende;
            if (begin == 8) begin = 0;
            if (letzter) letzter->release();
            letzter = dynamic_cast<LTDBPixel*>(
                dieser->getThis()); // dieser becomes letzter
            dieser = (LTDBPixel*)dieser->release();
#ifdef WIN32
            if (zF) zF->actionPlus();
#endif
        }
        if (letzter) letzter = (LTDBPixel*)letzter->release();
        if (!w)
        {
            outF->write(&byte, 1); // save the last byte
        }
        outF->flush(); // flush file stream
    }
}

Image* LTDBBody::getImage() const // returns the loaded image
{
    return dynamic_cast<Image*>(b->getThis());
}

const Point& LTDBBody::getSize() const // returns the size of the image
{
    return gr;
}

// Content of the LTDBFile class from FileSystem.h
// Constructor
LTDBFile::LTDBFile()
    : ReferenceCounter(),
      pfad(new Text()),
      datKpf(0)
{}

// Destructor
LTDBFile::~LTDBFile()
{
    if (pfad) pfad->release();
    if (datKpf) datKpf->release();
}

// non-constant
void LTDBFile::setFile(Text* pfad) // Sets the path to the file
{ // Delete values of any previous file
    if (datKpf) datKpf = (LTDBFileHeader*)datKpf->release();
    // Set path
    this->pfad->setText(*pfad);
    pfad->release();
}

void LTDBFile::create() // Creates the file
{
    FilePathCreate(dynamic_cast<Text*>(pfad->getThis()));
    std::ofstream* outF = new std::ofstream(pfad->getText(), std::ios::binary);
    int i = 0;
    outF->write((char*)&i, 2);
    delete outF;
}

void LTDBFile::readData(
    ProgressBar* f) // The class briefly reads all images and remembers
                // where in the file each one is located
{ // This function will take some time, but will make
  // the other functions faster afterwards
    if (FileExists(dynamic_cast<Text*>(pfad->getThis())))
    {
        if (datKpf) datKpf->release();
        datKpf = new LTDBFileHeader();
        std::ifstream* inF
            = new std::ifstream(pfad->getText(), std::ios::binary);
        datKpf->load(f, inF);
        delete inF;
    }
}

void LTDBFile::remove() // Deletes the file
{
    if (FileExists(dynamic_cast<Text*>(pfad->getThis())))
    {
        FileRemove(dynamic_cast<Text*>(pfad->getThis()));
        if (datKpf) datKpf->release();
    }
}

void LTDBFile::remove(ProgressBar* f, Text* name) // Deletes an image from the file
{
    if (FileExists(dynamic_cast<Text*>(pfad->getThis())) && name)
    {
        if (!datKpf) readData(0); // read data
        // Check if file is not present
        if (!datKpf)
        {
            name->release();
            return;
        }
        int index = datKpf->getImageIndex(dynamic_cast<Text*>(name->getThis()));
        if (index == -1) // the image does not exist
        {
            name->release();
            return;
        }
        // Determine temporary file path
        Text* pf_tmp = new Text(pfad->getText());
        char c = '0';
        pf_tmp->append("0");
        for (int i = 0; FileExists(dynamic_cast<Text*>(pf_tmp->getThis()));
            ++i)
        {
            c = (char)('0' + (i % 10));
            if ((i % 10) == 0) pf_tmp->append("$");
            pf_tmp->replace(
                pf_tmp->countOf((char)('0' - ((i - 1) % 10))) - 1,
                (char)('0' - ((i - 1) % 10)),
                c);
        }
        std::ifstream* inF = new std::ifstream(
            pfad->getText(), std::ios::binary); // open old file
        inF->seekg(0, std::ios::end);
        __int64 datlen = inF->tellg();
        inF->seekg(0, std::ios::beg);
        std::ofstream* outF = new std::ofstream(
            pf_tmp->getText(), std::ios::binary); // open new file
        if (inF->is_open() && outF->is_open())
        {
            __int64 position = datKpf->getImagePosition(index);
            datKpf->removeImage(index);
            datKpf->save(outF);
            LTDBFileHeader* kpf_tmp = new LTDBFileHeader();
            kpf_tmp->load(0, inF);
            kpf_tmp->release();
            char byte = 0;
            __int64 pos_minus = inF->tellg() - outF->tellp();
            for (int i = 0; i < index; ++i)
                datKpf->setImagePos(i, datKpf->getImagePosition(i) - pos_minus);
            // Copy bytes up to the file
            for (__int64 i = inF->tellg(); i < position; ++i)
            {
                inF->read(&byte, 1);
                outF->write(&byte, 1);
            } // skip image to be deleted
            LTDBHeader* delkpf = new LTDBHeader();
            delkpf->load(inF);
            LTDBBody* delkpr
                = new LTDBBody(dynamic_cast<LTDBHeader*>(delkpf->getThis()));
            delkpr->load(f, inF);
            delkpf = (LTDBHeader*)delkpf->release();
            delkpr = (LTDBBody*)delkpr->release(); // copy remaining bytes
            pos_minus = inF->tellg() - outF->tellp();
            for (__int64 i = (__int64)inF->tellg(); i < datlen; ++i)
            {
                inF->read(&byte, 1);
                outF->write(&byte, 1);
            }
            for (int i = index; i < datKpf->getBCount(); ++i)
                datKpf->setImagePos(i, datKpf->getImagePosition(i) - pos_minus);
            outF->seekp(0, std::ios::beg);
            datKpf->save(outF);
            inF->close();
            outF->close();
            FileRemove(dynamic_cast<Text*>(pfad->getThis()));
            FileRename(dynamic_cast<Text*>(pf_tmp->getThis()),
                dynamic_cast<Text*>(pfad->getThis()));
        }
        delete inF;
        delete outF;
        pf_tmp = (Text*)pf_tmp->release();
    }
    if (name) name = (Text*)name->release();
}

Image* LTDBFile::load(ProgressBar* f, Text* name) // Loads an image from the file
{
    if (name)
    {
        if (!FileExists(dynamic_cast<Text*>(pfad->getThis())))
        {
            name->release();
            return 0;
        }
        if (!datKpf) readData(0);
        LTDBHeader* k_tmp = new LTDBHeader();
        k_tmp->Init(dynamic_cast<Text*>(name->getThis()), Point(0, 0));
        int index = datKpf->getImageIndex(k_tmp->getTitel());
        k_tmp->release();
        if (index == -1)
        { // Error message
            Text* fehler = new Text("The image ");
            fehler->append(*name);
            fehler->append(" was not found in the file\n");
            fehler->append(*pfad);
            fehler->append("!");
            Logging::error() << fehler << "\n";
            name->release();
            return 0;
        }
        std::ifstream* inF
            = new std::ifstream(pfad->getText(), std::ios::binary);
        // Determine start of the file to load
        __int64 position = datKpf->getImagePosition(index);
        inF->seekg(position, std::ios::beg);
        LTDBHeader* kpf = new LTDBHeader();
        kpf->load(inF);
        Text* t = kpf->getTitel();
        if (!t->isEqual(*name))
        { // Error message
            t->release();
            kpf->release();
            inF->close();
            delete inF;
            Text* fehler = new Text("The file ");
            fehler->append(*pfad);
            fehler->append(" is not a valid LTDB file!");
#ifdef WIN32
            WMessageBox(0, new Text("Error"), fehler, MB_ICONERROR);
#endif
            name->release();
            return 0;
        }
        t->release();
        LTDBBody* kpr = new LTDBBody(dynamic_cast<LTDBHeader*>(kpf->getThis()));
        kpr->load(f, inF); // load image
        Image* ret = kpr->getImage();
        kpr->release();
        kpf->release();
        inF->close();
        delete inF;
        name->release();
        return ret;
    }
    return 0;
}

int LTDBFile::save(
ProgressBar* f, Image* bild, Text* name) // Saves an image to the file
{
    int warn = -1;
    if (name && bild)
    {
        if (FileExists(dynamic_cast<Text*>(pfad->getThis())))
        {
            if (!datKpf) readData(0);
            int index
                = datKpf->getImageIndex(dynamic_cast<Text*>(name->getThis()));
            if (index == -1)
            {
                warn = 0;
                LTDBHeader* kpf = new LTDBHeader();
                warn = kpf->Init(
                    dynamic_cast<Text*>(name->getThis()), bild->getSize());
                if (datKpf->getImageIndex(kpf->getTitel()) != -1)
                {
                    Logging::error()
                        << "An image with this name already exists!\n";
                    bild->release();
                    name->release();
                    kpf->release();
                    return -1;
                }
                // find temporary file path
                Text* pf_tmp = new Text(pfad->getText());
                char c = '0';
                pf_tmp->append("0");
                for (int i = 0;
                    FileExists(dynamic_cast<Text*>(pf_tmp->getThis()));
                    ++i)
                {
                    c = (char)('0' + (i % 10));
                    if ((i % 10) == 0) pf_tmp->append("$");
                    pf_tmp->replace(
                        pf_tmp->countOf((char)('0' - ((i - 1) % 10))) - 1,
                        (char)('0' - ((i - 1) % 10)),
                        c);
                }
                std::ifstream* inF
                    = new std::ifstream(pfad->getText(), std::ios::binary);
                inF->seekg(0, std::ios::end);
                __int64 datLen = inF->tellg();
                inF->seekg(0, std::ios::beg);
                std::ofstream* outF
                    = new std::ofstream(pf_tmp->getText(), std::ios::binary);
                datKpf->addImage(kpf->getTitel());
                index = datKpf->getImageIndex(kpf->getTitel());
                datKpf->save(outF);
                LTDBFileHeader* kpf_tmp = new LTDBFileHeader();
                kpf_tmp->load(0, inF);
                kpf_tmp->release();
                __int64 pos_plus = outF->tellp() - inF->tellg();
                for (int i = 0; i < index; ++i)
                    datKpf->setImagePos(
                        i, datKpf->getImagePosition(i) + pos_plus);
                datKpf->setImagePos(index, datLen + pos_plus);
                outF->seekp(0, std::ios::beg);
                datKpf->save(outF);
                char byte = 0;
                for (__int64 i = inF->tellg(); i < datLen; ++i)
                {
                    inF->read(&byte, 1);
                    outF->write(&byte, 1);
                }
                kpf->save(outF); // save image header
                LTDBBody* kpr
                    = new LTDBBody(dynamic_cast<LTDBHeader*>(kpf->getThis()));
                kpr->setImage(dynamic_cast<Image*>(bild->getThis()));
                kpr->save(f, outF); // save image
                kpf->release();
                kpr->release();
                inF->close();
                outF->close();
                delete inF;
                delete outF;
                FileRemove(dynamic_cast<Text*>(pfad->getThis()));
                FileRename(
                    (Text*)pf_tmp, dynamic_cast<Text*>(pfad->getThis()));
            }
        }
    }
    if (name) name->release();
    if (bild) bild->release();
    return warn;
}

RCArray<Text>* LTDBFile::zImageListe() // Lists all images in the file
{
    if (!datKpf) readData(0);
    if (datKpf) return datKpf->zImageListe();
    return 0;
}

// constant
Text* LTDBFile::getPfad() const // Returns the path to the file
{
    return dynamic_cast<Text*>(pfad->getThis());
}

int LTDBFile::getImageCount() const
{
    if (!datKpf) return 0;
    return datKpf->getBCount();
}

bool LTDBFile::isOpen() const // Checks if the file is open
{
    if (!pfad) return 0;
    return FileExists(dynamic_cast<Text*>(pfad->getThis()));
}
#ifdef WIN32
// LTDS File format
// Content of the LTDSPixel class from FileSystem.h
// Constructor
LTDSPixel::LTDSPixel(LTDSPixel* davor)
    : ReferenceCounter(),
      index(0),
      iA(0),
      miA(8),
      maxIndex(1),
      aender(0),
      aenderA(0),
      komp(0),
      alpha(0),
      davor(davor)
{}

// Destructor
LTDSPixel::~LTDSPixel()
{
    if (davor) davor->release();
}

// non-constant
// intended for loading
bool LTDSPixel::addBitZuColor(unsigned char bit)
{
    if (aenderA && iA != miA) // The bit belongs to alpha
    {
        alpha |= ((bit & Bits(1))) << (7 - komp - iA);
        ++iA;
    }
    else // The bit belongs to the next pixel
        return false;
    return true;
}

char LTDSPixel::addByte(char byte,
char begin) // returns end of pixel, -1 if not finished
{
    if (begin >= 8 || begin < 0) return -1;
    for (int i = begin; i < 8; ++i)
    {
        switch (index)
        {
        case 0:
            // The first bit of a pixel stores whether the
            // compression changed
            aender = ((byte >> (7 - i)) & Bits(1)) == 1;
            if (!aender) // If compression doesn't change, the values
                         // from the previous pixel are inherited
            {
                if (!davor) // The file is corrupted (the first pixel cannot
                            // inherit from the previous one)
                {
                    MessageBox(NULL,
                        "Error, the image file is corrupted",
                        "Error",
                        MB_ICONERROR);
                    exit(0);
                }
                aenderA = davor->getAEnderA();
                komp = davor->getKomp();
                miA -= komp;
                if (!aenderA) alpha = davor->getA();
                maxIndex += aenderA * (8 - komp); // Determine the length
                // of the pixel in bits. Each color has 8 bits by default,
                // compression can make it smaller
            }
            else
                maxIndex += 4; // Since the pixel doesn't inherit values from
                               // the previous one, it is 4 bits larger
            break;
        case 1:         // The second bit of a pixel stores either the
                        // compression type or already the color
            if (aender) // The bit belongs to the 4 compression bits
                aenderA = ((byte >> (7 - i)) & Bits(1)) == 1;
            else
            {
                if (!addBitZuColor(
                        byte >> (7 - i))) // The bit belongs to the color
                    return i;
            }
            break;
        case 2:         // The sixth bit of a pixel stores either the
                        // compression type or already the color
            if (aender) // The bit belongs to the 4 compression bits
                komp |= (unsigned char)((byte >> (7 - i)) & Bits(1)) << 2;
            else
            {
                if (!addBitZuColor(
                        byte >> (7 - i))) // The bit belongs to the color
                    return i;
            }
            break;
        case 3:         // The seventh bit of a pixel stores either the
                        // compression type or already the color
            if (aender) // The bit belongs to the 4 compression bits
                komp |= (unsigned char)((byte >> (7 - i)) & Bits(1)) << 1;
            else
            {
                if (!addBitZuColor(
                        byte >> (7 - i))) // The bit belongs to the color
                    return i;
            }
            break;
        case 4:         // The eighth bit of a pixel stores either the
                        // compression type or already the color
            if (aender) // The bit belongs to the 4 compression bits
            {
                komp |= (unsigned char)((byte >> (7 - i)) & Bits(1));
                // That was the last compression bit
                // Evaluate compression
                miA -= komp;
                if (!aenderA) alpha = davor->getA();
                maxIndex += aenderA * (8 - komp); // bit length of the pixel
            }
            else
            {
                if (!addBitZuColor(
                        byte >> (7 - i))) // The bit belongs to the color
                    return i;
            }
            break;
        default: // The remaining bits all store the color values of the pixel
            if (!addBitZuColor(byte >> (7 - i))) // The bit belongs to the color
                return i;
            break;
        }
        ++index;
        if (index >= maxIndex)
        {
            if (davor)
            {
                if (aenderA) alpha = davor->getA() + alpha;
                davor = (LTDSPixel*)davor->release();
            }
            return i + 1;
        }
    }
    return -1;
}

// intended for saving
void LTDSPixel::setAlpha(unsigned char alpha) // sets the color of the pixel
{
    this->alpha = alpha;
}

void LTDSPixel::Komp() // Compresses the pixel
{
    maxIndex = 1;
    if (!davor)
    { // This is the first pixel
        aender = 1;
        aenderA = 1;
        maxIndex += 4;
        miA = getBits(alpha);
    }
    else
    { // The difference to the previous pixel is stored
        miA = getBits(alpha - davor->getA());
        if (alpha != davor->getA())
            aenderA = 1;
        else
            aenderA = 0;
    } // Check if something changes
    if (!miA && aenderA) ++miA;
    komp = 8 - miA;
    maxIndex += aenderA * miA;
    if (davor)
    {
        if (aenderA != davor->getAEnderA() || komp != davor->getKomp())
        { // Something changes
            aender = 1;
            maxIndex += 4;
        }
        else
        { // Nothing changes
            aender = 0;
        }
    }
}

bool LTDSPixel::getNextColorBit(char& byte, int i)
{
    unsigned char AA = alpha;
    if (davor)
    {
        AA -= davor->getA();
    }
    if (aenderA && iA != miA) // The bit belongs to alpha
    {
        byte |= ((AA >> (7 - komp - iA)) & Bits(1)) << (7 - i);
        ++iA;
    }
    else // The pixel is already finished
        return false;
    return true;
}

char LTDSPixel::getNextByte(
    char& byte, int bbegin) // Returns the next bits, -1 if the pixel
                            // is not finished
{
    // bbegin specifies where to write in the byte variable
    // the function returns the end of the pixel in the byte variable
    // -1 means the pixel is not finished
    for (int i = bbegin; i < 8; ++i)
    {
        switch (index)
        {
        case 0: // The first bit of the pixel stores whether the
                // compression changes
            byte |= ((int)aender & Bits(1)) << (7 - i);
            break;
        case 1: // The second bit of the pixel stores either the color
                // or the compression
            if (aender) // Compression
                byte |= ((int)aenderA & Bits(1)) << (7 - i);
            else // Color
            {
                if (!getNextColorBit(byte, i)) return i;
            }
            break;
        case 2: // The second bit of the pixel stores either the color
                // or the compression
            if (aender) // Compression
                byte |= ((komp >> 2) & Bits(1)) << (7 - i);
            else // Color
            {
                if (!getNextColorBit(byte, i)) return i;
            }
            break;
        case 3: // The third bit of the pixel stores either the color
                // or the compression
            if (aender) // Compression
                byte |= ((komp >> 1) & Bits(1)) << (7 - i);
            else // Color
            {
                if (!getNextColorBit(byte, i)) return i;
            }
            break;
        case 4: // The fourth bit of the pixel stores either the color
                // or the compression
            if (aender) // Compression
                byte |= (komp & Bits(1)) << (7 - i);
            else // Color
            {
                if (!getNextColorBit(byte, i)) return i;
            }
            break;
        default: // The remaining bits store the color of the pixel
            if (!getNextColorBit(byte, i)) return i;
            break;
        }
        ++index;
        if (index >= maxIndex)
        {
            if (davor) davor = (LTDSPixel*)davor->release();
            return i + 1;
        }
    }
    return -1;
}

// constant
unsigned char LTDSPixel::getKomp() const // has the compression changed
{
    return komp;
}

bool LTDSPixel::getAEnderA()
    const // returns whether the alpha value changes
{
    return aenderA;
}

unsigned char LTDSPixel::getA() const // returns alpha
{
    return alpha;
}

// Content of the LTDSFileHeader class from FileSystem.h
// Constructor
LTDSFileHeader::LTDSFileHeader()
    : ReferenceCounter(),
      sganzahl(0),
      gr(0),
      pos(0)
{}

// Destructor
LTDSFileHeader::~LTDSFileHeader()
{
    delete[] gr;
    delete[] pos;
}

// non-constant
void LTDSFileHeader::load(std::ifstream* inF) // Loads from inF
{
    if (inF->good() && inF->is_open())
    {
        inF->read((char*)&sganzahl, 1);
        delete[] gr;
        delete[] pos;
        gr = new unsigned char[sganzahl + 1];
        pos = new int[sganzahl + 1];
        gr[sganzahl] = 0;
        pos[sganzahl] = 0;
        for (int i = 0; i < sganzahl; ++i)
        {
            inF->read((char*)&gr[i], 1);
            inF->read((char*)&pos[i], 4);
        }
    }
}

void LTDSFileHeader::addSG(char sg) // Add font size
{
    ++sganzahl;
    unsigned char* gr_tmp = gr;
    int* pos_tmp = pos;
    gr = new unsigned char[sganzahl + 1];
    pos = new int[sganzahl + 1];
    gr[sganzahl] = 0;
    pos[sganzahl] = 0;
    if (sganzahl - 1 > 0)
    {
        memcpy(gr, gr_tmp, 1 * (sganzahl - 1));
        memcpy(pos, pos_tmp, 4 * (sganzahl - 1));
    }
    delete[] gr_tmp;
    delete[] pos_tmp;
    pos[sganzahl - 1] = 0;
    gr[sganzahl - 1] = sg;
}

void LTDSFileHeader::removeSG(char sg) // Remove font size
{
    bool hatsg = 0;
    int sgpos = 0;
    for (int i = 0; i < sganzahl; ++i)
    {
        hatsg = gr[i] == sg;
        sgpos = i;
        if (hatsg) break;
    }
    if (hatsg)
    {
        --sganzahl;
        unsigned char* gr_tmp = gr;
        int* pos_tmp = pos;
        gr = new unsigned char[sganzahl + 1];
        pos = new int[sganzahl + 1];
        gr[sganzahl] = 0;
        pos[sganzahl] = 0;
        for (int i = 0; i < sgpos; ++i)
        {
            gr[i] = gr_tmp[i];
            pos[i] = pos_tmp[i];
        }
        for (int i = sgpos + 1; i < sganzahl; ++i)
        {
            gr[i - 1] = gr_tmp[i];
            pos[i - 1] = pos_tmp[i];
        }
        delete[] gr_tmp;
        delete[] pos_tmp;
    }
}

// constant
void LTDSFileHeader::save(std::ofstream* outF) const // Saves to outF
{
    if (outF->is_open() && outF->good())
    {
        outF->write((char*)&sganzahl, 1);
        for (int i = 0; i < sganzahl; ++i)
        {
            outF->write((char*)&gr[i], 1);
            outF->write((char*)&pos[i], 4);
        }
    }
}

unsigned char* LTDSFileHeader::getFontSizeList()
const // returns a list of stored font sizes
{
    return gr;
}

int* LTDSFileHeader::getPositionList()
const // returns a position list of stored font sizes
{
    return pos;
}

int LTDSFileHeader::getFontSizeCount()
const // returns the number of stored font sizes
{
    return sganzahl;
}

// Content of the LTDSFontHeader class from FileSystem.h
// Constructor
LTDSFontHeader::LTDSFontHeader()
    : ReferenceCounter(),
      fontSize(0),
      zeichen(0),
      pos(0),
      zeichenAnzahl(0)
{}

// Destructor
LTDSFontHeader::~LTDSFontHeader()
{
    delete[] pos;
    delete[] zeichen;
}

// non-constant
void LTDSFontHeader::load(std::ifstream* inF) // loads from inF
{
    if (inF->good() && inF->is_open())
    {
        inF->read((char*)&fontSize, 1);
        inF->read((char*)&zeichenAnzahl, 1);
        delete[] pos;
        delete[] zeichen;
        zeichen = new unsigned char[zeichenAnzahl];
        pos = new int[zeichenAnzahl + 1];
        for (int i = 0; i < zeichenAnzahl; ++i)
        {
            inF->read((char*)&zeichen[i], 1);
            inF->read((char*)&pos[i], 4);
        }
        pos[zeichenAnzahl] = 0;
    }
}

void LTDSFontHeader::setFontSize(
unsigned char gr) // set font size
{
    fontSize = gr;
}

void LTDSFontHeader::setCharAlphabet(
Alphabet* alphabet) // sets the characters from alphabet
{
    int count = 0;
    for (int i = 0; i < 256; ++i)
    {
        Character* zeich = alphabet->zCharacter(i);
        if (zeich) ++count;
    }
    delete[] zeichen;
    delete[] pos;
    zeichen = new unsigned char[count];
    pos = new int[count + 1];
    pos[count] = 0;
    zeichenAnzahl = count;
    count = 0;
    for (int i = 0; i < 256; ++i)
    {
        Character* zeich = alphabet->getCharacter(i);
        if (zeich)
        {
            zeichen[count] = i;
            pos[count] = 0;
            ++count;
            zeich->release();
        }
    }
    fontSize = alphabet->getFontSize();
    alphabet->release();
}

void LTDSFontHeader::addChar(unsigned char zeichen) // Add character
{
    ++zeichenAnzahl;
    unsigned char* zeichen_tmp = this->zeichen;
    int* pos_tmp = pos;
    this->zeichen = new unsigned char[zeichenAnzahl];
    pos = new int[zeichenAnzahl + 1];
    if (zeichenAnzahl - 1 > 0)
    {
        memcpy(this->zeichen, zeichen_tmp, 1 * (zeichenAnzahl - 1));
        memcpy(pos, pos_tmp, 4 * (zeichenAnzahl - 1));
    }
    delete[] zeichen_tmp;
    delete[] pos_tmp;
    this->zeichen[zeichenAnzahl - 1] = zeichen;
    pos[zeichenAnzahl - 1] = 0;
    pos[zeichenAnzahl] = 0;
}

void LTDSFontHeader::removeChar(unsigned char zeich) // Remove character
{
    bool hatZ = 0;
    int zPos = 0;
    for (int i = 0; i < zeichenAnzahl; ++i)
    {
        hatZ = zeichen[i] == zeich;
        zPos = i;
        if (hatZ) break;
    }
    if (hatZ)
    {
        --zeichenAnzahl;
        unsigned char* zeichen_tmp = zeichen;
        int* pos_tmp = pos;
        zeichen = new unsigned char[zeichenAnzahl];
        pos = new int[zeichenAnzahl + 1];
        for (int i = 0; i < zPos; ++i)
        {
            zeichen[i] = zeichen_tmp[i];
            pos[i] = pos_tmp[i];
        }
        for (int i = zPos + 1; i <= zeichenAnzahl; ++i)
        {
            zeichen[i - 1] = zeichen_tmp[i];
            pos[i - 1] = pos_tmp[i];
        }
        pos[zeichenAnzahl] = 0;
        delete[] zeichen_tmp;
        delete[] pos_tmp;
    }
}

// constant
void LTDSFontHeader::save(
std::ofstream* outF) const // saves to outF
{
    if (outF->good() && outF->is_open())
    {
        outF->write((char*)&fontSize, 1);
        outF->write((char*)&zeichenAnzahl, 1);
        for (int i = 0; i < zeichenAnzahl; ++i)
        {
            outF->write((char*)&zeichen[i], 1);
            outF->write((char*)&pos[i], 4);
        }
    }
}

unsigned char
LTDSFontHeader::getFontSize() const // returns the font size
{
    return fontSize;
}

unsigned char
LTDSFontHeader::getCharCount() const // returns the character count
{
    return zeichenAnzahl;
}

int* LTDSFontHeader::getPositionen()
const // returns the character positions
{
    return pos;
}

unsigned char* LTDSFontHeader::getChar() const // returns the characters
{
    return zeichen;
}

// Content of the LTDSCharacterHeader class from FileSystem.h
// Constructor
LTDSCharacterHeader::LTDSCharacterHeader()
    : ReferenceCounter(),
      zeichen(0),
      size(0, 0)
{}

// non-constant
void LTDSCharacterHeader::load(std::ifstream* inF) // loads from inF
{
    if (inF->good() && inF->is_open())
    {
        inF->read((char*)&zeichen, 1);
        inF->read((char*)&size.x, 1);
        inF->read((char*)&size.y, 1);
    }
}

void LTDSCharacterHeader::init(unsigned char zeichen,
const Point& groesse) // initialization (for saving)
{
    this->zeichen = zeichen;
    this->size = groesse;
}

void LTDSCharacterHeader::init(unsigned char zeichen, int br, int hoe)
{
    this->zeichen = zeichen;
    size.x = br, size.y = hoe;
}

// constant
void LTDSCharacterHeader::save(
std::ofstream* outF) const // saves to outF
{
    if (outF->good() && outF->is_open())
    {
        outF->write((char*)&zeichen, 1);
        outF->write((char*)&size.x, 1);
        outF->write((char*)&size.y, 1);
    }
}

unsigned char LTDSCharacterHeader::getChar() const // returns the character
{
    return zeichen;
}

int LTDSCharacterHeader::getWidth() const // returns the width
{
    return size.x;
}

int LTDSCharacterHeader::getHeight() const // returns the height
{
    return size.y;
}

const Point& LTDSCharacterHeader::getSize() const // returns the size
{
    return size;
}

// Content of the LTDSCharacterBody class from FileSystem.h
// Constructor
LTDSCharacterBody::LTDSCharacterBody(LTDSCharacterHeader* kopf)
    : ReferenceCounter(),
      size(kopf->getSize()),
      zeichen(kopf->getChar()),
      buchstabe(new Character())
{
    buchstabe->NewCharacter(size);
    kopf->release();
}

// Destructor
LTDSCharacterBody::~LTDSCharacterBody()
{
    if (buchstabe) buchstabe->release();
}

// non-constant
void LTDSCharacterBody::setCharacter(
    Character* zeichen) // sets the character
{
    if (buchstabe) buchstabe->release();
    buchstabe = zeichen;
}

void LTDSCharacterBody::load(std::ifstream* inF) // Loads from inF
{
    if (inF->good() && inF->is_open())
    {
        LTDSPixel* vorher = 0;
        LTDSPixel* jetzt = new LTDSPixel(vorher);
        char byte = 0;
        int beg = 0;
        int ende = -1;
        for (int i = 0; i < size.x * size.y; ++i)
        {
            if (!jetzt) // if it is not the first pixel
                jetzt = new LTDSPixel(
                    dynamic_cast<LTDSPixel*>(vorher->getThis()));
            int ende = -1;
            while (ende < 0) // load pixel
            {
                if (beg == 0) inF->read(&byte, 1);
                ende = jetzt->addByte(byte, beg); // evaluate byte
                beg = 0;
            }
            beg = ende;
            if (beg == 8) beg = 0;
            if (buchstabe) buchstabe->setPixel(i, jetzt->getA());
            if (vorher) vorher = (LTDSPixel*)vorher->release();
            vorher = dynamic_cast<LTDSPixel*>(jetzt->getThis());
            jetzt = (LTDSPixel*)jetzt->release();
        }
        if (vorher) vorher->release();
        if (jetzt) jetzt->release();
    }
}

// constant
void LTDSCharacterBody::save(
std::ofstream* outF) const // saves to outF
{
    if (outF->good() && outF->is_open())
    {
        LTDSPixel* vorher = 0; // Last saved pixel
        LTDSPixel* jetzt
            = new LTDSPixel(0); // The pixel currently being saved
        int begin = 0,
            ende = 0;  // pixel start, end position in the byte variable
        char byte = 0; // The next byte of the file
        bool w = 0;
        unsigned char* alphaBuff = buchstabe->getBuff();
        for (int i = 0; i < size.x * size.y; ++i) // for each pixel
        {
            if (!jetzt) // if it is not the first pixel
                jetzt = new LTDSPixel(
                    dynamic_cast<LTDSPixel*>(vorher->getThis()));
            jetzt->setAlpha(alphaBuff[i]); // set pixel color
            jetzt->Komp();                 // compress pixel
            ende = -1;
            while (ende < 0) // fill byte
            {
                ende = jetzt->getNextByte(byte, begin);
                begin = 0;
                w = 0;
                if (ende == -1 || ende == 8) // save byte
                {
                    outF->write(&byte, 1);
                    w = 1;
                    byte = 0;
                }
            } // pixel finished
            begin = ende;
            if (begin == 8) begin = 0;
            if (vorher) vorher->release();
            vorher = dynamic_cast<LTDSPixel*>(
                jetzt->getThis()); // jetzt becomes vorher
            jetzt = (LTDSPixel*)jetzt->release();
        }
        if (vorher) vorher = (LTDSPixel*)vorher->release();
        if (!w)
        {
            outF->write(&byte, 1); // save the last byte
        }
        outF->flush(); // flush file stream
    }
}

Character*
LTDSCharacterBody::getCharacter() const // returns the character
{
    return dynamic_cast<Character*>(buchstabe->getThis());
}

unsigned char
LTDSCharacterBody::getChar() const // returns the character
{
    return zeichen;
}

// Content of the LTDSFile class from FileSystem.h
// Constructor
LTDSFile::LTDSFile()
    : ReferenceCounter(),
      pfad(new Text()),
      dateiKopf(0)
{}

// Destructor
LTDSFile::~LTDSFile()
{
    if (dateiKopf) dateiKopf->release();
    pfad->release();
}

// non-constant
void LTDSFile::setPfad(Text* txt) // sets the path to the file
{
    if (dateiKopf) dateiKopf = (LTDSFileHeader*)dateiKopf->release();
    pfad->setText(txt->getText());
    txt->release();
}

void LTDSFile::readData() // reads the file header
{
    if (!FileExists(dynamic_cast<Text*>(pfad->getThis()))) return;
    if (dateiKopf) dateiKopf->release();
    dateiKopf = new LTDSFileHeader();
    std::ifstream* inF = new std::ifstream(pfad->getText(), std::ios::binary);
    dateiKopf->load(inF);
    inF->close();
    delete inF;
}

void LTDSFile::addFontSize(
    Alphabet* alphabet) // adds a font size
{
    if (!FileExists(dynamic_cast<Text*>(
            pfad->getThis()))) // check if the file exists
        return;
    if (!dateiKopf) // check if the file header has been read
        readData();
    int sgroesse
        = alphabet
              ->getFontSize(); // font size to be added
    unsigned char* sglist
        = dateiKopf->getFontSizeList(); // list of already existing
                                              // font sizes
    unsigned char sganzahl
        = dateiKopf->getFontSizeCount(); // number of already
                                                // existing font sizes
    for (int i = 0; i < sganzahl;
        ++i) // check if the font size already exists
    {
        if (sglist[i] == sgroesse)
        {
            alphabet->release();
            return;
        }
    }
    dateiKopf->addSG(sgroesse); // add font size to file header
    int* sgPosList
        = dateiKopf
              ->getPositionList(); // list of font size positions
    sglist = dateiKopf->getFontSizeList(); // list of already
                                                 // existing font sizes
    std::ifstream* inF
        = new std::ifstream(pfad->getText(), std::ios::binary); // old file
    pfad->append("0");
    std::ofstream* outF
        = new std::ofstream(pfad->getText(), std::ios::binary); // new file
    dateiKopf->save(outF); // save file header to new file
    inF->seekg(1 + 5 * sganzahl,
        std::ios::beg); // position of the first font size in the old file
    for (int i = 0; i < sganzahl;
        ++i) // update character positions of all font sizes
    {
        LTDSFontHeader* sgKpf_tmp
            = new LTDSFontHeader(); // font size header
        sgKpf_tmp->load(inF);       // load from old file
        int* zeichP_tmp
            = sgKpf_tmp
                  ->getPositionen(); // character positions of the font size
        unsigned char zeichA_tmp
            = sgKpf_tmp
                  ->getCharCount(); // number of characters in the font size
        for (int i1 = 0; i1 < zeichA_tmp; ++i1)
            zeichP_tmp[i1] += 5; // update character positions
        sgKpf_tmp->save(
            outF); // save font size header to new file
        int beginByte
            = (int)inF->tellg(); // copy remaining bytes until the next
                                 // font size to new file
        int endByte = sgPosList[i + 1];
        if (!endByte)
        {
            inF->seekg(0, std::ios::end);
            endByte = (int)inF->tellg();
            inF->seekg(beginByte, std::ios::beg);
        }
        char byte;
        for (int i1 = beginByte; i1 < endByte; ++i1) // copy operation
        {
            inF->read(&byte, 1);
            outF->write(&byte, 1);
        }
        sgKpf_tmp->release();
    }
    inF->close(); // close old file
    sgPosList[sganzahl] = (int)outF->tellp();
    outF->seekp(0, std::ios::beg);
    for (int i = 0; i < sganzahl; ++i) // update positions in file header
        sgPosList[i] += 5;
    dateiKopf->save(outF); // save updated file header
    outF->seekp(sgPosList[sganzahl], std::ios::beg);
    LTDSFontHeader* sgkopf
        = new LTDSFontHeader(); // header of the new font size
    sgkopf->setCharAlphabet(dynamic_cast<Alphabet*>(
        alphabet->getThis())); // initialize font size header
    sgkopf->save(outF);   // save font size header
    int* BuchstabenPosList
        = sgkopf->getPositionen(); // positions of the different characters
                                   // in the file (still 0)
    int count = 0;
    for (int i = 0; i < 256; ++i)
    {
        Character* zeich = alphabet->getCharacter(i);
        if (zeich)
        {
            BuchstabenPosList[count]
                = (int)outF->tellp(); // set character position
            LTDSCharacterHeader* zeichKpf
                = new LTDSCharacterHeader(); // character header
            zeichKpf->init(i, zeich->getWidth(), zeich->getHeight());
            zeichKpf->save(outF); // save character header
            LTDSCharacterBody* zeichKoerp
                = new LTDSCharacterBody(dynamic_cast<LTDSCharacterHeader*>(
                    zeichKpf->getThis())); // character body
            zeichKpf->release();
            zeichKoerp->setCharacter(
                dynamic_cast<Character*>(zeich->getThis()));
            zeichKoerp->save(outF); // save character body
            zeich->release();
            ++count;
        }
    }
    outF->seekp(sgPosList[sganzahl], std::ios::beg);
    sgkopf->save(outF); // save updated font size header
    outF->close();
    Text* pfad2 = new Text();
    pfad2->setText(pfad->getText());
    pfad->remove(pfad->getLength() - 1, pfad->getLength());
    FileRemove(dynamic_cast<Text*>(pfad->getThis())); // delete old file
    FileRename(dynamic_cast<Text*>(pfad2->getThis()),
        dynamic_cast<Text*>(
            pfad->getThis())); // rename new file to old
    pfad2->release();          // free memory
    sgkopf->release();
    delete inF;
    delete outF;
    alphabet->release();
}

void LTDSFile::addCharacter(int gr,
    Character* zeich,
    unsigned char zeichen) // Adds a character to a font size
{
    if (!FileExists(
            dynamic_cast<Text*>(pfad->getThis()))) // check if file exists
    {
        zeich->release();
        return;
    }
    if (!dateiKopf) // check if the file header was loaded
        readData();
    unsigned char* sgList
        = dateiKopf->getFontSizeList(); // list of font sizes from
                                              // the file
    int* sgPosList = dateiKopf->getPositionList(); // list of font size
                                                   // positions from file
    unsigned char sgAnzahl
        = dateiKopf->getFontSizeCount(); // number of font sizes
                                                // from the file
    int sgNum = -1;
    for (int i = 0; i < sgAnzahl;
        ++i) // find the position of the correct font size
    {
        if (sgList[i] == gr)
        {
            sgNum = i;
            break;
        }
    }
    std::ifstream* inF
        = new std::ifstream(pfad->getText(), std::ios::binary); // old file
    pfad->append("0");
    std::ofstream* outF
        = new std::ofstream(pfad->getText(), std::ios::binary); // new file
    inF->seekg(1 + 5 * sgAnzahl, std::ios::beg);
    if (sgNum
        == -1) // The font size does not exist yet and will be created
    {
        dateiKopf->addSG(gr); // add font size to file header
        sgPosList = dateiKopf->getPositionList();
        sgList = dateiKopf->getFontSizeList();
        dateiKopf->save(outF); // save file header
        inF->seekg(1 + 5 * sgAnzahl,
            std::ios::beg); // position of the first
                            // font size in the old file
        for (int i = 0; i < sgAnzahl;
            ++i) // update character positions of all font sizes
        {
            LTDSFontHeader* sgKpf_tmp
                = new LTDSFontHeader(); // font size header
            sgKpf_tmp->load(inF);       // load from old file
            int* zeichP_tmp
                = sgKpf_tmp
                      ->getPositionen(); // character positions of the font size
            unsigned char zeichA_tmp
                = sgKpf_tmp->getCharCount(); // number of characters in
                                                 // the font size
            for (int i1 = 0; i1 < zeichA_tmp; ++i1)
                zeichP_tmp[i1] += 5; // update character positions
            sgKpf_tmp->save(
                outF); // save font size header to new file
            int beginByte
                = (int)inF->tellg(); // copy remaining bytes until the next
                                     // font size to new file
            int endByte = sgPosList[i + 1];
            if (i + 1 >= sgAnzahl)
            {
                inF->seekg(0, std::ios::end);
                endByte = (int)inF->tellg();
                inF->seekg(beginByte, std::ios::beg);
            }
            char byte;
            for (int i1 = beginByte; i1 < endByte; ++i1) // copy operation
            {
                inF->read(&byte, 1);
                outF->write(&byte, 1);
            }
            sgKpf_tmp->release();
        }
        sgPosList[sgAnzahl] = (int)outF->tellp();
        outF->seekp(0, std::ios::beg);
        for (int i = 0; i < sgAnzahl;
            ++i) // update positions in file header
            sgPosList[i] += 5;
        dateiKopf->save(outF); // save updated file header
        outF->seekp(sgPosList[sgAnzahl], std::ios::beg);
        LTDSFontHeader* sgKpf
            = new LTDSFontHeader(); // initialize font size header
        sgKpf->setFontSize(gr);
        sgKpf->addChar(zeichen);
        sgKpf->getPositionen()[0] = (int)outF->tellp() + 7;
        sgKpf->save(outF); // save font size header
        sgKpf->release();
        LTDSCharacterHeader* zeichKpf
            = new LTDSCharacterHeader(); // character header
        zeichKpf->init(zeichen, zeich->getSize());
        zeichKpf->save(outF); // save character header
        LTDSCharacterBody* zeichKoerp
            = new LTDSCharacterBody(dynamic_cast<LTDSCharacterHeader*>(
                zeichKpf->getThis())); // character body
        zeichKpf->release();
        zeichKoerp->setCharacter(dynamic_cast<Character*>(zeich->getThis()));
        zeichKoerp->save(outF); // save character body
        zeichKoerp->release();
    }
    else
    {
        dateiKopf->save(outF); // save file header
        int beginByte
            = 1 + 5 * sgAnzahl; // copy remaining bytes until the next
                                // font size to new file
        int endByte = sgPosList[sgNum];
        char byte;
        for (int i1 = beginByte; i1 < endByte;
            ++i1) // copy operation up to the specified size
        {
            inF->read(&byte, 1);
            outF->write(&byte, 1);
        }
        LTDSFontHeader* sgKpf = new LTDSFontHeader(); // font size header
        sgKpf->load(inF);
        for (int i = 0; i < sgKpf->getCharCount(); ++i)
            sgKpf->getPositionen()[i] += 5;
        sgKpf->addChar(zeichen);
        int indexPlus = 5;
        int zeichenPos = sgPosList[sgNum + 1]; // position of the new character
        if (sgNum + 1 >= sgAnzahl)
        {
            int tmp = (int)inF->tellg();
            inF->seekg(0, std::ios::end);
            zeichenPos = (int)inF->tellg();
            inF->seekg(tmp, std::ios::beg);
        }
        zeichenPos += indexPlus;
        sgKpf->getPositionen()[sgKpf->getCharCount() - 1] = zeichenPos;
        sgKpf->save(outF); // save font size header
        sgKpf->release();
        for (int i = (int)inF->tellg() + indexPlus; i < zeichenPos;
            ++i) // copy operation up to the character start
        {
            inF->read(&byte, 1);
            outF->write(&byte, 1);
        }
        LTDSCharacterHeader* zeichKpf = new LTDSCharacterHeader(); // character header
        zeichKpf->init(zeichen, zeich->getSize());
        zeichKpf->save(outF); // save character header
        LTDSCharacterBody* zeichKoerp
            = new LTDSCharacterBody(dynamic_cast<LTDSCharacterHeader*>(
                zeichKpf->getThis())); // character body
        zeichKpf->release();
        zeichKoerp->setCharacter(dynamic_cast<Character*>(zeich->getThis()));
        zeichKoerp->save(outF); // save character body
        zeichKoerp->release();
        int nowPos = (int)outF->tellp();
        indexPlus += nowPos - zeichenPos;
        for (int i = sgNum + 1; i < sgAnzahl; ++i) // update file header
            sgPosList[i] += indexPlus;
        outF->seekp(0, std::ios::beg);
        dateiKopf->save(outF); // save file header
        outF->seekp(nowPos, std::ios::beg);
        for (int i = sgNum + 1; i < sgAnzahl;
            ++i) // update remaining font sizes
        {
            LTDSFontHeader* sgKpf_tmp
                = new LTDSFontHeader(); // font size header
            sgKpf_tmp->load(inF);       // load from old file
            int* zeichP_tmp
                = sgKpf_tmp
                      ->getPositionen(); // character positions of the font size
            unsigned char zeichA_tmp
                = sgKpf_tmp->getCharCount(); // number of characters in
                                                 // the font size
            for (int i1 = 0; i1 < zeichA_tmp; ++i1)
                zeichP_tmp[i1]
                    += indexPlus; // update character positions
            sgKpf_tmp->save(
                outF); // save font size header to new file
            int beginByte
                = (int)inF->tellg(); // copy remaining bytes until the next
                                     // font size to new file
            int endByte = sgPosList[i + 1];
            if (i + 1 >= sgAnzahl)
            {
                inF->seekg(0, std::ios::end);
                endByte = (int)inF->tellg();
                inF->seekg(beginByte, std::ios::beg);
            }
            char byte;
            for (int i1 = beginByte; i1 < endByte; ++i1) // copy operation
            {
                inF->read(&byte, 1);
                outF->write(&byte, 1);
            }
            sgKpf_tmp->release();
        }
    }
    inF->close();
    outF->close();
    Text* pfad2 = new Text(pfad->getText());
    pfad->remove(pfad->getLength() - 1, pfad->getLength());
    FileRemove(dynamic_cast<Text*>(pfad->getThis())); // delete old file
    FileRename(dynamic_cast<Text*>(pfad2->getThis()),
        dynamic_cast<Text*>(pfad->getThis())); // rename new file to old
    pfad2->release();                          // free memory
    delete inF;
    delete outF;
    zeich->release();
}

void LTDSFile::deleteFontSize(
    int gr) // Deletes a font size from the file
{
    if (!FileExists(dynamic_cast<Text*>(
            pfad->getThis()))) // check if file exists
        return;
    if (!dateiKopf) // check if the file header was loaded
        readData();
    unsigned char* sgList
        = dateiKopf->getFontSizeList(); // list of font sizes
    unsigned char sgAnzahl
        = dateiKopf->getFontSizeCount(); // number of font sizes
    int sgNum = -1;
    for (int i = 0; i < sgAnzahl; ++i) // search for font size to delete
    {
        if (sgList[i] == gr)
        {
            sgNum = i;
            break;
        }
    }
    if (sgNum == -1) // the font size is not present
        return;
    int* sgPosList
        = dateiKopf
              ->getPositionList(); // list of font size positions
    std::ifstream* inF
        = new std::ifstream(pfad->getText(), std::ios::binary); // old file
    pfad->append("0");
    std::ofstream* outF
        = new std::ofstream(pfad->getText(), std::ios::binary); // new file
    outF->seekp(1 + 5 * (sgAnzahl - 1), std::ios::beg);
    inF->seekg(1 + 5 * sgAnzahl, std::ios::beg);
    for (int i = 0; i < sgNum; ++i) // update font sizes before the one
                                    // being deleted
    {
        LTDSFontHeader* sgKpf_tmp
            = new LTDSFontHeader(); // font size header
        sgKpf_tmp->load(inF);       // load font size header
        int* zeichPosLTmp = sgKpf_tmp->getPositionen(); // character positions
        unsigned char zeichATmp
            = sgKpf_tmp->getCharCount(); // character count
        for (int i1 = 0; i1 < zeichATmp;
            ++i1) // move character positions back by 5 bytes
            zeichPosLTmp[i1] -= 5;
        sgKpf_tmp->save(outF); // save to new file
        char byte = 0;
        for (int i1 = (int)inF->tellg(); i1 < sgPosList[i + 1];
            ++i1) // copy the character body
        {
            inF->read(&byte, 1);
            outF->write(&byte, 1);
        }
        sgKpf_tmp->release();
    }
    int indexMinus = 5 + sgPosList[sgNum + 1] - (int)inF->tellg();
    inF->seekg(sgPosList[sgNum + 1], std::ios::beg);
    for (int i = sgNum + 1; i < sgAnzahl;
        ++i) // font sizes after the one being deleted
    {
        LTDSFontHeader* sgKpf_tmp
            = new LTDSFontHeader(); // font size header
        sgKpf_tmp->load(inF);       // load font size header
        int* zeichPosLTmp = sgKpf_tmp->getPositionen(); // character positions
        unsigned char zeichATmp
            = sgKpf_tmp->getCharCount(); // character count
        for (int i1 = 0; i1 < zeichATmp;
            ++i1) // update character positions
            zeichPosLTmp[i1] -= indexMinus;
        sgKpf_tmp->save(outF); // save to new file
        char byte = 0;
        int BeginByte = (int)inF->tellg();
        int EndByte = sgPosList[i + 1];
        if (!EndByte)
        {
            inF->seekg(0, std::ios::end);
            EndByte = (int)inF->tellg();
            inF->seekg(BeginByte, std::ios::beg);
        }
        for (int i1 = BeginByte; i1 < EndByte;
            ++i1) // copy the character body
        {
            inF->read(&byte, 1);
            outF->write(&byte, 1);
        }
    }
    for (int i = 0; i < sgNum; ++i) // update file header
        sgPosList[i] -= 5;
    for (int i = sgNum + 1; i < sgAnzahl; ++i)
        sgPosList[i] -= indexMinus;
    dateiKopf->removeSG(gr);
    outF->seekp(0, std::ios::beg);
    dateiKopf->save(outF); // save file header
    inF->close();
    outF->close();
    Text* pfad2 = new Text(pfad->getText());
    pfad->remove(pfad->getLength() - 1, pfad->getLength());
    FileRemove(dynamic_cast<Text*>(pfad->getThis())); // delete old file
    FileRename(dynamic_cast<Text*>(pfad2->getThis()),
        dynamic_cast<Text*>(pfad->getThis())); // rename new file to old
    pfad2->release();
    delete inF;
    delete outF;
}

void LTDSFile::deleteCharacter(
    int gr, unsigned char zeichen) // Deletes a character from the file
{
    if (!FileExists(dynamic_cast<Text*>(
            pfad->getThis()))) // check if the file exists
        return;
    if (!dateiKopf) // check if the file header was read
        readData();
    unsigned char* sgList
        = dateiKopf->getFontSizeList(); // list of font sizes
    unsigned char sgAnzahl
        = dateiKopf->getFontSizeCount(); // number of font sizes
    int* sgPosList
        = dateiKopf
              ->getPositionList(); // list of font size positions
    int sgNum = -1;
    for (int i = 0; i < sgAnzahl; ++i) // search for font size
    {
        if (sgList[i] == gr)
        {
            sgNum = i;
            break;
        }
    }
    if (sgNum == -1) // font size not found
        return;
    std::ifstream* inF
        = new std::ifstream(pfad->getText(), std::ios::binary); // old file
    pfad->append("0");
    std::ofstream* outF
        = new std::ofstream(pfad->getText(), std::ios::binary); // new file
    int indexMinus = 0;
    inF->seekg(1 + 5 * sgAnzahl, std::ios::beg);
    dateiKopf->save(outF); // save file header
    for (int i = 0; i < sgAnzahl; ++i)
    {
        LTDSFontHeader* sgKopf = new LTDSFontHeader(); // font header
        sgKopf->load(inF);                              // load font header
        unsigned char sgZeichAnzahl
            = sgKopf->getCharCount();                    // character count
        unsigned char* sgZeichenList = sgKopf->getChar(); // character list
        int* sgZPosList = sgKopf->getPositionen();           // position list
        if (i == sgNum) // character is in this font size
        {
            int sgZNum = -1;
            for (int i1 = 0; i1 < sgZeichAnzahl; ++i1) // search for character
            {
                if (sgZeichenList[i1] == zeichen)
                {
                    sgZNum = i1;
                    break;
                }
            }
            if (sgZNum == -1) // character not found
            {
                sgKopf->release();
                inF->close();
                outF->close();
                delete inF;
                delete outF;
                FileRemove(dynamic_cast<Text*>(pfad->getThis()));
                pfad->remove(pfad->getLength() - 1, pfad->getLength());
                return; // abort
            }
            outF->seekp(2 + 5 * (sgZeichAnzahl - 1), std::ios::cur);
            indexMinus += 5;
            for (int i1 = 0; i1 < sgZNum;
                ++i1) // characters before the one being deleted
            {
                char byte = 0;
                for (int i2 = sgZPosList[i1]; i2 < sgZPosList[i1 + 1];
                    ++i2) // copy
                {
                    inF->read(&byte, 1);
                    outF->write(&byte, 1);
                }
                sgZPosList[i1]
                    -= indexMinus; // update font size header
            }
            if (!sgZPosList[sgZNum + 1])
            {
                int endByte = sgPosList[i + 1];
                if (!endByte)
                {
                    int beginByte = (int)inF->tellg();
                    inF->seekg(0, std::ios::end);
                    endByte = (int)inF->tellg();
                    inF->seekg(beginByte, std::ios::beg);
                }
                indexMinus += endByte - sgZPosList[sgZNum];
            }
            else
                indexMinus += sgZPosList[sgZNum + 1] - sgZPosList[sgZNum];
            if (sgZNum + 1 < sgZeichAnzahl)
                inF->seekg(sgZPosList[sgZNum + 1], std::ios::beg);
            for (int i1 = sgZNum + 1; i1 < sgZeichAnzahl;
                ++i1) // characters after the deleted character
            {
                int beginByte = (int)inF->tellg();
                int endByte = sgZPosList[i1 + 1];
                if (!endByte)
                {
                    inF->seekg(0, std::ios::end);
                    endByte = (int)inF->tellg();
                    inF->seekg(beginByte, std::ios::beg);
                }
                char byte = 0;
                for (int i2 = beginByte; i2 < endByte; ++i2) // copy
                {
                    inF->read(&byte, 1);
                    outF->write(&byte, 1);
                }
                sgZPosList[i1]
                    -= indexMinus; // update font size header
            }
            sgKopf->removeChar(zeichen);
        }
        else
        {
            for (int i1 = 0; i1 < sgZeichAnzahl;
                ++i1) // update font size header
                sgZPosList[i] -= indexMinus;
            sgKopf->save(outF); // save font size header
            int beginByte = (int)inF->tellg();
            int endByte = sgPosList[i + 1];
            if (!endByte)
            {
                inF->seekg(0, std::ios::end);
                endByte = (int)inF->tellg();
                inF->seekg(beginByte, std::ios::beg);
            }
            char byte;
            for (int i1 = beginByte; i1 < endByte; ++i1) // copy
            {
                inF->read(&byte, 1);
                outF->write(&byte, 1);
            }
            sgPosList[i] -= indexMinus;
        }
        outF->seekp(sgPosList[i], std::ios::beg);
        sgKopf->save(outF); // save font size header
        outF->seekp(sgPosList[i + 1], std::ios::beg);
        sgKopf->release();
    }
    inF->close();
    outF->close();
    Text* pfad2 = new Text(pfad->getText());
    pfad->remove(pfad->getLength() - 1, pfad->getLength());
    FileRemove(dynamic_cast<Text*>(pfad->getThis())); // delete old file
    FileRename(dynamic_cast<Text*>(pfad2->getThis()),
        dynamic_cast<Text*>(
            pfad->getThis())); // rename new file to old
    pfad2->release();          // free memory
    delete inF;
    delete outF;
}

void LTDSFile::deleteFile() // Deletes the entire file
{
    if (!FileExists(dynamic_cast<Text*>(pfad->getThis()))) return;
    if (!dateiKopf) readData();
    FileRemove(dynamic_cast<Text*>(pfad->getThis()));
}

void LTDSFile::createFile() // creates the file
{
    FilePathCreate(dynamic_cast<Text*>(pfad->getThis()));
    if (dateiKopf) dateiKopf->release();
    dateiKopf = new LTDSFileHeader();
    std::ofstream* outF = new std::ofstream(pfad->getText(), std::ios::binary);
    dateiKopf->save(outF);
    outF->close();
    delete outF;
}

void LTDSFile::saveFont(
Font* font) // Saves the provided font
{
    if (!FileExists(dynamic_cast<Text*>(pfad->getThis())))
    {
        font->release();
        return;
    }
    deleteFile();
    if (dateiKopf) dateiKopf->release();
    dateiKopf = new LTDSFileHeader();
    for (int i = 0; i < 256; ++i)
    {
        Alphabet* alp = font->getAlphabet((unsigned char)i);
        if (alp)
        {
            dateiKopf->addSG((char)alp->getFontSize());
            alp->release();
        }
    }
    std::ofstream* outF = new std::ofstream(pfad->getText(), std::ios::binary);
    dateiKopf->save(outF);
    for (int i = 0; i < 256; ++i)
    {
        Alphabet* alp = font->getAlphabet((unsigned char)i);
        if (alp)
        {
            dateiKopf->getPositionList()[i] = (int)outF->tellp();
            LTDSFontHeader* sgKpf = new LTDSFontHeader();
            sgKpf->setCharAlphabet(dynamic_cast<Alphabet*>(alp->getThis()));
            sgKpf->save(outF);
            for (int i1 = 0; i1 < sgKpf->getCharCount(); ++i1)
            {
                sgKpf->getPositionen()[i1] = (int)outF->tellp();
                LTDSCharacterHeader* zeichKpf = new LTDSCharacterHeader();
                Character* zeichen = alp->getCharacter(sgKpf->getChar()[i1]);
                zeichKpf->init(sgKpf->getChar()[i1],
                    zeichen->getWidth(),
                    zeichen->getHeight());
                zeichKpf->save(outF);
                LTDSCharacterBody* zeichKoerp = new LTDSCharacterBody(
                    dynamic_cast<LTDSCharacterHeader*>(zeichKpf->getThis()));
                zeichKoerp->setCharacter(
                    dynamic_cast<Character*>(zeichen->getThis()));
                zeichKoerp->save(outF);
                zeichKoerp->release();
                zeichen->release();
                zeichKpf->release();
            }
            alp->release();
            int p = (int)outF->tellp();
            outF->seekp(dateiKopf->getPositionList()[i], std::ios::beg);
            sgKpf->save(outF);
            outF->seekp(p, std::ios::beg);
            sgKpf->release();
        }
    }
    outF->seekp(0, std::ios::beg);
    dateiKopf->save(outF);
    outF->close();
    delete outF;
    font->release();
}

// constant
Font* LTDSFile::loadFont() // returns the loaded font
{
    if (!FileExists(dynamic_cast<Text*>(pfad->getThis()))) return 0;
    if (!dateiKopf) return 0;
    Font* ret = new Font();
    std::ifstream* inF = new std::ifstream(pfad->getText(), std::ios::binary);
    inF->seekg(dateiKopf->getPositionList()[0], std::ios::beg);
    for (int i = 0; i < dateiKopf->getFontSizeCount(); ++i)
    {
        LTDSFontHeader* sgKpf = new LTDSFontHeader();
        sgKpf->load(inF);
        Alphabet* alphabet = new Alphabet();
        alphabet->setFontSize(sgKpf->getFontSize());
        for (int i1 = 0; i1 < sgKpf->getCharCount(); ++i1)
        {
            LTDSCharacterHeader* zeichKpf = new LTDSCharacterHeader();
            zeichKpf->load(inF);
            LTDSCharacterBody* zeichKoerp = new LTDSCharacterBody(
                dynamic_cast<LTDSCharacterHeader*>(zeichKpf->getThis()));
            zeichKoerp->load(inF);
            alphabet->setCharacter(
                zeichKpf->getChar(), zeichKoerp->getCharacter());
            zeichKoerp->release();
            zeichKpf->release();
        }
        ret->addAlphabet(dynamic_cast<Alphabet*>(alphabet->getThis()));
        alphabet->release();
        sgKpf->release();
    }
    inF->close();
    delete inF;
    return ret;
}

Alphabet* LTDSFile::loadAlphabet(
int fontgroesse) // returns a loaded font with only the specified
                    // font size
{
    if (!FileExists(dynamic_cast<Text*>(pfad->getThis()))) return 0;
    if (!dateiKopf) return 0;
    Alphabet* ret = 0;
    int sgNum = -1;
    for (int i = 0; i < dateiKopf->getFontSizeCount(); ++i)
    {
        if (dateiKopf->getFontSizeList()[i] == fontgroesse)
        {
            sgNum = i;
            break;
        }
    }
    if (sgNum == -1) return 0;
    ret = new Alphabet();
    ret->NeuAlphabet();
    ret->setFontSize(fontgroesse);
    std::ifstream* inF = new std::ifstream(pfad->getText(), std::ios::binary);
    inF->seekg(dateiKopf->getPositionList()[sgNum], std::ios::beg);
    LTDSFontHeader* sgKpf = new LTDSFontHeader();
    sgKpf->load(inF);
    for (int i = 0; i < sgKpf->getCharCount(); ++i)
    {
        LTDSCharacterHeader* sgZKpf = new LTDSCharacterHeader();
        sgZKpf->load(inF);
        LTDSCharacterBody* sgZKoerp = new LTDSCharacterBody(
            dynamic_cast<LTDSCharacterHeader*>(sgZKpf->getThis()));
        sgZKoerp->load(inF);
        ret->setCharacter(sgZKpf->getChar(), sgZKoerp->getCharacter());
        sgZKoerp->release();
        sgZKpf->release();
    }
    sgKpf->release();
    inF->close();
    delete inF;
    return ret;
}

Character* LTDSFile::loadCharacter(int fontgroesse,
unsigned char zeichen) // Loads a specific character
{
    if (!FileExists(dynamic_cast<Text*>(pfad->getThis()))) return 0;
    if (!dateiKopf) return 0;
    Character* ret = 0;
    int sgNum = -1;
    for (int i = 0; i < dateiKopf->getFontSizeCount(); ++i)
    {
        if (dateiKopf->getFontSizeList()[i] == fontgroesse)
        {
            sgNum = i;
            break;
        }
    }
    if (sgNum == -1) return 0;
    std::ifstream* inF = new std::ifstream(pfad->getText(), std::ios::binary);
    inF->seekg(dateiKopf->getPositionList()[sgNum], std::ios::beg);
    LTDSFontHeader* sgKpf = new LTDSFontHeader();
    sgKpf->load(inF);
    int sgZNum = -1;
    for (int i = 0; i < sgKpf->getCharCount(); ++i)
    {
        if (sgKpf->getChar()[i] == zeichen)
        {
            sgZNum = i;
            break;
        }
    }
    if (sgZNum != -1)
    {
        inF->seekg(sgKpf->getPositionen()[sgZNum], std::ios::beg);
        LTDSCharacterHeader* sgZKpf = new LTDSCharacterHeader();
        sgZKpf->load(inF);
        LTDSCharacterBody* sgZKoerp = new LTDSCharacterBody(
            dynamic_cast<LTDSCharacterHeader*>(sgZKpf->getThis()));
        sgZKoerp->load(inF);
        ret = sgZKoerp->getCharacter();
        sgZKoerp->release();
        sgZKpf->release();
    }
    sgKpf->release();
    inF->close();
    delete inF;
    if (ret)
    {
        ret->setFontSize(fontgroesse);
    }
    return ret;
}

Text* LTDSFile::getPfad() const // returns the file path
{
    return dynamic_cast<Text*>(pfad->getThis());
}

int LTDSFile::getFontSizeCount()
const // returns the number of font sizes from the file
{
    if (!FileExists(dynamic_cast<Text*>(pfad->getThis()))) return 0;
    if (!dateiKopf) return 0;
    return dateiKopf->getFontSizeCount();
}

unsigned char* LTDSFile::getFontSizes()
const // returns an array of font sizes
{
    if (!FileExists(dynamic_cast<Text*>(pfad->getThis()))) return 0;
    if (!dateiKopf) return 0;
    return dateiKopf->getFontSizeList();
}

unsigned char LTDSFile::getCharacterCount(
int sg) // returns the number of stored characters for a font size
{
    if (!FileExists(dynamic_cast<Text*>(pfad->getThis()))) return 0;
    if (!dateiKopf) return 0;
    int ret = 0;
    unsigned char* groessen = dateiKopf->getFontSizeList();
    unsigned char sizeCount = dateiKopf->getFontSizeCount();
    int grpos = -1;
    for (int i = 0; i < sizeCount; ++i)
    {
        if (groessen[i] == sg)
        {
            grpos = i;
            break;
        }
    }
    if (grpos != -1)
    {
        int* grposlist = dateiKopf->getPositionList();
        LTDSFontHeader* sgkpf = new LTDSFontHeader();
        std::ifstream* inF
            = new std::ifstream(pfad->getText(), std::ios::binary);
        inF->seekg(grposlist[grpos], std::ios::beg);
        sgkpf->load(inF);
        ret = sgkpf->getCharCount();
        sgkpf->release();
        inF->close();
        delete inF;
    }
    return ret;
}

unsigned char* LTDSFile::getCharacters(
int sg) // returns an array of characters for a font size
{
    if (!FileExists(dynamic_cast<Text*>(pfad->getThis()))) return 0;
    if (!dateiKopf) return 0;
    unsigned char* ret = 0;
    unsigned char* groessen = dateiKopf->getFontSizeList();
    unsigned char sizeCount = dateiKopf->getFontSizeCount();
    int grpos = -1;
    for (int i = 0; i < sizeCount; ++i)
    {
        if (groessen[i] == sg)
        {
            grpos = i;
            break;
        }
    }
    if (grpos != -1)
    {
        int* grposlist = dateiKopf->getPositionList();
        LTDSFontHeader* sgkpf = new LTDSFontHeader();
        std::ifstream* inF
            = new std::ifstream(pfad->getText(), std::ios::binary);
        inF->seekg(grposlist[grpos], std::ios::beg);
        sgkpf->load(inF);
        int anz = sgkpf->getCharCount();
        ret = new unsigned char[anz];
        for (int i = 0; i < anz; ++i)
            ret[i] = sgkpf->getChar()[i];
        sgkpf->release();
        inF->close();
        delete inF;
    }
    return ret;
}
#endif
// Bit functions
int Framework::Bits(int a) // returns 1-bits in the desired count
{
    int ret = 0;
    for (int i = 0; i < a; ++i)
    {
        ret <<= 1;
        ++ret;
    }
    return ret;
}

int Framework::getBits(char c) // returns how many bits c requires
{
    int ret = 0;
    for (int i = 0; (c & (char)Bits(i)) != c; ++i)
        ++ret;
    return ret;
}