nsISaveAsCharset::attr_FallbackQuestionMark + nsISaveAsCharset::attr_EntityNone,
nsISaveAsCharset::attr_FallbackQuestionMark + nsISaveAsCharset::attr_EntityAfterCharsetConv,
PRInt32 generate_encodedwords(char *pUTF8, const char *charset, char method, char *output, PRInt32 outlen, PRInt32 output_carryoverlen, PRInt32 foldlen, PRBool foldingonly){  nsCOMPtr <nsISaveAsCharset> conv;  PRUnichar *_pUCS2 = nsnull, *pUCS2 = nsnull, *pUCS2Head = nsnull, cUCS2Tmp = 0;  char  *ibuf, *o = output, encodedword_head[kMAX_CSNAME+4+1], _charset[kMAX_CSNAME];  char  *pUTF8Head = nsnull, cUTF8Tmp = 0;  PRInt32   olen = 0, offset, linelen = output_carryoverlen, convlen = 0;  PRInt32   encodedword_headlen = 0, encodedword_taillen = foldingonly ? 0 : 2; // "?="  nsresult rv;  encodedword_head[0] = 0;  if (!foldingonly) {    // Deal with UCS2 pointer    pUCS2 = _pUCS2 = ToNewUnicode(NS_ConvertUTF8toUCS2(pUTF8));    if (!pUCS2)      return -1;    // Resolve charset alias    {      nsCOMPtr <nsICharsetConverterManager2> ccm2 = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);      nsCOMPtr <nsIAtom> charsetAtom;      charset = !nsCRT::strcasecmp(charset, "us-ascii") ? "ISO-8859-1" : charset;      rv = ccm2->GetCharsetAtom(NS_ConvertASCIItoUCS2(charset).get(), getter_AddRefs(charsetAtom));      if (NS_FAILED(rv)) {        if (_pUCS2)          nsMemory::Free(_pUCS2);        return -1;      }      const PRUnichar *charsetName;      charsetAtom->GetUnicode(&charsetName);      strcpy(_charset, NS_ConvertUCS2toUTF8(charsetName).get());      if (_charset[0])        charset = _charset;    }    // Prepare MIME encoded-word head with official charset name    if (PR_snprintf(encodedword_head, sizeof(encodedword_head)-1, "=?%s?%c?", charset, method) < 0) {      if (_pUCS2)        nsMemory::Free(_pUCS2);      return -1;    }    encodedword_headlen = strlen(encodedword_head);    // Load HANKAKU-KANA prefrence and cache it.    if (!nsCRT::strcasecmp("ISO-2022-JP", charset)) {      static PRInt32  conv_kana = -1;      if (conv_kana < 0) {        nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID, &rv));        if (nsnull != prefs && NS_SUCCEEDED(rv)) {          PRBool val;          if (NS_FAILED(prefs->GetBoolPref("mailnews.send_hankaku_kana", &val)))            val = PR_FALSE;  // no pref means need the mapping          conv_kana = val ? 0 : 1;        }      }      // Do nsITextTransform if needed      if (conv_kana > 0) {        nsCOMPtr <nsITextTransform> textTransform;        rv = nsComponentManager::CreateInstance(NS_HANKAKUTOZENKAKU_CONTRACTID, nsnull,                                                 NS_GET_IID(nsITextTransform), getter_AddRefs(textTransform));        if (NS_SUCCEEDED(rv)) {          nsString text(pUCS2), result;          rv = textTransform->Change(pUCS2, nsCRT::strlen(pUCS2), result);          if (NS_SUCCEEDED(rv)) {            if (_pUCS2)              nsMemory::Free(_pUCS2);            pUCS2 = _pUCS2 = ToNewUnicode(result);            if (!pUCS2)              return -1;          }        }      }    }    // Create an instance of charset converter and initialize it    conv = do_CreateInstance(NS_SAVEASCHARSET_CONTRACTID, &rv);    if(NS_SUCCEEDED(rv)) {      rv = conv->Init(charset,                        nsISaveAsCharset::attr_FallbackQuestionMark + nsISaveAsCharset::attr_EntityNone,                        nsIEntityConverter::transliterate);    }    if (NS_FAILED(rv)) {      if (_pUCS2)        nsMemory::Free(_pUCS2);      return -1;    }  } // if (!foldingonly)  /*     See if folding needs to happen.     If carried over length is already too long to hold     encoded-word header and trailer length, it's too obvious     that we need to fold.  So, don't waste time for calculation.  */  if (linelen + encodedword_headlen + encodedword_taillen < foldlen) {    if (foldingonly) {      offset = strlen(pUTF8Head = pUTF8);      pUTF8 += offset;    }    else {      rv = conv->Convert(pUCS2, &ibuf);      if (NS_FAILED(rv) || ibuf == nsnull) {        if (_pUCS2)          nsMemory::Free(_pUCS2);        return -1; //error      }      if (method == 'B') {        /* 4 / 3 = B encoding multiplier */        offset = strlen(ibuf) * 4 / 3;      }      else {        /* 3 = Q encoding multiplier */        offset = 0;        for (PRInt32 i = 0; *(ibuf+i); i++)          offset += NO_Q_ENCODING_NEEDED(*(ibuf+i)) ? 1 : 3;      }    }    if (linelen + encodedword_headlen + offset + encodedword_taillen > foldlen) {      /* folding has to happen */      if (foldingonly) {        pUTF8 = pUTF8Head;        pUTF8Head = nsnull;      }      else        PR_Free(ibuf);    }    else {      /* no folding needed, let's fall thru */      strcpy(o, encodedword_head);      olen += encodedword_headlen;      linelen += encodedword_headlen;      o += encodedword_headlen;      if (!foldingonly)        *pUCS2 = 0;    }  }  else {    strcpy(o, "\r\n ");    olen += 3;    o += 3;    linelen = 1;  }  /*    Let's do the nasty RFC-2047 & folding stuff  */  while ((foldingonly ? *pUTF8 : *pUCS2) && (olen < outlen)) {    strcpy(o, encodedword_head);    olen += encodedword_headlen;    linelen += encodedword_headlen;    o += encodedword_headlen;    olen += encodedword_taillen;    if (foldingonly)      pUTF8Head = pUTF8;    else      pUCS2Head = pUCS2;    while ((foldingonly ? *pUTF8 : *pUCS2) && (olen < outlen)) {      if (foldingonly) {        ++pUTF8;        for (;;) {          if (*pUTF8 == ' ' || *pUTF8 == TAB || !*pUTF8) {            offset = pUTF8 - pUTF8Head;            cUTF8Tmp = *pUTF8;            *pUTF8 = 0;            break;          }          ++pUTF8;        }      }      else {        convlen = ++pUCS2 - pUCS2Head;        cUCS2Tmp = *(pUCS2Head + convlen);        *(pUCS2Head + convlen) = 0;        rv = conv->Convert(pUCS2Head, &ibuf);        *(pUCS2Head + convlen) = cUCS2Tmp;        if (NS_FAILED(rv) || ibuf == nsnull) {          if (_pUCS2)            nsMemory::Free(_pUCS2);          return -1; //error        }        if (method == 'B') {          /* 4 / 3 = B encoding multiplier */          offset = strlen(ibuf) * 4 / 3;        }        else {          /* 3 = Q encoding multiplier */          offset = 0;          for (PRInt32 i = 0; *(ibuf+i); i++)            offset += NO_Q_ENCODING_NEEDED(*(ibuf+i)) ? 1 : 3;        }      }      if (linelen + offset > foldlen) {process_lastline:        PRInt32 enclen;        if (foldingonly) {          strcpy(o, pUTF8Head);          enclen = strlen(o);          o += enclen;          *pUTF8 = cUTF8Tmp;        }        else {          if (method == 'B')            enclen = intlmime_encode_b((const unsigned char *)ibuf, strlen(ibuf), o);          else            enclen = intlmime_encode_q((const unsigned char *)ibuf, strlen(ibuf), o);          PR_Free(ibuf);          o += enclen;          strcpy(o, "?=");        }        o += encodedword_taillen;        olen += enclen;        if (foldingonly ? *pUTF8 : *pUCS2) { /* not last line */          strcpy(o, "\r\n ");          o += 3;          olen += 3;          linelen = 1;          if (foldingonly) {            pUTF8Head = nsnull;            if (*pUTF8 == ' ' || *pUTF8 == TAB)              ++pUTF8;          }        }        else {          if (_pUCS2)            nsMemory::Free(_pUCS2);          return linelen + enclen + encodedword_taillen;        }        break;      }      else {        if (foldingonly)          *pUTF8 = cUTF8Tmp;        else {          if (*pUCS2)            PR_Free(ibuf);        }      }    }  }  if (linelen)    goto process_lastline;  if (_pUCS2)    nsMemory::Free(_pUCS2);  return linelen;}