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; }
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; }