// subject_ex.cpp

#include <string.h>
#include <iostream.h>
#include <mimepp/mimepp.h>

//
// Sets aText as the subject line of aMessage, using the appropriate encoding.
// aCharset is the character set of the text (for example, "ISO-8859-1").
// aEncoding is 'Q' for quoted-printable encoding, or 'B' for base64
// encoding.  If aEncoding is 0, the function will try to choose the best
// encoding for the specified charset.
//
void SetSubject(
    DwMessage& aMessage,
    const char* aText,
    const char* aCharset,
    int aEncoding=0)
{
    int textLen = strlen(aText);
	int charsetLen = strlen(aCharset);

    // If the encoding type is ISO-8859-?, and if all characters are
    // 7-bit, then don't encode

    int num8BitChars = 0;
    int i;
    for (i=0; i < textLen; ++i) {
        int ch = aText[i] & 0xff;
        if (ch < 32 || 126 < ch) {
            ++num8BitChars;
        }
    }
    if (strcmp(aCharset, "US-ASCII") == 0
        || (strncmp(aCharset, "ISO-8859", 8) == 0 && num8BitChars == 0)) {

        DwString str = aText;
        DwFoldLine(str, 9);
        aMessage.Headers().Subject().FromString(str);
        aMessage.Headers().Subject().SetModified();
        aMessage.Headers().Subject().Parse();
        return;
    }

    // If no encoding is given, then determine a reasonable default:
    // Use Q encoding for:
    //    ISO-8859-1 (Latin-1)
    //    ISO-8859-2 (Latin-2)
    //    ISO-8859-3 (Latin-3)
    //    ISO-8859-4 (Latin-4)
    //    ISO-8859-9 (Latin-5)
    // Use B encoding for all others

    if (aEncoding == 0) {
        if (strcmp(aCharset, "ISO-8859-1") == 0
            || strcmp(aCharset, "ISO-8859-2") == 0
            || strcmp(aCharset, "ISO-8859-3") == 0
            || strcmp(aCharset, "ISO-8859-4") == 0
            || strcmp(aCharset, "ISO-8859-9") == 0) {

            aEncoding = 'Q';
        }
        else {
            aEncoding = 'B';
        }
    }
    else if (aEncoding != 'q' && aEncoding != 'Q'
        && aEncoding != 'b' && aEncoding != 'B') {

        aEncoding = 'B';
    }
    if (aEncoding == 'q' || aEncoding == 'Q') {
        aMessage.Headers().Subject().DeleteAllEncodedWords();
        int startPos = 0;
        int endPos = 0;
        int count = 0;
        while (endPos < textLen) {
            int ch = aText[endPos] & 0xff;
            if (ch < 32 || 126 < ch || ch == 61 || ch == 63) {
                count += 2;
            }
            ++count;
            ++endPos;
            if (count + charsetLen + 7 > 64) {
                DwEncodedWord* word = new DwEncodedWord;
                word->SetCharset(aCharset);
                word->SetEncodingType(aEncoding);
				DwString s(aText, startPos, endPos-startPos);
                word->SetDecodedText(s);
                aMessage.Headers().Subject().AddEncodedWord(word);
				count = 0;
                startPos = endPos;
            }
        }
        if (count > 0) {
            DwEncodedWord* word = new DwEncodedWord;
            word->SetCharset(aCharset);
            word->SetEncodingType(aEncoding);
    		DwString s(aText, startPos, endPos-startPos);
            word->SetDecodedText(s);
            aMessage.Headers().Subject().AddEncodedWord(word);
        }
        aMessage.Headers().Subject().Assemble();
    }
    else /* if (aEncoding != 'q' && aEncoding != 'Q') */ {
        aMessage.Headers().Subject().DeleteAllEncodedWords();
        int startPos = 0;
        int endPos = 0;
        while (endPos < textLen) {
            endPos += 39;
            endPos = (endPos < textLen) ? endPos : textLen;
            DwEncodedWord* word = new DwEncodedWord;
            word->SetCharset(aCharset);
            word->SetEncodingType(aEncoding);
    		DwString s(aText, startPos, endPos-startPos);
            word->SetDecodedText(s);
            aMessage.Headers().Subject().AddEncodedWord(word);
            startPos = endPos;
        }
        aMessage.Headers().Subject().Assemble();
    }
}

// Some test strings to try

static const char* str1 =
    "Vor vielen Jahren lebte ein Kaiser, der so ungeheuer viel auf neue "
    "Kleider hielt, dass er all sein Geld dafuer ausgab, um recht "
    "geputzt zu sein. Er kuemmerte sich nicht um seine Soldaten, "
    "kuemmerte sich nicht um Theater und liebte es nicht, in den "
    "Wald zu fahren, ausser um seine neuen Kleider zu zeigen. Er "
    "hatte einen Rock fuer jede Stunde des Tages, und ebenso wie "
    "man von einem Koenig sagte, er ist im Rat, so sagte man hier "
    "immer: \"Der Kaiser ist in der Garderobe!\"";

static const char* str2 =
    "Vor vielen Jahren lebte ein Kaiser, der so ungeheuer viel auf neue "
    "Kleider hielt, da\337 er all sein Geld daf\374r ausgab, um recht "
    "geputzt zu sein. Er k\374mmerte sich nicht um seine Soldaten, "
    "k\374mmerte sich nicht um Theater und liebte es nicht, in den "
    "Wald zu fahren, au\337er um seine neuen Kleider zu zeigen. Er "
    "hatte einen Rock f\374r jede Stunde des Tages, und ebenso wie "
    "man von einem K\366nig sagte, er ist im Rat, so sagte man hier "
    "immer: \"Der Kaiser ist in der Garderobe!\"";

static const char* str3 = "M\366chtest du e\337en gehen?";

static const char* str4 =
    "Jack be nimble, Jack be quick, Jack jump over the candlestick";

static const char* str5 =
    "======================= Free cable descrambler!!!! ===================";


int main(int, char**)
{
    DwMessage msg;
    const char* str = str2;
    const char* charset = "ISO-8859-1";
    // int encoding = 'B';
    int encoding = 'Q';
 
    SetSubject(msg, str, charset, encoding);
    //SetSubject(msg, str, charset);

    msg.Assemble();
	cout << msg.AsString() << flush;

	DwString textStr;
    DwText& text = msg.Headers().Subject();
	int numEncodedWords = text.NumEncodedWords();
	for (int i=0; i < numEncodedWords; ++i) {
    	DwEncodedWord& encodedWord = text.EncodedWordAt(i);
		textStr += encodedWord.DecodedText();
	}
	cout << endl;
	cout << textStr << endl;
	return 0;
}
