void mozTXTToHTMLConv::CompleteAbbreviatedURL(const PRUnichar * aInString, PRInt32 aInLength, const PRUint32 pos, nsString& aOutString) { NS_ASSERTION(PRInt32(pos) < aInLength, "bad args to CompleteAbbreviatedURL, see bug #190851"); if (PRInt32(pos) >= aInLength) return; if (aInString[pos] == '@') { // only pre-pend a mailto url if the string contains a .domain in it.. //i.e. we want to linkify [email protected] but not "let's meet @8pm" nsDependentString inString(aInString, aInLength); if (inString.FindChar('.', pos) != kNotFound) // if we have a '.' after the @ sign.... { aOutString.AssignLiteral("mailto:"); aOutString += aInString; } } else if (aInString[pos] == '.') { if (ItMatchesDelimited(aInString, aInLength, NS_LITERAL_STRING("www.").get(), 4, LT_IGNORE, LT_IGNORE)) { aOutString.AssignLiteral("http://"); aOutString += aInString; } else if (ItMatchesDelimited(aInString,aInLength, NS_LITERAL_STRING("ftp.").get(), 4, LT_IGNORE, LT_IGNORE)) { aOutString.AssignLiteral("ftp://"); aOutString += aInString; } } }
// NOTE: the converted html for the phrase is appended to aOutString // tagHTML and attributeHTML are plain ASCII (literal strings, in fact) bool mozTXTToHTMLConv::StructPhraseHit(const PRUnichar * aInString, PRInt32 aInStringLength, bool col0, const PRUnichar* tagTXT, PRInt32 aTagTXTLen, const char* tagHTML, const char* attributeHTML, nsString& aOutString, PRUint32& openTags) { /* We're searching for the following pattern: LT_DELIMITER - "*" - ALPHA - [ some text (maybe more "*"-pairs) - ALPHA ] "*" - LT_DELIMITER. <strong> is only inserted, if existence of a pair could be verified We use the first opening/closing tag, if we can choose */ const PRUnichar * newOffset = aInString; PRInt32 newLength = aInStringLength; if (!col0) // skip the first element? { newOffset = &aInString[1]; newLength = aInStringLength - 1; } // opening tag if ( ItMatchesDelimited(aInString, aInStringLength, tagTXT, aTagTXTLen, (col0 ? LT_IGNORE : LT_DELIMITER), LT_ALPHA) // is opening tag && NumberOfMatches(newOffset, newLength, tagTXT, aTagTXTLen, LT_ALPHA, LT_DELIMITER) // remaining closing tags > openTags ) { openTags++; aOutString.AppendLiteral("<"); aOutString.AppendASCII(tagHTML); aOutString.Append(PRUnichar(' ')); aOutString.AppendASCII(attributeHTML); aOutString.AppendLiteral("><span class=\"moz-txt-tag\">"); aOutString.Append(tagTXT); aOutString.AppendLiteral("</span>"); return true; } // closing tag else if (openTags > 0 && ItMatchesDelimited(aInString, aInStringLength, tagTXT, aTagTXTLen, LT_ALPHA, LT_DELIMITER)) { openTags--; aOutString.AppendLiteral("<span class=\"moz-txt-tag\">"); aOutString.Append(tagTXT); aOutString.AppendLiteral("</span></"); aOutString.AppendASCII(tagHTML); aOutString.Append(PRUnichar('>')); return true; } return false; }
bool mozTXTToHTMLConv::SmilyHit(const PRUnichar * aInString, PRInt32 aLength, bool col0, const char* tagTXT, const char* imageName, nsString& outputHTML, PRInt32& glyphTextLen) { if ( !aInString || !tagTXT || !imageName ) return false; PRInt32 tagLen = strlen(tagTXT); PRUint32 delim = (col0 ? 0 : 1) + tagLen; if ( (col0 || IsSpace(aInString[0])) && ( aLength <= PRInt32(delim) || IsSpace(aInString[delim]) || (aLength > PRInt32(delim + 1) && ( aInString[delim] == '.' || aInString[delim] == ',' || aInString[delim] == ';' || aInString[delim] == '8' || aInString[delim] == '>' || aInString[delim] == '!' || aInString[delim] == '?' ) && IsSpace(aInString[delim + 1])) ) && ItMatchesDelimited(aInString, aLength, NS_ConvertASCIItoUTF16(tagTXT).get(), tagLen, col0 ? LT_IGNORE : LT_DELIMITER, LT_IGNORE) // Note: tests at different pos for LT_IGNORE and LT_DELIMITER ) { if (!col0) { outputHTML.Truncate(); outputHTML.Append(PRUnichar(' ')); } outputHTML.AppendLiteral("<span class=\""); // <span class=" AppendASCIItoUTF16(imageName, outputHTML); // e.g. smiley-frown outputHTML.AppendLiteral("\" title=\""); // " title=" AppendASCIItoUTF16(tagTXT, outputHTML); // smiley tooltip outputHTML.AppendLiteral("\"><span>"); // "><span> AppendASCIItoUTF16(tagTXT, outputHTML); // original text outputHTML.AppendLiteral("</span></span>"); // </span></span> glyphTextLen = (col0 ? 0 : 1) + tagLen; return true; } return false; }
PRUint32 mozTXTToHTMLConv::NumberOfMatches(const PRUnichar * aInString, PRInt32 aInStringLength, const PRUnichar* rep, PRInt32 aRepLen, LIMTYPE before, LIMTYPE after) { PRUint32 result = 0; for (PRInt32 i = 0; i < aInStringLength; i++) { const PRUnichar * indexIntoString = &aInString[i]; if (ItMatchesDelimited(indexIntoString, aInStringLength - i, rep, aRepLen, before, after)) result++; } return result; }
uint32_t mozTXTToHTMLConv::NumberOfMatches(const char16_t * aInString, int32_t aInStringLength, const char16_t* rep, int32_t aRepLen, LIMTYPE before, LIMTYPE after) { uint32_t result = 0; for (int32_t i = 0; i < aInStringLength; i++) { const char16_t * indexIntoString = &aInString[i]; if (ItMatchesDelimited(indexIntoString, aInStringLength - i, rep, aRepLen, before, after)) result++; } return result; }
// the glyph is appended to aOutputString instead of the original string... bool mozTXTToHTMLConv::GlyphHit(const PRUnichar * aInString, PRInt32 aInLength, bool col0, nsString& aOutputString, PRInt32& glyphTextLen) { PRUnichar text0 = aInString[0]; PRUnichar text1 = aInString[1]; PRUnichar firstChar = (col0 ? text0 : text1); // temporary variable used to store the glyph html text nsAutoString outputHTML; bool bTestSmilie; bool bArg = false; int i; // refactor some of this mess to avoid code duplication and speed execution a bit // there are two cases that need to be tried one after another. To avoid a lot of // duplicate code, rolling into a loop i = 0; while ( i < 2 ) { bTestSmilie = false; if ( !i && (firstChar == ':' || firstChar == ';' || firstChar == '=' || firstChar == '>' || firstChar == '8' || firstChar == 'O')) { // first test passed bTestSmilie = true; bArg = col0; } if ( i && col0 && ( text1 == ':' || text1 == ';' || text1 == '=' || text1 == '>' || text1 == '8' || text1 == 'O' ) ) { // second test passed bTestSmilie = true; bArg = false; } if ( bTestSmilie && ( SmilyHit(aInString, aInLength, bArg, ":-)", "moz-smiley-s1", // smile outputHTML, glyphTextLen) || SmilyHit(aInString, aInLength, bArg, ":)", "moz-smiley-s1", // smile outputHTML, glyphTextLen) || SmilyHit(aInString, aInLength, bArg, ":-D", "moz-smiley-s5", // laughing outputHTML, glyphTextLen) || SmilyHit(aInString, aInLength, bArg, ":-(", "moz-smiley-s2", // frown outputHTML, glyphTextLen) || SmilyHit(aInString, aInLength, bArg, ":(", "moz-smiley-s2", // frown outputHTML, glyphTextLen) || SmilyHit(aInString, aInLength, bArg, ":-[", "moz-smiley-s6", // embarassed outputHTML, glyphTextLen) || SmilyHit(aInString, aInLength, bArg, ";-)", "moz-smiley-s3", // wink outputHTML, glyphTextLen) || SmilyHit(aInString, aInLength, col0, ";)", "moz-smiley-s3", // wink outputHTML, glyphTextLen) || SmilyHit(aInString, aInLength, bArg, ":-\\", "moz-smiley-s7", // undecided outputHTML, glyphTextLen) || SmilyHit(aInString, aInLength, bArg, ":-P", "moz-smiley-s4", // tongue outputHTML, glyphTextLen) || SmilyHit(aInString, aInLength, bArg, ";-P", "moz-smiley-s4", // tongue outputHTML, glyphTextLen) || SmilyHit(aInString, aInLength, bArg, "=-O", "moz-smiley-s8", // surprise outputHTML, glyphTextLen) || SmilyHit(aInString, aInLength, bArg, ":-*", "moz-smiley-s9", // kiss outputHTML, glyphTextLen) || SmilyHit(aInString, aInLength, bArg, ">:o", "moz-smiley-s10", // yell outputHTML, glyphTextLen) || SmilyHit(aInString, aInLength, bArg, ">:-o", "moz-smiley-s10", // yell outputHTML, glyphTextLen) || SmilyHit(aInString, aInLength, bArg, "8-)", "moz-smiley-s11", // cool outputHTML, glyphTextLen) || SmilyHit(aInString, aInLength, bArg, ":-$", "moz-smiley-s12", // money outputHTML, glyphTextLen) || SmilyHit(aInString, aInLength, bArg, ":-!", "moz-smiley-s13", // foot outputHTML, glyphTextLen) || SmilyHit(aInString, aInLength, bArg, "O:-)", "moz-smiley-s14", // innocent outputHTML, glyphTextLen) || SmilyHit(aInString, aInLength, bArg, ":'(", "moz-smiley-s15", // cry outputHTML, glyphTextLen) || SmilyHit(aInString, aInLength, bArg, ":-X", "moz-smiley-s16", // sealed outputHTML, glyphTextLen) ) ) { aOutputString.Append(outputHTML); return true; } i++; } if (text0 == '\f') { aOutputString.AppendLiteral("<span class='moz-txt-formfeed'></span>"); glyphTextLen = 1; return true; } if (text0 == '+' || text1 == '+') { if (ItMatchesDelimited(aInString, aInLength, NS_LITERAL_STRING(" +/-").get(), 4, LT_IGNORE, LT_IGNORE)) { aOutputString.AppendLiteral(" ±"); glyphTextLen = 4; return true; } if (col0 && ItMatchesDelimited(aInString, aInLength, NS_LITERAL_STRING("+/-").get(), 3, LT_IGNORE, LT_IGNORE)) { aOutputString.AppendLiteral("±"); glyphTextLen = 3; return true; } } // x^2 => x<sup>2</sup>, also handle powers x^-2, x^0.5 // implement regular expression /[\dA-Za-z\)\]}]\^-?\d+(\.\d+)*[^\dA-Za-z]/ if ( text1 == '^' && ( nsCRT::IsAsciiDigit(text0) || nsCRT::IsAsciiAlpha(text0) || text0 == ')' || text0 == ']' || text0 == '}' ) && ( (2 < aInLength && nsCRT::IsAsciiDigit(aInString[2])) || (3 < aInLength && aInString[2] == '-' && nsCRT::IsAsciiDigit(aInString[3])) ) ) { // Find first non-digit PRInt32 delimPos = 3; // skip "^" and first digit (or '-') for (; delimPos < aInLength && ( nsCRT::IsAsciiDigit(aInString[delimPos]) || (aInString[delimPos] == '.' && delimPos + 1 < aInLength && nsCRT::IsAsciiDigit(aInString[delimPos + 1])) ); delimPos++) ; if (delimPos < aInLength && nsCRT::IsAsciiAlpha(aInString[delimPos])) { return false; } outputHTML.Truncate(); outputHTML += text0; outputHTML.AppendLiteral( "<sup class=\"moz-txt-sup\">" "<span style=\"display:inline-block;width:0;height:0;overflow:hidden\">" "^</span>"); aOutputString.Append(outputHTML); aOutputString.Append(&aInString[2], delimPos - 2); aOutputString.AppendLiteral("</sup>"); glyphTextLen = delimPos /* - 1 + 1 */ ; return true; } /* The following strings are not substituted: |TXT |HTML |Reason +------+---------+---------- -> ← Bug #454 => ⇐ dito <- → dito <= ⇒ dito (tm) ™ dito 1/4 ¼ is triggered by 1/4 Part 1, 2/4 Part 2, ... 3/4 ¾ dito 1/2 ½ similar */ return false; }