Back to index

lightning-sunbird  0.9+nobinonly
mimetext.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is mozilla.org code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK *****
00038  * This Original Code has been modified by IBM Corporation. Modifications made by IBM 
00039  * described herein are Copyright (c) International Business Machines Corporation, 2000.
00040  * Modifications to Mozilla code or documentation identified per MPL Section 3.3
00041  *
00042  * Date             Modified by     Description of modification
00043  * 04/20/2000       IBM Corp.      OS/2 VisualAge build.
00044  */
00045 #include "mimetext.h"
00046 #include "mimebuf.h"
00047 #include "mimethtm.h"
00048 #include "comi18n.h"
00049 #include "mimemoz2.h"
00050 
00051 #include "prlog.h"
00052 #include "prmem.h"
00053 #include "plstr.h"
00054 #include "nsCRT.h"
00055 #include "nsIPrefService.h"
00056 #include "nsIPrefBranch.h"
00057 #include "nsIServiceManager.h"
00058 #include "nsIPrefLocalizedString.h"
00059 #include "nsMsgUtils.h"
00060 #include "nsMimeTypes.h"
00061 #include "nsReadableUtils.h"
00062 
00063 #define MIME_SUPERCLASS mimeLeafClass
00064 MimeDefClass(MimeInlineText, MimeInlineTextClass, mimeInlineTextClass,
00065                       &MIME_SUPERCLASS);
00066 
00067 static int MimeInlineText_initialize (MimeObject *);
00068 static void MimeInlineText_finalize (MimeObject *);
00069 static int MimeInlineText_rot13_line (MimeObject *, char *line, PRInt32 length);
00070 static int MimeInlineText_parse_eof (MimeObject *obj, PRBool abort_p);
00071 static int MimeInlineText_parse_end  (MimeObject *, PRBool);
00072 static int MimeInlineText_parse_decoded_buffer (const char *, PRInt32, MimeObject *);
00073 static int MimeInlineText_rotate_convert_and_parse_line(char *, PRInt32,
00074                  MimeObject *);
00075 static int MimeInlineText_open_dam(char *line, PRInt32 length, MimeObject *obj);
00076 static int MimeInlineText_initializeCharset(MimeObject *obj);
00077 
00078 static int
00079 MimeInlineTextClassInitialize(MimeInlineTextClass *clazz)
00080 {
00081   MimeObjectClass *oclass = (MimeObjectClass *) clazz;
00082   MimeLeafClass   *lclass = (MimeLeafClass *) clazz;
00083   PR_ASSERT(!oclass->class_initialized);
00084   oclass->initialize           = MimeInlineText_initialize;
00085   oclass->finalize             = MimeInlineText_finalize;
00086   oclass->parse_eof            = MimeInlineText_parse_eof;
00087   oclass->parse_end            = MimeInlineText_parse_end;
00088   clazz->rot13_line            = MimeInlineText_rot13_line;
00089   clazz->initialize_charset    =  MimeInlineText_initializeCharset;
00090   lclass->parse_decoded_buffer = MimeInlineText_parse_decoded_buffer;
00091   return 0;
00092 }
00093 
00094 static int
00095 MimeInlineText_initialize (MimeObject *obj)
00096 {
00097   /* This is an abstract class; it shouldn't be directly instantiated. */
00098   PR_ASSERT(obj->clazz != (MimeObjectClass *) &mimeInlineTextClass);
00099 
00100   ((MimeInlineText *) obj)->initializeCharset = PR_FALSE;
00101   ((MimeInlineText *) obj)->needUpdateMsgWinCharset = PR_FALSE;
00102   return ((MimeObjectClass*)&MIME_SUPERCLASS)->initialize(obj);
00103 }
00104 
00105 static int MimeInlineText_initializeCharset(MimeObject *obj)
00106 {
00107   MimeInlineText  *text = (MimeInlineText *) obj;
00108 
00109   text->inputAutodetect = PR_FALSE;
00110   text->charsetOverridable = PR_FALSE;
00111   
00112   /* Figure out an appropriate charset for this object.
00113   */
00114   if (!text->charset && obj->headers)
00115   {
00116     if (obj->options && obj->options->override_charset)
00117     {
00118       text->charset = nsCRT::strdup(obj->options->default_charset);
00119     }
00120     else
00121     {
00122       char *ct = MimeHeaders_get (obj->headers, HEADER_CONTENT_TYPE,
00123                                   PR_FALSE, PR_FALSE);
00124       if (ct)
00125       {
00126         text->charset = MimeHeaders_get_parameter (ct, "charset", NULL, NULL);
00127         PR_Free(ct);
00128       }
00129     
00130       if (!text->charset)
00131       {
00132         /* If we didn't find "Content-Type: ...; charset=XX" then look
00133            for "X-Sun-Charset: XX" instead.  (Maybe this should be done
00134            in MimeSunAttachmentClass, but it's harder there than here.)
00135          */
00136         text->charset = MimeHeaders_get (obj->headers,
00137                                           HEADER_X_SUN_CHARSET,
00138                                           PR_FALSE, PR_FALSE);
00139       }
00140 
00141       /* iMIP entities without an explicit charset parameter default to
00142        US-ASCII (RFC 2447, section 2.4). However, Microsoft Outlook generates
00143        UTF-8 but omits the charset parameter.
00144        When no charset is defined by the container (e.g. iMIP), iCalendar
00145        files default to UTF-8 (RFC 2445, section 4.1.4).
00146        */
00147       if (!text->charset &&
00148           obj->content_type &&
00149           !PL_strcasecmp(obj->content_type, TEXT_CALENDAR))
00150         text->charset = strdup("UTF-8");
00151 
00152       if (!text->charset)
00153       {
00154         nsresult res;
00155         
00156         text->charsetOverridable = PR_TRUE;
00157 
00158         nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &res)); 
00159         if (NS_SUCCEEDED(res))
00160         {
00161           nsCOMPtr<nsIPrefLocalizedString> str;
00162           if (NS_SUCCEEDED(prefBranch->GetComplexValue("intl.charset.detector", NS_GET_IID(nsIPrefLocalizedString), getter_AddRefs(str)))) {
00163             //only if we can get autodetector name correctly, do we set this to true
00164             text->inputAutodetect = PR_TRUE;
00165           }
00166         }
00167         
00168         if (obj->options && obj->options->default_charset)
00169           text->charset = nsCRT::strdup(obj->options->default_charset);
00170         else
00171         {
00172           if (NS_SUCCEEDED(res))
00173           {
00174             nsXPIDLString value;
00175             NS_GetLocalizedUnicharPreferenceWithDefault(prefBranch, "mailnews.view_default_charset", EmptyString(), value);
00176             text->charset = ToNewUTF8String(value);
00177           }
00178           else
00179             text->charset = nsCRT::strdup("");
00180         }
00181       } 
00182     }
00183   }
00184   
00185   if (text->inputAutodetect)
00186   {
00187     //we need to prepare lineDam for charset detection
00188     text->lineDamBuffer = (char*)PR_Malloc(DAM_MAX_BUFFER_SIZE);
00189     text->lineDamPtrs = (char**)PR_Malloc(DAM_MAX_LINES*sizeof(char*));
00190     text->curDamOffset = 0;
00191     text->lastLineInDam = 0;
00192     if (!text->lineDamBuffer || !text->lineDamPtrs)
00193     {
00194       text->inputAutodetect = PR_FALSE;
00195       PR_FREEIF(text->lineDamBuffer);
00196       PR_FREEIF(text->lineDamPtrs);
00197     }
00198   }
00199 
00200   text->initializeCharset = PR_TRUE;
00201 
00202   return 0;
00203 }
00204 
00205 static void
00206 MimeInlineText_finalize (MimeObject *obj)
00207 {
00208   MimeInlineText *text = (MimeInlineText *) obj;
00209 
00210   obj->clazz->parse_eof (obj, PR_FALSE);
00211   obj->clazz->parse_end (obj, PR_FALSE);
00212 
00213   text->inputDecoder = nsnull;
00214   text->utf8Encoder = nsnull;
00215   PR_FREEIF(text->charset);
00216 
00217   /* Should have been freed by parse_eof, but just in case... */
00218   PR_ASSERT(!text->cbuffer);
00219   PR_FREEIF (text->cbuffer);
00220 
00221   if (text->inputAutodetect) {
00222     PR_FREEIF(text->lineDamBuffer);
00223     PR_FREEIF(text->lineDamPtrs);
00224     text->inputAutodetect = PR_FALSE;
00225   }
00226 
00227   ((MimeObjectClass*)&MIME_SUPERCLASS)->finalize (obj);
00228 }
00229 
00230 
00231 static int
00232 MimeInlineText_parse_eof (MimeObject *obj, PRBool abort_p)
00233 {
00234   int status;
00235 
00236   if (obj->closed_p) return 0;
00237   NS_ASSERTION(!obj->parsed_p, "obj already parsed");
00238 
00239   MimeInlineText *text = (MimeInlineText *) obj;
00240 
00241   /* Flush any buffered data from the MimeLeaf's decoder */
00242   status = ((MimeLeafClass*)&MIME_SUPERCLASS)->close_decoder(obj);
00243   if (status < 0) return status;
00244 
00245   /* If there is still data in the ibuffer, that means that the last
00246    line of this part didn't end in a newline; so push it out anyway
00247    (this means that the parse_line method will be called with a string
00248    with no trailing newline, which isn't the usual case).  We do this
00249    here, rather than in MimeObject_parse_eof, because MimeObject isn't
00250    aware of the rotating-and-converting / charset detection we need to
00251    do first.
00252   */
00253   if (!abort_p && obj->ibuffer_fp > 0)
00254   {
00255     status = MimeInlineText_rotate_convert_and_parse_line (obj->ibuffer,
00256                                                            obj->ibuffer_fp,
00257                                                            obj);
00258     obj->ibuffer_fp = 0;
00259     if (status < 0)
00260     {
00261       //we haven't find charset yet? Do it before return
00262       if (text->inputAutodetect)
00263         status = MimeInlineText_open_dam(nsnull, 0, obj);
00264 
00265       obj->closed_p = PR_TRUE;
00266       return status;
00267     }
00268   }
00269 
00270   //we haven't find charset yet? now its the time
00271   if (text->inputAutodetect)
00272      status = MimeInlineText_open_dam(nsnull, 0, obj);
00273  
00274   return ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof (obj, abort_p);
00275 }
00276 
00277 static int
00278 MimeInlineText_parse_end (MimeObject *obj, PRBool abort_p)
00279 {
00280   MimeInlineText *text = (MimeInlineText *) obj;
00281 
00282   if (obj->parsed_p)
00283        {
00284          PR_ASSERT(obj->closed_p);
00285          return 0;
00286        }
00287 
00288   /* We won't be needing this buffer any more; nuke it. */
00289   PR_FREEIF(text->cbuffer);
00290   text->cbuffer_size = 0;
00291 
00292   return ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_end (obj, abort_p);
00293 }
00294 
00295 
00296 /* This maps A-M to N-Z and N-Z to A-M.  All other characters are left alone.
00297    (Comments in GNUS imply that for Japanese, one should rotate by 47?)
00298  */
00299 static const unsigned char MimeInlineText_rot13_table[256] = {
00300   0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
00301   21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
00302   40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
00303   59, 60, 61, 62, 63, 64, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
00304   65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 91, 92, 93, 94, 95, 96,
00305   110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 97, 98,
00306   99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 123, 124, 125, 126,
00307   127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
00308   142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
00309   157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
00310   172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
00311   187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201,
00312   202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216,
00313   217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231,
00314   232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
00315   247, 248, 249, 250, 251, 252, 253, 254, 255 };
00316 
00317 static int
00318 MimeInlineText_rot13_line (MimeObject *obj, char *line, PRInt32 length)
00319 {
00320   unsigned char *s, *end;
00321   PR_ASSERT(line);
00322   if (!line) return -1;
00323   s = (unsigned char *) line;
00324   end = s + length;
00325   while (s < end)
00326        {
00327          *s = MimeInlineText_rot13_table[*s];
00328          s++;
00329        }
00330   return 0;
00331 }
00332 
00333 
00334 static int
00335 MimeInlineText_parse_decoded_buffer (const char *buf, PRInt32 size, MimeObject *obj)
00336 {
00337   PR_ASSERT(!obj->closed_p);
00338   if (obj->closed_p) return -1;
00339 
00340   /* MimeLeaf takes care of this. */
00341   PR_ASSERT(obj->output_p && obj->options && obj->options->output_fn);
00342   if (!obj->options) return -1;
00343 
00344   /* If we're supposed to write this object, but aren't supposed to convert
00345         it to HTML, simply pass it through unaltered. */
00346   if (!obj->options->write_html_p && obj->options->format_out != nsMimeOutput::nsMimeMessageAttach)
00347        return MimeObject_write(obj, buf, size, PR_TRUE);
00348 
00349   /* This is just like the parse_decoded_buffer method we inherit from the
00350         MimeLeaf class, except that we line-buffer to our own wrapper on the
00351         `parse_line' method instead of calling the `parse_line' method directly.
00352    */
00353   return mime_LineBuffer (buf, size,
00354                                            &obj->ibuffer, &obj->ibuffer_size, &obj->ibuffer_fp,
00355                                            PR_TRUE,
00356                                            ((int (*PR_CALLBACK) (char *, PRInt32, void *))
00357                                             /* This cast is to turn void into MimeObject */
00358                                             MimeInlineText_rotate_convert_and_parse_line),
00359                                            obj);
00360 }
00361 
00362 
00363 #define MimeInlineText_grow_cbuffer(text, desired_size) \
00364   (((desired_size) >= (text)->cbuffer_size) ? \
00365    mime_GrowBuffer ((desired_size), sizeof(char), 100, \
00366                                &(text)->cbuffer, &(text)->cbuffer_size) \
00367    : 0)
00368 
00369 static int 
00370 MimeInlineText_convert_and_parse_line(char *line, PRInt32 length, MimeObject *obj)
00371 {
00372   int status;
00373   char *converted = 0;
00374   PRInt32 converted_len = 0;
00375   
00376   MimeInlineText *text = (MimeInlineText *) obj;
00377 
00378   //in case of charset autodetection, charset can be override by meta charset
00379   if (text->charsetOverridable) {
00380     if (mime_typep(obj, (MimeObjectClass *) &mimeInlineTextHTMLClass))
00381     {
00382       MimeInlineTextHTML  *textHTML = (MimeInlineTextHTML *) obj;
00383       if (textHTML->charset && 
00384           *textHTML->charset &&
00385           nsCRT::strcmp(textHTML->charset, text->charset))
00386       {
00387         //if meta tag specified charset is different from our detected result, use meta charset.
00388         //but we don't want to redo previous lines
00389         MIME_get_unicode_decoder(textHTML->charset, getter_AddRefs(text->inputDecoder));
00390         PR_FREEIF(text->charset);
00391         text->charset = nsCRT::strdup(textHTML->charset);
00392 
00393         //update MsgWindow charset if we are instructed to do so
00394         if (text->needUpdateMsgWinCharset && *text->charset)
00395           SetMailCharacterSetToMsgWindow(obj, text->charset);
00396       }
00397     }
00398   }
00399 
00400   //initiate decoder if not yet
00401   if (text->inputDecoder == nsnull)
00402     MIME_get_unicode_decoder(text->charset, getter_AddRefs(text->inputDecoder));
00403   // If no decoder found, use ""UTF-8"", that will map most non-US-ASCII chars as invalid
00404   // A pure-ASCII only decoder would be better, but there is none
00405   if (text->inputDecoder == nsnull)
00406     MIME_get_unicode_decoder("UTF-8", getter_AddRefs(text->inputDecoder));
00407   if (text->utf8Encoder == nsnull)
00408     MIME_get_unicode_encoder("UTF-8", getter_AddRefs(text->utf8Encoder));
00409 
00410   PRBool useInputCharsetConverter = obj->options->m_inputCharsetToUnicodeDecoder && !nsCRT::strcasecmp(text->charset, obj->options->charsetForCachedInputDecoder.get());
00411 
00412   if (useInputCharsetConverter)
00413     status = obj->options->charset_conversion_fn(line, length,
00414                          text->charset,
00415                                                                                      "UTF-8",
00416                                                                                      &converted,
00417                                                                                      &converted_len,
00418                          obj->options->stream_closure, obj->options->m_inputCharsetToUnicodeDecoder,
00419                        obj->options->m_unicodeToUTF8Encoder);
00420   else
00421     status = obj->options->charset_conversion_fn(line, length,
00422                          text->charset,
00423                                                                                      "UTF-8",
00424                                                                                      &converted,
00425                                                                                      &converted_len,
00426                          obj->options->stream_closure, (nsIUnicodeDecoder*)text->inputDecoder,
00427                          (nsIUnicodeEncoder*)text->utf8Encoder);
00428 
00429   if (status < 0)
00430   {
00431     PR_FREEIF(converted);
00432     return status;
00433   }
00434 
00435   if (converted)
00436   {
00437     line = converted;
00438     length = converted_len;
00439   }
00440 
00441   /* Now that the line has been converted, call the subclass's parse_line
00442         method with the decoded data. */
00443   status = obj->clazz->parse_line(line, length, obj);
00444   PR_FREEIF(converted);
00445 
00446   return status;
00447 }
00448 
00449 //In this function call, all buffered lines in lineDam will be sent to charset detector 
00450 // and a charset will be used to parse all those line and following lines in this mime obj.
00451 static int 
00452 MimeInlineText_open_dam(char *line, PRInt32 length, MimeObject *obj)
00453 {
00454   MimeInlineText *text = (MimeInlineText *) obj;
00455   const char* detectedCharset = nsnull;
00456   nsresult res = NS_OK;
00457   int status = 0;
00458   PRInt32 i;
00459 
00460   if (text->curDamOffset <= 0) {
00461     //there is nothing in dam, use current line for detection
00462     if (length > 0) {
00463       res = MIME_detect_charset(line, length, &detectedCharset);  
00464     }
00465   } else {
00466     //we have stuff in dam, use the one 
00467     res = MIME_detect_charset(text->lineDamBuffer, text->curDamOffset, &detectedCharset);  
00468   }
00469 
00470   //set the charset for this obj
00471   if (NS_SUCCEEDED(res) && detectedCharset && *detectedCharset)  {
00472     PR_FREEIF(text->charset);
00473     text->charset = nsCRT::strdup(detectedCharset);
00474 
00475     //update MsgWindow charset if we are instructed to do so
00476     if (text->needUpdateMsgWinCharset && *text->charset)
00477       SetMailCharacterSetToMsgWindow(obj, text->charset);
00478   }
00479 
00480   //process dam and line using the charset
00481   if (text->curDamOffset) {
00482     for (i = 0; i < text->lastLineInDam-1; i++)
00483     {
00484       status = MimeInlineText_convert_and_parse_line(
00485                 text->lineDamPtrs[i],  
00486                 text->lineDamPtrs[i+1] - text->lineDamPtrs[i],
00487                 obj  );
00488     }
00489     status = MimeInlineText_convert_and_parse_line(
00490                 text->lineDamPtrs[i],
00491                 text->lineDamBuffer + text->curDamOffset - text->lineDamPtrs[i],
00492                 obj );
00493   }
00494 
00495   if (length)
00496     status = MimeInlineText_convert_and_parse_line(line, length, obj);
00497 
00498   PR_Free(text->lineDamPtrs);
00499   PR_Free(text->lineDamBuffer);
00500   text->lineDamPtrs = nsnull;
00501   text->lineDamBuffer = nsnull;
00502   text->inputAutodetect = PR_FALSE;
00503 
00504   return status;
00505 }
00506 
00507 
00508 static int
00509 MimeInlineText_rotate_convert_and_parse_line(char *line, PRInt32 length,
00510                                                                               MimeObject *obj)
00511 {
00512   int status = 0;
00513   MimeInlineTextClass *textc = (MimeInlineTextClass *) obj->clazz;
00514 
00515   PR_ASSERT(!obj->closed_p);
00516   if (obj->closed_p) return -1;
00517 
00518   /* Rotate the line, if desired (this happens on the raw data, before any
00519         charset conversion.) */
00520   if (obj->options && obj->options->rot13_p)
00521        {
00522          status = textc->rot13_line(obj, line, length);
00523          if (status < 0) return status;
00524        }
00525 
00526   // Now convert to the canonical charset, if desired.
00527   //
00528   PRBool  doConvert = PR_TRUE;
00529   // Don't convert vCard data
00530   if ( ( (obj->content_type) && (!PL_strcasecmp(obj->content_type, TEXT_VCARD)) ) ||
00531        (obj->options->format_out == nsMimeOutput::nsMimeMessageSaveAs)
00532        || obj->options->format_out == nsMimeOutput::nsMimeMessageAttach)
00533     doConvert = PR_FALSE;
00534     
00535   // Only convert if the user prefs is false 
00536   if ( (obj->options && obj->options->charset_conversion_fn) &&
00537        (!obj->options->force_user_charset) &&
00538        (doConvert)       
00539      )
00540        {
00541     MimeInlineText  *text = (MimeInlineText *) obj;
00542 
00543     if (!text->initializeCharset)
00544     {
00545       MimeInlineText_initializeCharset(obj);
00546       //update MsgWindow charset if we are instructed to do so
00547       if (text->needUpdateMsgWinCharset && *text->charset)
00548         SetMailCharacterSetToMsgWindow(obj, text->charset);
00549     }
00550 
00551     //if autodetect is on, push line to dam
00552     if (text->inputAutodetect)
00553     {
00554       //see if we reach the lineDam buffer limit, if so, there is no need to keep buffering
00555       if (text->lastLineInDam >= DAM_MAX_LINES ||
00556           DAM_MAX_BUFFER_SIZE - text->curDamOffset <= length) {
00557         //we let open dam process this line as well as thing that already in Dam
00558         //In case there is nothing in dam because this line is too big, we need to 
00559         //perform autodetect on this line
00560         status = MimeInlineText_open_dam(line, length, obj);
00561       }
00562       else {
00563         //buffering current line
00564         text->lineDamPtrs[text->lastLineInDam] = text->lineDamBuffer + text->curDamOffset;
00565         memcpy(text->lineDamPtrs[text->lastLineInDam], line, length);
00566         text->lastLineInDam++;
00567         text->curDamOffset += length;
00568       }
00569     }
00570     else 
00571       status = MimeInlineText_convert_and_parse_line(line, length, obj);
00572        }
00573   else
00574     status = obj->clazz->parse_line(line, length, obj);
00575 
00576   return status;
00577 }