void CFulEditCtrl::Colorize(const tstring& aLine, int begin) {
	CHARFORMAT2 cf;
	cf.cbSize = sizeof(CHARFORMAT2);
	
	ColorList *cList = HighlightManager::getInstance()->getList();

	int end = GetTextLengthEx(GTL_NUMCHARS);
	
	SetSel(begin, end);
	//otroligt fulhack, måste lagas riktigt nån gång
	SetSelectionCharFormat(selFormat);

	logged = false;

	//compare the last line against all strings in the vector
	for(ColorIter i = cList->begin(); i != cList->end(); ++i) {
		ColorSettings* cs = &(*i);
		int pos;
		
		//set start position for find
		if( cs->getIncludeNick() ) {
			pos = 0;
		} else {
			pos = aLine.find(_T(">"));
			if(pos == tstring::npos)
				pos = aLine.find(_T("**")) + nick.length();
		}

		//prepare the charformat
		cf.dwMask = CFM_BOLD | CFM_UNDERLINE | CFM_STRIKEOUT | CFM_ITALIC;
		cf.dwEffects = 0;
		if(cs->getBold())		cf.dwEffects |= CFE_BOLD;
		if(cs->getItalic())		cf.dwEffects |= CFE_ITALIC;
		if(cs->getUnderline())	cf.dwEffects |= CFE_UNDERLINE;
		if(cs->getStrikeout())	cf.dwEffects |= CFE_STRIKEOUT;
		
		if(cs->getHasBgColor()){
			cf.dwMask |= CFM_BACKCOLOR;
			cf.crBackColor = cs->getBgColor();
		}
		if(cs->getHasFgColor()){
			cf.dwMask |= CFM_COLOR;
			cf.crTextColor = cs->getFgColor();
		}
		
		while( pos != string::npos ){
			if(cs->usingRegexp()) 
				pos = RegExpMatch(cs, cf, aLine, begin);
			else 
				pos = FullTextMatch(cs, cf, aLine, pos, begin);
		}

		matchedPopup = false;
		matchedSound = false;
		
	}//end for

}//end Colorize
void CFulEditCtrl::AddInternalLine(const tstring & aLine) {
	int length = GetTextLengthEx(GTL_NUMCHARS)+1;
	
	AppendText(_T("\r"));
	AppendText(aLine.c_str());
	
	CHARRANGE cr;
	GetSel(cr);
	//HideSelection(TRUE, FALSE);

	Colorize(aLine, length);
	CheckUrls(aLine, length);
	
	SetSel(GetTextLengthEx(GTL_NUMCHARS), GetTextLengthEx(GTL_NUMCHARS));
	ScrollCaret();

	SetSel(cr);

	//HideSelection(FALSE, FALSE);

	skipLog = false;
}
tstring::size_type CFulEditCtrl::TextUnderCursor(POINT mousePT, tstring& x) {
	
	tstring::size_type start = tstring::npos;

	int ch = CharFromPos(mousePT);
	POINT charPT = PosFromChar(ch);

	//since CharFromPos returns the last character even if the cursor is past the end of text
	//we have to check if the pointer was actually above the last char

	//check xpos
	if( mousePT.x > ( charPT.x + 3 ) ) 
		return start;

	//check ypos
	if( mousePT.y > (charPT.y + fontHeight ) )
		return start;

	FINDTEXT ft;
	ft.chrg.cpMin = ch;
	ft.chrg.cpMax = -1;
	ft.lpstrText = _T("\r");

	int begin = (int)SendMessage(EM_FINDTEXT, 0, (LPARAM)&ft) + 1;
	int rEnd = (int)SendMessage(EM_FINDTEXT, FR_DOWN, (LPARAM)&ft);

	if(begin < 0) {
		begin = 0;
	}

	if(rEnd == -1) {
		rEnd = GetTextLengthEx(GTL_NUMCHARS);
	}

	if(rEnd > begin) {
		TCHAR *buf = new TCHAR[(rEnd-begin)+1];
		if(buf) {
			GetTextRange(begin, rEnd, buf);
			x = buf;
			delete[] buf;
			start = ch - begin;
		}
	}
	return start;
}
Beispiel #4
0
void ChatCtrl::AppendText(const Identity& i, const tstring& sMyNick, const tstring& sTime, tstring sMsg, CHARFORMAT2& cf, bool bUseEmo/* = true*/) {
	SetRedraw(FALSE);

	SCROLLINFO si = { 0 };
	POINT pt = { 0 };

	si.cbSize = sizeof(si);
	si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
	GetScrollInfo(SB_VERT, &si);
	GetScrollPos(&pt);

	LONG lSelBegin = 0, lSelEnd = 0, lTextLimit = 0, lNewTextLen = 0;
	LONG lSelBeginSaved, lSelEndSaved;

	// Unify line endings
	tstring::size_type j = 0; 
	while((j = sMsg.find(_T("\r"), j)) != tstring::npos)
		sMsg.erase(j, 1);

	GetSel(lSelBeginSaved, lSelEndSaved);
	lSelEnd = lSelBegin = GetTextLengthEx(GTL_NUMCHARS);

	bool isMyMessage = i.getUser() == ClientManager::getInstance()->getMe();
	tstring sLine = sTime + sMsg;

	// Remove old chat if size exceeds
	lNewTextLen = sLine.size();
	lTextLimit = GetLimitText();

	if(lSelEnd + lNewTextLen > lTextLimit) {
		LONG lRemoveChars = 0;
		int multiplier = 1;

		if(lNewTextLen >= lTextLimit) {
			lRemoveChars = lSelEnd;
			magnets.clear();
		} else {
			while(lRemoveChars < lNewTextLen)
				lRemoveChars = LineIndex(LineFromChar(multiplier++ * lTextLimit / 10));
		}

		if(magnets.size()) {
			tstring buf;
			buf.resize(lRemoveChars);
			GetTextRange(0, lRemoveChars, &buf[0]);

			CHARFORMAT2 cfSel;
			cfSel.cbSize = sizeof(CHARFORMAT2);

			for(TStringMap::iterator i = magnets.begin(); i != magnets.end();) {
				tstring::size_type j = 0;
				while((j = buf.find(i->first, j)) != tstring::npos) {
					SetSel(j, j + i->first.size());
					GetSelectionCharFormat(cfSel);
					if(cfSel.dwEffects & CFE_LINK) {
						magnets.erase(i++);
						break;
					}
					j += i->first.size();
				} if(j == tstring::npos) {
					++i;
				}
			}
		}

		// Update selection ranges
		lSelEnd = lSelBegin -= lRemoveChars;
		lSelEndSaved -= lRemoveChars;
		lSelBeginSaved -= lRemoveChars;

		// ...and the scroll position
		pt.y -= PosFromChar(lRemoveChars).y;

		SetSel(0, lRemoveChars);
		ReplaceSel(_T(""));
	}


	// Add to the end
	SetSel(lSelBegin, lSelEnd);
	setText(sLine);

	CHARFORMAT2 enc;
	enc.bCharSet = RUSSIAN_CHARSET;
	enc.dwMask = CFM_CHARSET;

	SetSel(0, sLine.length());
	SetSelectionCharFormat(enc);

	// Format TimeStamp
	if(!sTime.empty()) {
		lSelEnd += sTime.size();
		SetSel(lSelBegin, lSelEnd - 1);
		SetSelectionCharFormat(WinUtil::m_TextStyleTimestamp);

		PARAFORMAT2 pf;
		memzero(&pf, sizeof(PARAFORMAT2));
		pf.dwMask = PFM_STARTINDENT; 
		pf.dxStartIndent = 0;
		SetParaFormat(pf);
	}

	// Authors nick
	tstring sAuthor = Text::toT(i.getNick());
	if(!sAuthor.empty()) {
		LONG iLen = (sMsg[0] == _T('*')) ? 1 : 0;
		LONG iAuthorLen = sAuthor.size() + 1;
		sMsg.erase(0, iAuthorLen + iLen);
   		
		lSelBegin = lSelEnd;
		lSelEnd += iAuthorLen + iLen;
		
		if(isMyMessage) {
			SetSel(lSelBegin, lSelBegin + iLen + 1);
			SetSelectionCharFormat(WinUtil::m_ChatTextMyOwn);
			SetSel(lSelBegin + iLen + 1, lSelBegin + iLen + iAuthorLen);
			SetSelectionCharFormat(WinUtil::m_TextStyleMyNick);
		} else {
			bool isFavorite = FavoriteManager::getInstance()->isFavoriteUser(i.getUser());

			if(BOOLSETTING(BOLD_AUTHOR_MESS) || isFavorite || i.isOp()) {
				SetSel(lSelBegin, lSelBegin + iLen + 1);
				SetSelectionCharFormat(cf);
				SetSel(lSelBegin + iLen + 1, lSelEnd);
				if(isFavorite){
					SetSelectionCharFormat(WinUtil::m_TextStyleFavUsers);
				} else if(i.isOp()) {
					SetSelectionCharFormat(WinUtil::m_TextStyleOPs);
				} else {
					SetSelectionCharFormat(WinUtil::m_TextStyleBold);
				}
			} else {
				SetSel(lSelBegin, lSelEnd);
				SetSelectionCharFormat(cf);
            }
		}
	} else {
		bool thirdPerson = false;
        switch(sMsg[0]) {
			case _T('*'):
				if(sMsg[1] != _T(' ')) break;
				thirdPerson = true;
            case _T('<'):
				tstring::size_type iAuthorLen = sMsg.find(thirdPerson ? _T(' ') : _T('>'), thirdPerson ? 2 : 1);
				if(iAuthorLen != tstring::npos) {
                    bool isOp = false, isFavorite = false;

                    if(client != NULL) {
						tstring nick(sMsg.c_str() + 1);
						nick.erase(iAuthorLen - 1);
						
						const OnlineUserPtr ou = client->findUser(Text::fromT(nick));
						if(ou != NULL) {
							isFavorite = FavoriteManager::getInstance()->isFavoriteUser(ou->getUser());
							isOp = ou->getIdentity().isOp();
						}
                    }
                    
					lSelBegin = lSelEnd;
					lSelEnd += iAuthorLen;
					sMsg.erase(0, iAuthorLen);

        			if(BOOLSETTING(BOLD_AUTHOR_MESS) || isFavorite || isOp) {
        				SetSel(lSelBegin, lSelBegin + 1);
        				SetSelectionCharFormat(cf);
						SetSel(lSelBegin + 1, lSelEnd);
						if(isFavorite){
							SetSelectionCharFormat(WinUtil::m_TextStyleFavUsers);
						} else if(isOp) {
							SetSelectionCharFormat(WinUtil::m_TextStyleOPs);
						} else {
							SetSelectionCharFormat(WinUtil::m_TextStyleBold);
						}
        			} else {
        				SetSel(lSelBegin, lSelEnd);
        				SetSelectionCharFormat(cf);
                    }
				}
        }
	}
				   			
	// Format the message part
	FormatChatLine(sMyNick, sMsg, cf, isMyMessage, sAuthor, lSelEnd, bUseEmo);

	SetSel(lSelBeginSaved, lSelEndSaved);
	if(	isMyMessage || ((si.nPage == 0 || (size_t)si.nPos >= (size_t)si.nMax - si.nPage - 5) &&
		(lSelBeginSaved == lSelEndSaved || !selectedUser.empty() || !selectedIP.empty() || !selectedURL.empty())))
	{
		PostMessage(EM_SCROLL, SB_BOTTOM, 0);
	} else {
		SetScrollPos(&pt);
	}

	// Force window to redraw
	SetRedraw(TRUE);
	InvalidateRect(NULL);
}
bool CFulEditCtrl::AddLine(const tstring & line, bool aTimeStamps) {
	bool noScroll = false;
	matchedTab = false;
	timeStamps = aTimeStamps;

	tstring aLine = Util::replace(line, _T("\r\n"), _T("\r"));
	if(GetWindowTextLength() > SETTING(CHATBUFFERSIZE)) {
		SetRedraw(FALSE);
		int ch = LineIndex(LineFromChar(2000));
		SetSel(0, ch);
		ReplaceSel(_T(""));
		UpdateUrlRanges(ch);
		SetSel(GetTextLengthEx(GTL_NUMCHARS), GetTextLengthEx(GTL_NUMCHARS));
		ScrollCaret();
		SetRedraw(TRUE);
	}
	if(Util::strnicmp(_T("<") + nick + _T(">"), aLine, nick.length() + 2) == 0)
		skipLog = true;

	if(isSet(STRIP_ISP) && aLine[0] == _T('<')) {
		tstring::size_type end = aLine.find(_T(">"));
		if( end != tstring::npos ) {
			tstring::size_type pos = aLine.rfind(_T("]"), end);
			if( end > 0 && (end-1) == pos )
				pos = aLine.rfind(_T("]"), pos-1);
			
			if(pos != string::npos) 
				aLine = _T("<") + aLine.substr(pos+1);
		}
	}
		
	tstring::size_type pos = aLine.find(_T("> /me "));
	if( pos != tstring::npos)
		aLine = _T("** ") + aLine.substr(1, pos-1) +  aLine.substr(pos+5, aLine.length());

	if(timeStamps)
		aLine = _T("[") + Util::getShortTimeString() + _T("] ") + aLine;
	
	
	SetRedraw(FALSE);
	
	//Get the pos of the last char
	POINT pt = PosFromChar(GetTextLengthEx(GTL_NUMCHARS));
	CRect rc;
	GetClientRect(&rc);
	int l = -1;

	//check if the last char is visible, if not then save the
	//scrollbar position
	if(rc.PtInRect(pt)){
		noScroll = false;
	} else {
		noScroll = true;
		l = GetFirstVisibleLine();
	}
    
	AddInternalLine(aLine);
				
	//restore the scrollbar position
	if(noScroll) {
		LineScroll(l - GetFirstVisibleLine());
	} 

	SetRedraw();
	Invalidate();
	UpdateWindow();

	return matchedTab;
}