diff options
Diffstat (limited to 'plugins/IEView/src/TextToken.cpp')
| -rw-r--r-- | plugins/IEView/src/TextToken.cpp | 824 | 
1 files changed, 824 insertions, 0 deletions
diff --git a/plugins/IEView/src/TextToken.cpp b/plugins/IEView/src/TextToken.cpp new file mode 100644 index 0000000000..56512ac119 --- /dev/null +++ b/plugins/IEView/src/TextToken.cpp @@ -0,0 +1,824 @@ +/*
 +
 +IEView Plugin for Miranda IM
 +Copyright (C) 2005-2010  Piotr Piastucki
 +
 +This program is free software; you can redistribute it and/or
 +modify it under the terms of the GNU General Public License
 +as published by the Free Software Foundation; either version 2
 +of the License, or (at your option) any later version.
 +
 +This program is distributed in the hope that it will be useful,
 +but WITHOUT ANY WARRANTY; without even the implied warranty of
 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +GNU General Public License for more details.
 +
 +You should have received a copy of the GNU General Public License
 +along with this program; if not, write to the Free Software
 +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 +
 +*/
 +#include "TextToken.h"
 +#include "m_MathModule.h"
 +//#include "m_metacontacts.h"
 +#include "Utils.h"
 +
 +TextToken::TextToken(int type, const char *text, int len) {
 +	next = NULL;
 +	tag = 0;
 +	end = false;
 +	this->type = type;
 +	this->text = Utils::dupString(text, len);
 +	this->wtext = Utils::convertToWCS(this->text);
 +	this->link = NULL;
 +	this->wlink = NULL;
 +}
 +
 +TextToken::TextToken(int type, const wchar_t *wtext, int len) {
 +	next = NULL;
 +	tag = 0;
 +	end = false;
 +	this->type = type;
 +	this->wtext = Utils::dupString(wtext, len);
 +	this->text = Utils::convertToString(this->wtext);
 +	this->link = NULL;
 +	this->wlink = NULL;
 +}
 +
 +TextToken::~TextToken() {
 +	if (text!=NULL) {
 +		delete text;
 +	}
 +	if (wtext!=NULL) {
 +		delete wtext;
 +	}
 +	if (link!=NULL) {
 +		delete link;
 +	}
 +	if (wlink!=NULL) {
 +		delete wlink;
 +	}
 +}
 +
 +TextToken * TextToken::getNext() {
 +	return next;
 +}
 +
 +void TextToken::setNext(TextToken *ptr) {
 +	next = ptr;
 +}
 +
 +int TextToken::getType() {
 +	return type;
 +}
 +
 +const char *TextToken::getText() {
 +	return text;
 +}
 +
 +const wchar_t *TextToken::getTextW() {
 +	return wtext;
 +}
 +
 +int TextToken::getTag() {
 +	return tag;
 +}
 +
 +void TextToken::setTag(int tag) {
 +	this->tag = tag;
 +}
 +
 +bool TextToken::isEnd() {
 +	return end;
 +}
 +
 +void TextToken::setEnd(bool b) {
 +	this->end = b;
 +}
 +
 +const char *TextToken::getLink() {
 +	return link;
 +}
 +
 +const wchar_t *TextToken::getLinkW() {
 +	return wlink;
 +}
 +
 +void TextToken::setLink(const char *link) {
 +	if (this->link != NULL) {
 +		delete this->link;
 +	}
 +	if (this->wlink != NULL) {
 +		delete this->wlink;
 +	}
 +	this->link = Utils::dupString(link);
 +	this->wlink = Utils::convertToWCS(link);
 +}
 +
 +void TextToken::setLink(const wchar_t *link) {
 +	if (this->link != NULL) {
 +		delete this->link;
 +	}
 +	if (this->wlink != NULL) {
 +		delete this->wlink;
 +	}
 +	this->link = Utils::convertToString(link);
 +	this->wlink = Utils::dupString(link);
 +}
 +
 +static int countNoWhitespace(const wchar_t *str) {
 +	int c;
 +	for (c=0; *str!='\n' && *str!='\r' && *str!='\t' && *str!=' ' && *str!='\0'; str++, c++);
 +	return c;
 +}
 +
 +TextToken* TextToken::tokenizeBBCodes(const wchar_t *text) {
 +	return tokenizeBBCodes(text, (int)wcslen(text));
 +}
 +
 +TextToken* TextToken::tokenizeMath(const wchar_t *text) {
 +	TextToken *firstToken = NULL, *lastToken = NULL, *mathToken = NULL;
 +	static bool     mathModInitialized = false;
 +	static wchar_t *mathTagName[] = {NULL, NULL};
 +	static int      mathTagLen[] = {0, 0};
 +	int i;
 +	if (!mathModInitialized) {
 +		if (ServiceExists(MATH_GET_PARAMS)) {
 +			char* mthDelStart =  (char *)CallService(MATH_GET_PARAMS, (WPARAM)MATH_PARAM_STARTDELIMITER, 0);
 +			char* mthDelEnd   =  (char *)CallService(MATH_GET_PARAMS, (WPARAM)MATH_PARAM_ENDDELIMITER, 0);
 +			if (mthDelStart!=NULL) {
 +				mathTagName[0] = Utils::convertToWCS(mthDelStart);
 +				mathTagLen[0] = (int)wcslen(mathTagName[0]);
 +			}
 +			if (mthDelEnd!=NULL) {
 +				mathTagName[1] = Utils::convertToWCS(mthDelEnd);
 +				mathTagLen[1] = (int)wcslen(mathTagName[1]);
 +			}
 +			CallService(MTH_FREE_MATH_BUFFER,0, (LPARAM) mthDelStart);
 +			CallService(MTH_FREE_MATH_BUFFER,0, (LPARAM) mthDelEnd);
 +		}
 +		mathModInitialized = true;
 +	}
 +	int textLen = 0;
 +	int l = (int)wcslen(text);
 +	for (i=0; i<=l;) {
 +		bool mathFound = false;
 +		int k = 0, tagDataStart=0, newTokenType = 0, newTokenSize = 0;
 +		if (mathTagName[0] != NULL && mathTagName[1] != NULL) {
 +			if (!wcsnicmp(text+i, mathTagName[0], mathTagLen[0])) {
 +				k = tagDataStart = i + mathTagLen[0];
 +				for (; k < l; k++) {
 +					if (!wcsnicmp(text+k, mathTagName[1], mathTagLen[1])) {
 +						k += mathTagLen[1];
 +						mathFound = true;
 +						break;
 +					}
 +				}
 +			}
 +		}
 +		if (mathFound) {
 +			mathToken = new TextToken(MATH, text + tagDataStart, k - mathTagLen[1] - tagDataStart);
 +			char* mathPath=(char*)CallService(MTH_GET_GIF_UNICODE, 0, (LPARAM) mathToken->getTextW());
 +			if (mathPath!=NULL) {
 +				mathToken->setLink(mathPath);
 +				CallService(MTH_FREE_GIFPATH, 0, (LPARAM) mathPath);
 +			} else {
 +				mathToken->setLink("");
 +			}
 +			mathToken->setEnd(false);
 +			newTokenType = MATH;
 +			newTokenSize = k - i;
 +		} else {
 +			if (i==l) {
 +				newTokenType = END;
 +				newTokenSize = 1;
 +			} else {
 +				newTokenType = TEXT;
 +				newTokenSize = 1;
 +			}
 +		}
 +		if (newTokenType != TEXT) {
 +			if (textLen >0 ) {
 +				TextToken *newToken = new TextToken(TEXT, text+i-textLen, textLen);
 +				textLen = 0;
 +				if (lastToken == NULL) {
 +					firstToken = newToken;
 +				} else {
 +					lastToken->setNext(newToken);
 +				}
 +				lastToken = newToken;
 +			}
 +			if (newTokenType == MATH) {
 +				if (lastToken == NULL) {
 +					firstToken = mathToken;
 +				} else {
 +					lastToken->setNext(mathToken);
 +				}
 +				lastToken = mathToken;
 +			}
 +		} else {
 +			textLen += newTokenSize;
 +		}
 +		i += newTokenSize;
 +	}
 +	return firstToken;
 +}
 +// TODO: Add the following BBCodes: code
 +#define BB_TAG_NUM 10
 +TextToken* TextToken::tokenizeBBCodes(const wchar_t *text, int l) {
 +	static const wchar_t *bbTagName[] = {L"b", L"i", L"u", L"s", L"img", L"color", L"size", L"bimg", L"url", L"code"};
 +	static int 		bbTagNameLen[] = {1, 1, 1, 1, 3, 5, 4, 4, 3, 4};
 +	static int 		bbTagArg[] = {0, 0, 0, 0, 0, 1, 1, 0, 1, 0};
 +	static int 		bbTagId[] = {BB_B, BB_I, BB_U, BB_S, BB_IMG, BB_COLOR, BB_SIZE, BB_BIMG, BB_URL, BB_CODE};
 +	static int      bbTagEnd[BB_TAG_NUM];
 +	static int      bbTagCount[BB_TAG_NUM];
 +	int i,j;
 +	TextToken *firstToken = NULL, *lastToken = NULL, * bbToken = NULL;
 +	int textLen = 0;
 +	for (j = 0; j < BB_TAG_NUM; j++) {
 +		bbTagCount[j] = 0;
 +		bbTagEnd[j] = 0;
 +	}
 +	for (i = 0; i <= l;) {
 +		int k, tagArgStart=0, tagArgEnd=0, tagDataStart=0, newTokenType = 0, newTokenSize = 0;
 +		bool bbFound = false;
 +		if (text[i] == '[') {
 +			if (text[i+1] != '/') {
 +				for (j = 0; j < BB_TAG_NUM; j++) {
 +					k = i + 1;
 +					if (!wcsnicmp(text+k, bbTagName[j], bbTagNameLen[j])) {
 +						tagArgStart = tagArgEnd = 0;
 +						k += bbTagNameLen[j];
 +						if (bbTagArg[j]) {
 +							if (text[k] != '=') continue;
 +							k++;
 +							tagArgStart = k;
 +							for (; text[k]!='\0'; k++) {
 +								if (text[k]==']') break;
 +							}
 +							tagArgEnd = k;
 +						}
 +						if (text[k] == ']') {
 +							k++;
 +							tagDataStart = k;
 +							if (k < bbTagEnd[j]) k = bbTagEnd[j];
 +							for (; k < l; k++) {
 +								if (text[k] == '[' && text[k+1] == '/') {
 +									k += 2;
 +									if (!wcsnicmp(text+k, bbTagName[j], bbTagNameLen[j])) {
 +										k += bbTagNameLen[j];
 +										if (text[k] == ']') {
 +											k++;
 +											bbFound = true;
 +											break;
 +										}
 +									}
 +								}
 +							}
 +							if (bbFound) break;
 +						}
 +					}
 +				}
 +				if (bbFound) {
 +					bbTagEnd[j] = k;
 +					switch (bbTagId[j]) {
 +					case BB_B:
 +					case BB_I:
 +					case BB_U:
 +					case BB_S:
 +					case BB_CODE:
 +					case BB_COLOR:
 +					case BB_SIZE:
 +						bbTagCount[j]++;
 +						if (bbTagArg[j]) {
 +							bbToken = new TextToken(BBCODE, text + tagArgStart, tagArgEnd - tagArgStart);
 +						} else {
 +							bbToken = new TextToken(BBCODE, bbTagName[j], bbTagNameLen[j]);
 +						}
 +						bbToken->setTag(bbTagId[j]);
 +						bbToken->setEnd(false);
 +						newTokenType = BBCODE;
 +						newTokenSize = tagDataStart - i;
 +						break;
 +					case BB_URL:
 +					case BB_IMG:
 +					case BB_BIMG:
 +						bbToken = new TextToken(BBCODE, text + tagDataStart, k - bbTagNameLen[j] - 3 - tagDataStart);
 +						bbToken->setTag(bbTagId[j]);
 +						bbToken->setEnd(false);
 +						newTokenType = BBCODE;
 +						newTokenSize = k - i;
 +						if (bbTagArg[j]) {
 +							wchar_t *urlLink = 	Utils::dupString(text + tagArgStart, tagArgEnd - tagArgStart);
 +							bbToken->setLink(urlLink);
 +							delete urlLink;
 +						}
 +						break;
 +					}
 +				}
 +			} else {
 +				for (j = 0; j < BB_TAG_NUM; j++) {
 +					k = i + 2;
 +					if (bbTagCount[j]>0 && !wcsnicmp(text+k, bbTagName[j], bbTagNameLen[j])) {
 +						k += bbTagNameLen[j];
 +						if (text[k] == ']') {
 +							k++;
 +							bbFound = true;
 +							break;
 +						}
 +					}
 +				}
 +				if (bbFound) {
 +					bbTagCount[j]--;
 +					bbToken = new TextToken(BBCODE, bbTagName[j], bbTagNameLen[j]);
 +					bbToken->setEnd(true);
 +					bbToken->setTag(bbTagId[j]);
 +					newTokenType = BBCODE;
 +					newTokenSize = k - i;
 +				}
 +			}
 +		}
 +		if (!bbFound) {
 +			if (i==l) {
 +				newTokenType = END;
 +				newTokenSize = 1;
 +			} else {
 +				newTokenType = TEXT;
 +				newTokenSize = 1;
 +			}
 +		}
 +		if (newTokenType != TEXT) {
 +			if (textLen >0 ) {
 +				TextToken *newToken = new TextToken(TEXT, text+i-textLen, textLen);
 +				textLen = 0;
 +				if (lastToken == NULL) {
 +					firstToken = newToken;
 +				} else {
 +					lastToken->setNext(newToken);
 +				}
 +				lastToken = newToken;
 +			}
 +			if (newTokenType == BBCODE) {
 +				if (lastToken == NULL) {
 +					firstToken = bbToken;
 +				} else {
 +					lastToken->setNext(bbToken);
 +				}
 +				lastToken = bbToken;
 +			}
 +		} else {
 +			textLen += newTokenSize;
 +		}
 +		i += newTokenSize;
 +	}
 +	return firstToken;
 +}
 +
 +TextToken* TextToken::tokenizeLinks(const wchar_t *text) {
 +	TextToken *firstToken = NULL, *lastToken = NULL;
 +	int textLen = 0;
 +	int l = (int)wcslen(text);
 +	for (int i=0; i<=l;) {
 +		int newTokenType, newTokenSize;
 +		int urlLen = Utils::detectURL(text+i);
 +		if (i == l) {
 +			newTokenType = END;
 +			newTokenSize = 1;
 +		} else if (urlLen > 0) {
 +			newTokenType = LINK;
 +			newTokenSize = urlLen;
 +		} else if (!wcsncmp(text+i, L"www.", 4)) {
 +			newTokenType = WWWLINK;
 +			newTokenSize = countNoWhitespace(text+i);
 +	 	} else if (!wcsncmp(text+i, L"mailto:", 7)) {
 +			newTokenType = LINK;
 +			newTokenSize = countNoWhitespace(text+i);
 +		} else {
 +			newTokenType = TEXT;
 +			newTokenSize = 1;
 +		}
 +		if (newTokenType != TEXT) {
 +			if (textLen >0 ) {
 +				TextToken *newToken = new TextToken(TEXT, text+i-textLen, textLen);
 +				textLen = 0;
 +				if (lastToken == NULL) {
 +					firstToken = newToken;
 +				} else {
 +					lastToken->setNext(newToken);
 +				}
 +				lastToken = newToken;
 +			}
 +			if (newTokenType == WWWLINK || newTokenType == LINK) {
 +				TextToken *newToken = new TextToken(newTokenType, text+i, newTokenSize);
 +				newToken->setLink(newToken->getText());
 +				if (lastToken == NULL) {
 +					firstToken = newToken;
 +				} else {
 +					lastToken->setNext(newToken);
 +				}
 +				lastToken = newToken;
 +			}
 +		} else {
 +			textLen += newTokenSize;
 +		}
 +		i += newTokenSize;
 +	}
 +	return firstToken;
 +}
 +
 +TextToken* TextToken::tokenizeSmileys(HANDLE hContact, const char *proto, const wchar_t *text, bool isSent) {
 +	TextToken *firstToken = NULL, *lastToken = NULL;
 +	SMADD_BATCHPARSE2 sp;
 +	SMADD_BATCHPARSERES *spRes;
 +	int l = (int)wcslen(text);
 +	if (!Options::isSmileyAdd()) {
 +		return new TextToken(TEXT, text, l);
 +	}
 +	sp.cbSize = sizeof(sp);
 +	sp.Protocolname = proto;
 +	sp.flag = SAFL_PATH | SAFL_UNICODE | (isSent ? SAFL_OUTGOING : 0);
 +	sp.wstr = (wchar_t *)text;
 +	sp.hContact = hContact;
 +	spRes = (SMADD_BATCHPARSERES *) CallService(MS_SMILEYADD_BATCHPARSE, 0, (LPARAM)&sp);
 +	int last_pos = 0;
 +	if (spRes != NULL) {
 +		for (int i = 0; i < (int)sp.numSmileys; i++) {
 +			if (spRes[i].filepath != NULL && strlen((char *)spRes[i].filepath) > 0) {
 +				if ((int)spRes[i].startChar - last_pos > 0) {
 +					TextToken *newToken = new TextToken(TEXT, text+last_pos, spRes[i].startChar-last_pos);
 +					if (lastToken == NULL) {
 +						firstToken = newToken;
 +					} else {
 +						lastToken->setNext(newToken);
 +					}
 +					lastToken = newToken;
 +				}
 +				TextToken *newToken = new TextToken(SMILEY, text+spRes[i].startChar, spRes[i].size);
 +				if (sp.oflag & SAFL_UNICODE) {
 +					newToken->setLink((wchar_t *)spRes[i].filepath);
 +				} else {
 +					newToken->setLink((char *)spRes[i].filepath);
 +				}
 +				if (lastToken == NULL) {
 +					firstToken = newToken;
 +				} else {
 +					lastToken->setNext(newToken);
 +				}
 +				lastToken = newToken;
 +				last_pos = spRes[i].startChar + spRes[i].size;
 +			}
 +		}
 +		CallService(MS_SMILEYADD_BATCHFREE, 0, (LPARAM)spRes);
 +	}
 +	if (last_pos < l)  {
 +		TextToken *newToken = new TextToken(TEXT, text+last_pos, l-last_pos);
 +		if (lastToken == NULL) {
 +			firstToken = newToken;
 +		} else {
 +			lastToken->setNext(newToken);
 +		}
 +		lastToken = newToken;
 +	}
 +	return firstToken;
 +}
 +
 +TextToken* TextToken::tokenizeChatFormatting(const wchar_t *text) {
 +	TextToken *firstToken = NULL, *lastToken = NULL;
 +	int textLen = 0;
 +	int l = (int)wcslen(text);
 +	wchar_t* tokenBuffer = new wchar_t[l + 1];
 +	for (int i=0; i<=l;) {
 +		int newTokenType = TEXT;
 +		int newTokenSize = 1;
 +		int newTokenTag = 0;
 +		int newTokenTextLen = 0;
 +		const wchar_t * newTokenText = NULL;
 +		bool endToken = false;
 +
 +
 +		if (i==l) {
 +			newTokenType = END;
 +		} else {
 +			if (text[i] == '%') {
 +				newTokenSize = 2;
 +				switch (text[i + 1]) {
 +					case '%':
 +						break;
 +					case 'B':
 +						endToken = true;
 +					case 'b':
 +						newTokenType = BBCODE;
 +						newTokenTag = BB_B;
 +						break;
 +					case 'U':
 +						endToken = true;
 +					case 'u':
 +						newTokenType = BBCODE;
 +						newTokenTag = BB_U;
 +						break;
 +					case 'I':
 +						endToken = true;
 +					case 'i':
 +						newTokenType = BBCODE;
 +						newTokenTag = BB_I;
 +						break;
 +					case 'C':
 +						endToken = true;
 +					case 'c':
 +						newTokenType = BBCODE;
 +						newTokenTag = BB_COLOR;
 +						if (!endToken) {
 +							newTokenText = text + i + 2;
 +							newTokenTextLen = 7;
 +							newTokenSize = 9;
 +						}
 +						break;
 +					case 'F':
 +						endToken = true;
 +					case 'f':
 +						newTokenType = BBCODE;
 +						newTokenTag = BB_BACKGROUND;
 +						if (!endToken) {
 +							newTokenText = text + i + 2;
 +							newTokenTextLen = 7;
 +							newTokenSize = 9;
 +						}
 +						break;
 +					default:
 +						newTokenSize = 1;
 +				}
 +			}
 +		}
 +		if (newTokenType != TEXT) {
 +			if (textLen >0 ) {
 +				TextToken *newToken = new TextToken(TEXT, tokenBuffer, textLen);
 +				textLen = 0;
 +				if (lastToken == NULL) {
 +					firstToken = newToken;
 +				} else {
 +					lastToken->setNext(newToken);
 +				}
 +				lastToken = newToken;
 +			}
 +			if (newTokenType == BBCODE) {
 +				TextToken *newToken = new TextToken(newTokenType, newTokenText, newTokenTextLen);
 +				newToken->setEnd(endToken);
 +				newToken->setTag(newTokenTag);
 +				if (lastToken == NULL) {
 +					firstToken = newToken;
 +				} else {
 +					lastToken->setNext(newToken);
 +				}
 +				lastToken = newToken;
 +			}
 +		} else {
 +			tokenBuffer[textLen] = text[i];
 +			textLen++;
 +		}
 +		i += newTokenSize;
 +	}
 +	return firstToken;
 +}
 +
 +wchar_t *TextToken::htmlEncode(const wchar_t *str) {
 +	wchar_t *out;
 +	const wchar_t *ptr;
 +	bool wasSpace;
 +	int c;
 +	c = 0;
 +	wasSpace = false;
 +	for (ptr=str; *ptr!='\0'; ptr++) {
 +		if (*ptr==' ' && wasSpace) {
 +			wasSpace = true;
 +			c += 6;
 +		} else {
 +			wasSpace = false;
 +			switch (*ptr) {
 +				case '\n': c += 4; break;
 +				case '\r': break;
 +				case '&': c += 5; break;
 +				case '>': c += 4; break;
 +				case '<': c += 4; break;
 +				case '"': c += 6; break;
 +				case ' ': wasSpace = true;
 +				default: c += 1; break;
 +			}
 +		}
 +	}
 +	wchar_t *output = new wchar_t[c+1];
 +	wasSpace = false;
 +	for (out=output, ptr=str; *ptr!='\0'; ptr++) {
 +		if (*ptr==' ' && wasSpace) {
 +			wcscpy(out, L" ");
 +			out += 6;
 +		} else {
 +			wasSpace = false;
 +			switch (*ptr) {
 +				case '\n': wcscpy(out, L"<br>"); out += 4; break;
 +				case '\r': break;
 +				case '&': wcscpy(out, L"&"); out += 5; break;
 +				case '>': wcscpy(out, L">"); out += 4; break;
 +				case '<': wcscpy(out, L"<"); out += 4; break;
 +				case '"': wcscpy(out, L"""); out += 6; break;
 +				case ' ': wasSpace = true;
 +				default: *out = *ptr; out += 1; break;
 +			}
 +		}
 +	}
 +	*out  = '\0';
 +	return output;
 +}
 +
 +void TextToken::toString(wchar_t **str, int *sizeAlloced) {
 +	wchar_t *eText = NULL, *eLink = NULL;
 +	switch (type) {
 +		case TEXT:
 +			eText = htmlEncode(wtext);
 +			Utils::appendText(str, sizeAlloced, L"%s", eText);
 +			break;
 +		case WWWLINK:
 +		case LINK:
 +			{
 +				eText = htmlEncode(wtext);
 +				eLink = htmlEncode(wlink);
 +				const wchar_t *linkPrefix = type == WWWLINK ? L"http://" : L"";
 +				if ((Options::getGeneralFlags()&Options::GENERAL_ENABLE_EMBED)) {
 +					wchar_t *match = wcsstr(wlink, L"youtube.com");
 +					if (match != NULL) {
 +						match = wcsstr(match + 11, L"v=");
 +						if (match != NULL) {
 +							match += 2;
 +							wchar_t *match2 = wcsstr(match, L"&");
 +							int len = match2 != NULL ? match2 - match : (int)wcslen(match);
 +							match = mir_wstrdup(match);
 +							match[len] = 0;
 +							int width ;
 +							int height;
 +							int Embedsize = Options::getEmbedsize();
 +							switch (Embedsize){
 +							case 0:
 +								width = 320;
 +								height = 205;
 +								break;
 +							case 1:
 +								width = 480;
 +								height = 385;
 +								break;
 +							case 2:
 +								width = 560;
 +								height = 349;
 +								break;
 +							case 3:
 +								width = 640;
 +								height = 390;
 +								break;
 +
 +							};
 +
 +							Utils::appendText(str, sizeAlloced, L"<div><object width=\"%d\" height=\"%d\">\
 +																	 <param name=\"movie\" value=\"http://www.youtube.com/v/%s&feature=player_embedded&version=3\"/>\
 +																 <param name=\"allowFullScreen\" value=\"true\"/>\
 +																 <param name=\"allowScriptAccess\" value=\"true\"/>\
 +																 <embed src=\"http://www.youtube.com/v/%s&feature=player_embedded&version=3\" type=\"application/x-shockwave-flash\" allowfullscreen=\"true\" allowScriptAccess=\"always\" width=\"%d\" height=\"%d\"/>\
 +																 </object></div>", width, height, match, match, width, height);
 +							mir_free(match);
 +							break;
 +						}
 +					}
 +				}
 +				Utils::appendText(str, sizeAlloced, L"<a class=\"link\" target=\"_self\" href=\"%s%s\">%s</a>", linkPrefix, eLink, eText);
 +			}
 +			break;
 +		case SMILEY:
 +			eText = htmlEncode(wtext);
 +			if ((Options::getGeneralFlags()&Options::GENERAL_ENABLE_FLASH) && (wcsstr(wlink, L".swf")!=NULL)) {
 +				Utils::appendText(str, sizeAlloced,
 +		L"<span title=\"%s\" class=\"img\"><object classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" \
 +		codebase=\"http://active.macromedia.com/flash2/cabs/swflash.cab#version=4,0,0,0\" >\
 +		<param NAME=\"movie\" VALUE=\"%s\"><param NAME=\"quality\" VALUE=\"high\"><PARAM NAME=\"loop\" VALUE=\"true\"></object></span><span style=\"position:absolute; visibility:hidden;\">%s</span>",
 +				wlink, eText);
 +			} else if ((Options::getGeneralFlags()&Options::GENERAL_ENABLE_PNGHACK) && (wcsstr(wlink, L".png")!=NULL)) {
 +				Utils::appendText(str, sizeAlloced, L"<img class=\"img\" style=\"height:1px;width:1px;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%s',sizingMethod='image');\" alt=\"%s\"/><span style=\"position:absolute; visibility:hidden;\">%s</span>", wlink, eText, eText);
 +			} else {
 +				Utils::appendText(str, sizeAlloced, L"<img class=\"img\" src=\"file://%s\" alt=\"%s\" /><span style=\"position:absolute; visibility:hidden;\">%s</span>", wlink, eText, eText);
 +			}
 +			break;
 +		case MATH:
 +			eText = htmlEncode(wtext);
 +			if ((Options::getGeneralFlags()&Options::GENERAL_ENABLE_PNGHACK) && (wcsstr(wlink, L".png")!=NULL)) {
 +				Utils::appendText(str, sizeAlloced, L"<img class=\"img\" style=\"height:1px;width:1px;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%s',sizingMethod='image');\"  alt=\"%s\" /><span style=\"position:absolute; visibility:hidden;\">%s</span>",wlink , eText, eText);
 +			} else {
 +				Utils::appendText(str, sizeAlloced, L"<img class=\"img\" src=\"file://%s\" alt=\"%s\" /><span style=\"position:absolute; visibility:hidden;\">%s</span>", wlink, eText, eText);
 +			}
 +			break;
 +		case BBCODE:
 +			if (!end) {
 +				switch (tag) {
 +				case BB_B:
 +					//Utils::appendText(str, sizeAlloced, L"<span style=\"font-weight: bold;\">");
 +					Utils::appendText(str, sizeAlloced, L"<b>");
 +					break;
 +				case BB_I:
 +					//Utils::appendText(str, sizeAlloced, L"<span style=\"font-style: italic;\">");
 +					Utils::appendText(str, sizeAlloced, L"<i>");
 +					break;
 +				case BB_U:
 +					//Utils::appendText(str, sizeAlloced, L"<span style=\"text-decoration: underline;\">");
 +					Utils::appendText(str, sizeAlloced, L"<u>");
 +					break;
 +				case BB_S:
 +					//Utils::appendText(str, sizeAlloced, L"<span style=\"font-style: italic;\">");
 +					Utils::appendText(str, sizeAlloced, L"<s>");
 +					break;
 +				case BB_CODE:
 +					//Utils::appendText(str, sizeAlloced, L"<span style=\"font-style: italic;\">");
 +					Utils::appendText(str, sizeAlloced, L"<pre class=\"code\">");
 +					break;
 +				case BB_IMG:
 +					eText = htmlEncode(wtext);
 +					if ((Options::getGeneralFlags()&Options::GENERAL_ENABLE_FLASH) && (wcsstr(eText, L".swf")!=NULL)) {
 +						Utils::appendText(str, sizeAlloced,
 +		L"<div style=\"width: 100%%; border: 0; overflow: hidden;\"><object classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" \
 +		codebase=\"http://active.macromedia.com/flash2/cabs/swflash.cab#version=4,0,0,0\" width=\"100%%\" >\
 +		<param NAME=\"movie\" VALUE=\"%s\"><param NAME=\"quality\" VALUE=\"high\"><PARAM NAME=\"loop\" VALUE=\"true\"></object></div>",
 +						eText);
 +					} else if ((Options::getGeneralFlags()&Options::GENERAL_ENABLE_PNGHACK) && (wcsstr(eText, L".png")!=NULL)) {
 +						Utils::appendText(str, sizeAlloced, L"<img class=\"img\" style=\"height:1px;width:1px;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%s',sizingMethod='image');\" />", eText);
 +					} else {
 +						if (wcsncmp(eText, L"http://", 7)) {
 +							Utils::appendText(str, sizeAlloced, L"<div style=\"width: 100%%; border: 0; overflow: hidden;\"><img class=\"img\" style=\"width: expression((maxw = this.parentNode.offsetWidth ) > this.width ? 'auto' : maxw);\" src=\"file://%s\" /></div>", eText);
 +						} else {
 +							Utils::appendText(str, sizeAlloced, L"<div style=\"width: 100%%; border: 0; overflow: hidden;\"><img class=\"img\" style=\"width: expression((maxw = this.parentNode.offsetWidth ) > this.width ? 'auto' : maxw);\" src=\"%s\" /></div>", eText);
 +						}
 +					}
 +					break;
 +				case BB_BIMG:
 +					{
 +						wchar_t *absolutePath = Utils::toAbsolute(wtext);
 +						eText = htmlEncode(absolutePath);
 +						delete absolutePath;
 +					}
 +					if ((Options::getGeneralFlags()&Options::GENERAL_ENABLE_FLASH) && (wcsstr(eText, L".swf")!=NULL)) {
 +						Utils::appendText(str, sizeAlloced,
 +		L"<div style=\"width: 100%%; border: 0; overflow: hidden;\"><object classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" \
 +		codebase=\"http://active.macromedia.com/flash2/cabs/swflash.cab#version=4,0,0,0\" width=\"100%%\" >\
 +		<param NAME=\"movie\" VALUE=\"%s\"><param NAME=\"quality\" VALUE=\"high\"><PARAM NAME=\"loop\" VALUE=\"true\"></object></div>",
 +						eText);
 +					} else if ((Options::getGeneralFlags()&Options::GENERAL_ENABLE_PNGHACK) && (wcsstr(eText, L".png")!=NULL)) {
 +						Utils::appendText(str, sizeAlloced, L"<img class=\"img\" style=\"height:1px;width:1px;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%s',sizingMethod='image');\" />", eText);
 +					} else {
 +						Utils::appendText(str, sizeAlloced, L"<div style=\"width: 100%%; border: 0; overflow: hidden;\"><img class=\"img\" style=\"width: expression((maxw = this.parentNode.offsetWidth ) > this.width ? 'auto' : maxw);\" src=\"file://%s\" /></div>", eText);
 +					}
 +					break;
 +				case BB_URL:
 +					eText = htmlEncode(wtext);
 +					eLink = htmlEncode(wlink);
 +					Utils::appendText(str, sizeAlloced, L"<a href =\"%s\">%s</a>", eLink, eText);
 +					break;
 +				case BB_COLOR:
 +					eText = htmlEncode(wtext);
 +					//Utils::appendText(str, sizeAlloced, L"<span style=\"color: %s;\">", eText);
 +					Utils::appendText(str, sizeAlloced, L"<font color =\"%s\">", eText);
 +					break;
 +				case BB_BACKGROUND:
 +					eText = htmlEncode(wtext);
 +					Utils::appendText(str, sizeAlloced, L"<span style=\"background: %s;\">", eText);
 +					break;
 +				case BB_SIZE:
 +					eText = htmlEncode(wtext);
 +					Utils::appendText(str, sizeAlloced, L"<span style=\"font-size: %s;\">", eText);
 +					break;
 +				}
 +			} else {
 +				switch (tag) {
 +				case BB_B:
 +					Utils::appendText(str, sizeAlloced, L"</b>");
 +					break;
 +				case BB_I:
 +					Utils::appendText(str, sizeAlloced, L"</i>");
 +					break;
 +				case BB_U:
 +					Utils::appendText(str, sizeAlloced, L"</u>");
 +					break;
 +				case BB_S:
 +					Utils::appendText(str, sizeAlloced, L"</s>");
 +					break;
 +				case BB_CODE:
 +					Utils::appendText(str, sizeAlloced, L"</pre>");
 +					break;
 +				case BB_COLOR:
 +					Utils::appendText(str, sizeAlloced, L"</font>");
 +					break;
 +				case BB_SIZE:
 +					Utils::appendText(str, sizeAlloced, L"</span>");
 +					break;
 +				case BB_BACKGROUND:
 +					Utils::appendText(str, sizeAlloced, L"</span>");
 +					break;
 +				}
 +			}
 +			break;
 +	}
 +	if (eText!=NULL) delete eText;
 +	if (eLink!=NULL) delete eLink;
 +}
  | 
