*outlinep='\"'; outlinep++;
*outlinep='"'; outlinep++;
MimeInlineTextPlainFlowed_parse_line (char *line, PRInt32 length, MimeObject *obj){  int status;  PRBool quoting = ( obj->options    && ( obj->options->format_out == nsMimeOutput::nsMimeMessageQuoting ||         obj->options->format_out == nsMimeOutput::nsMimeMessageBodyQuoting       )           );  // see above  PRBool plainHTML = quoting || (obj->options &&       obj->options->format_out == nsMimeOutput::nsMimeMessageSaveAs);       // see above  struct MimeInlineTextPlainFlowedExData *exdata;  exdata = MimeInlineTextPlainFlowedExDataList;  while(exdata && (exdata->ownerobj != obj)) {    exdata = exdata->next;  }  NS_ASSERTION(exdata, "The extra data has disappeared!");  NS_ASSERTION(length > 0, "zero length");  if (length <= 0) return 0;  // Grows the buffer if needed for this line  // calculate needed buffersize. Use the linelength  // and then double it to compensate for text converted  // to links. Then add 15 for each '>' (blockquote) and  // 20 for each ':' and '@'. (overhead in conversion to  // links). Also add 5 for every '\r' or \n' and 7 for each  // space in case they have to be replaced by &nbsp;  int32 buffersizeneeded = length * 2 + 15*exdata->quotelevel;  for(int32 i=0; i<length; i++) {    switch(line[i]) {    case '>': buffersizeneeded += 25; break; // '>' -> '<blockquote type=cite>'    case '<': buffersizeneeded += 5; break; // '<' -> '&lt;'    case ':': buffersizeneeded += 20; break;    case '@': buffersizeneeded += 20; break;    case '\r': buffersizeneeded += 5; break;    case '\n': buffersizeneeded += 5; break;    case ' ': buffersizeneeded += 7; break; // Not very good for other charsets    case '\t': buffersizeneeded += 30; break;    default: break; // Nothing    }  }  buffersizeneeded += 30; // For possible <nobr> ... </nobr>  /* There is the issue of guessing how much space we will need for emoticons.     So what we will do is count the total number of "special" chars and     multiply by 82 (max len for a smiley line) and add one for good measure.*/  PRInt32   specialCharCount = 0;  for (PRInt32 z=0; z<length; z++)  {     if ( (line[z] == ')') || (line[z] == '(') || (line[z] == ':')         || (line[z] == ';') || (line[z] == '>') )      ++specialCharCount;  }  buffersizeneeded += 82 * (specialCharCount + 1);   status = MimeObject_grow_obuffer (obj, buffersizeneeded);  if (status < 0) return status;  char *templine = (char *)PR_CALLOC(buffersizeneeded);  if(!templine)     return MIME_OUT_OF_MEMORY;  uint32 linequotelevel = 0;  char *linep = line;  // Space stuffed?  if(' ' == *linep) {    linep++;  } else {    // count '>':s before the first non-'>'    while('>' == *linep) {      linep++;      linequotelevel++;    }    // Space stuffed?    if(' ' == *linep) {      linep++;    }  }  // Look if the last character (after stripping ending end  // of lines and quoting stuff) is a SPACE. If it is, we are looking at a  // flowed line. Normally we assume that the last two chars  // are CR and LF as said in RFC822, but that doesn't seem to  // be the case always.  PRBool flowed = PR_FALSE;  PRInt32 index = length-1;  while(index >= 0 && ('\r' == line[index] || '\n' == line[index])) {    index--;  }  if (index > linep - line && ' ' == line[index])       /* Ignore space stuffing, i.e. lines with just          (quote marks and) a space count as empty */    flowed = PR_TRUE;  mozITXTToHTMLConv *conv = GetTextConverter(obj->options);  PRBool skipConversion = !conv ||                          (obj->options && obj->options->force_user_charset);      if (!skipConversion)  {    nsString strline;    strline.AssignWithConversion(linep, (length - (linep - line)) );    PRUnichar* wresult = nsnull;    nsresult rv = NS_OK;    PRBool whattodo = obj->options->whattodo;    if (plainHTML)    {      if (quoting)        whattodo = 0;      else        whattodo = whattodo & ~mozITXTToHTMLConv::kGlyphSubstitution;                   /* Do recognition for the case, the result is viewed in                      Mozilla, but not GlyphSubstitution, because other UAs                      might not be able to display the glyphs. */    }    /* This is the main TXT to HTML conversion:       escaping (very important), eventually recognizing etc. */    rv = conv->ScanTXT(strline.GetUnicode(), whattodo, &wresult);    if (NS_FAILED(rv))    {      PR_Free(templine);      return -1;    }    /* avoid an extra string copy by using nsSubsumeStr, this transfers       ownership of wresult to strresult so don't try to free wresult later. */    nsSubsumeStr strresult(wresult, PR_TRUE /* assume ownership */);    /* avoid yet another extra string copy of the line by using .ToCString       which will convert and copy directly into the buffer we have already       allocated. */    strresult.ToCString(templine, buffersizeneeded - 10);   }  else  {    nsCRT::memcpy(templine, line, length);    templine[length] = '\0';    status = NS_OK;  }  if (status != NS_OK) {    PR_Free(templine);    return status;  }  //  NS_ASSERTION(*line == 0 || *obj->obuffer, "have line or buffer");  NS_ASSERTION(*line == 0 || *templine, "have line or buffer");  char *templinep = templine;  char *outlinep = obj->obuffer;  /* Correct number of blockquotes */  int32 quoteleveldiff=linequotelevel - exdata->quotelevel;  if((quoteleveldiff != 0) && flowed && exdata->inflow) {    // From RFC 2646 4.5    // The receiver SHOULD handle this error by using the 'quote-depth-wins' rule,    // which is to ignore the flowed indicator and treat the line as fixed.  That    // is, the change in quote depth ends the paragraph.    // We get that behaviour by just going on.  }  while(quoteleveldiff>0) {    quoteleveldiff--;    /* Output <blockquote> */    *outlinep='<'; outlinep++;    *outlinep='b'; outlinep++;    *outlinep='l'; outlinep++;    *outlinep='o'; outlinep++;    *outlinep='c'; outlinep++;    *outlinep='k'; outlinep++;    *outlinep='q'; outlinep++;    *outlinep='u'; outlinep++;    *outlinep='o'; outlinep++;    *outlinep='t'; outlinep++;    *outlinep='e'; outlinep++;    *outlinep=' '; outlinep++;    *outlinep='t'; outlinep++;    *outlinep='y'; outlinep++;    *outlinep='p'; outlinep++;    *outlinep='e'; outlinep++;    *outlinep='='; outlinep++;    *outlinep='c'; outlinep++;    *outlinep='i'; outlinep++;    *outlinep='t'; outlinep++;    *outlinep='e'; outlinep++;    // This is to have us observe the user pref settings for citations    MimeInlineTextPlainFlowed *tObj = (MimeInlineTextPlainFlowed *) obj;    char *style = MimeTextBuildPrefixCSS(tObj->mQuotedSizeSetting,                                         tObj->mQuotedStyleSetting,                                         tObj->mCitationColor);    if (!plainHTML && style && strlen(style))    {      *outlinep=' '; outlinep++;      *outlinep='s'; outlinep++;      *outlinep='t'; outlinep++;      *outlinep='y'; outlinep++;      *outlinep='l'; outlinep++;      *outlinep='e'; outlinep++;      *outlinep='='; outlinep++;      *outlinep='\"'; outlinep++;      strcpy(outlinep, style);      outlinep += nsCRT::strlen(style);      *outlinep='\"'; outlinep++;      PR_FREEIF(style);    }    *outlinep='>'; outlinep++;  }  while(quoteleveldiff<0) {    quoteleveldiff++;    /* Output </blockquote> */    *outlinep='<'; outlinep++;    *outlinep='/'; outlinep++;    *outlinep='b'; outlinep++;    *outlinep='l'; outlinep++;    *outlinep='o'; outlinep++;    *outlinep='c'; outlinep++;    *outlinep='k'; outlinep++;    *outlinep='q'; outlinep++;    *outlinep='u'; outlinep++;    *outlinep='o'; outlinep++;    *outlinep='t'; outlinep++;    *outlinep='e'; outlinep++;    *outlinep='>'; outlinep++;  }  exdata->quotelevel = linequotelevel;  PRBool in_tag = PR_FALSE;   PRBool in_quote_in_tag = PR_FALSE;  char quote_char;    if(flowed) {    // Check RFC 2646 "4.3. Usenet Signature Convention": "-- "+CRLF is    // not a flowed line    if      (  // is "-- "LINEBREAK        templinep[0] == '-'        && PL_strlen(templinep) >= 4        &&        (          !PL_strncmp(templinep, "-- \r", 4) ||          !PL_strncmp(templinep, "-- \n", 4)        )      )    {      if (linequotelevel > 0 || exdata->isSig)      {        *outlinep='-'; outlinep++;        *outlinep='-'; outlinep++;        *outlinep='&'; outlinep++;        *outlinep='n'; outlinep++;        *outlinep='b'; outlinep++;        *outlinep='s'; outlinep++;        *outlinep='p'; outlinep++;        *outlinep=';'; outlinep++;        *outlinep='<'; outlinep++;        *outlinep='b'; outlinep++;        *outlinep='r'; outlinep++;        *outlinep='>'; outlinep++;      } else {        exdata->isSig = PR_TRUE;        const char *const sig_mark_start =         "<div class=\"txt-sig\"><span class=\"txt-tag\">--&nbsp;<br></span>";        PRUint32 sig_mark_start_length = PL_strlen(sig_mark_start);        memcpy(outlinep, sig_mark_start, sig_mark_start_length);        outlinep += sig_mark_start_length;      }      templinep += 3;  // Above, we already outputted the equvivalent to "-- "    } else {      // Output templinep            /* Convert all spaces but the first in a row into nbsp         (i.e. always wrap) */      const PRBool firstSpaceNbsp = PR_FALSE;      PRBool nextSpaceIsNbsp = firstSpaceNbsp;      while(*templinep && (*templinep != '\r') && (*templinep != '\n'))      {        Update_in_tag_info(&in_tag, &in_quote_in_tag,                           &quote_char, *templinep);        // We don't touch anything insida a tag.        if (!in_tag) {          if (' ' == *templinep) {            if (nextSpaceIsNbsp)            {              *outlinep='&'; outlinep++;              *outlinep='n'; outlinep++;              *outlinep='b'; outlinep++;              *outlinep='s'; outlinep++;              *outlinep='p'; outlinep++;              *outlinep=';'; outlinep++;            }            else            {              *outlinep=' '; outlinep++;            }            nextSpaceIsNbsp = PR_TRUE;            templinep++;          } else if('\t' == *templinep) {            // Output 4 "spaces"            for(int spaces=0; spaces<4; spaces++) {              if (nextSpaceIsNbsp)              {                *outlinep='&'; outlinep++;                *outlinep='n'; outlinep++;                *outlinep='b'; outlinep++;                *outlinep='s'; outlinep++;                *outlinep='p'; outlinep++;                *outlinep=';'; outlinep++;              }              else              {                *outlinep=' '; outlinep++;              }              nextSpaceIsNbsp = PR_TRUE;            }            templinep++;          } else {            nextSpaceIsNbsp = firstSpaceNbsp;            *outlinep = *templinep;            outlinep++;            templinep++;          }         } else {          // In tag. Don't change anything          nextSpaceIsNbsp = firstSpaceNbsp;          *outlinep = *templinep;          outlinep++;          templinep++;        }      }    }    exdata->inflow=PR_TRUE;  } else {    // Fixed paragraph.        const PRBool firstSpaceNbsp = !plainHTML &&                                  !obj->options->wrap_long_lines_p;         /* If wrap, convert all spaces but the first in a row into nbsp,            otherwise all. */    PRBool nextSpaceIsNbsp = firstSpaceNbsp;    while(*templinep && (*templinep != '\r') && (*templinep != '\n')) {      Update_in_tag_info(&in_tag, &in_quote_in_tag,                         &quote_char, *templinep);            // We don't touch anything insida a tag.      if(!in_tag) {        if(' ' == *templinep) {          if (nextSpaceIsNbsp)          {            *outlinep='&'; outlinep++;            *outlinep='n'; outlinep++;            *outlinep='b'; outlinep++;            *outlinep='s'; outlinep++;            *outlinep='p'; outlinep++;            *outlinep=';'; outlinep++;          }          else          {            *outlinep=' '; outlinep++;          }          nextSpaceIsNbsp = PR_TRUE;          templinep++;        } else if('\t' == *templinep) {          // Output 4 "spaces"          for(int spaces=0; spaces<4; spaces++) {            if (nextSpaceIsNbsp)            {              *outlinep='&'; outlinep++;              *outlinep='n'; outlinep++;              *outlinep='b'; outlinep++;              *outlinep='s'; outlinep++;              *outlinep='p'; outlinep++;              *outlinep=';'; outlinep++;            }            else            {              *outlinep=' '; outlinep++;            }            nextSpaceIsNbsp = PR_TRUE;          }          templinep++;        } else {          nextSpaceIsNbsp = firstSpaceNbsp;          *outlinep = *templinep;          outlinep++;          templinep++;        }       } else {        // In tag. Don't change anything        nextSpaceIsNbsp = firstSpaceNbsp;        *outlinep = *templinep;        outlinep++;        templinep++;      }    }    *outlinep='<'; outlinep++;    *outlinep='b'; outlinep++;    *outlinep='r'; outlinep++;    *outlinep='>'; outlinep++;    exdata->inflow = PR_FALSE;  } // End Fixed line  *outlinep='\0'; outlinep++;  PR_Free(templine);  // Calculate linelength as  // <pointer to the next free char>-<pointer to the beginning>-1  // '-1' for the terminating '\0'  if (!(exdata->isSig && quoting))    return MimeObject_write(obj, obj->obuffer, outlinep-obj->obuffer-1, PR_TRUE);  else    return NS_OK;}