summaryrefslogtreecommitdiff
path: root/plugins/TabSRMM/chat/muchighlight.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/TabSRMM/chat/muchighlight.cpp')
-rw-r--r--plugins/TabSRMM/chat/muchighlight.cpp427
1 files changed, 427 insertions, 0 deletions
diff --git a/plugins/TabSRMM/chat/muchighlight.cpp b/plugins/TabSRMM/chat/muchighlight.cpp
new file mode 100644
index 0000000000..d790cc1d2b
--- /dev/null
+++ b/plugins/TabSRMM/chat/muchighlight.cpp
@@ -0,0 +1,427 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda IM: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * 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.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: muchighlight.cpp 13184 2010-12-07 14:16:58Z silvercircle $
+ *
+ * highlighter class for multi user chats
+ *
+ */
+
+#include "../src/commonheaders.h"
+
+//#define __HLT_PERFSTATS 0
+
+void CMUCHighlight::cleanup()
+{
+ if(m_NickPatternString)
+ mir_free(m_NickPatternString);
+ if(m_TextPatternString)
+ mir_free(m_TextPatternString);
+
+ m_TextPatternString = m_NickPatternString = 0;
+
+ if(m_NickPatterns)
+ mir_free(m_NickPatterns);
+ if(m_TextPatterns)
+ mir_free(m_TextPatterns);
+
+ m_iNickPatterns = m_iTextPatterns = 0;
+ m_NickPatterns = m_TextPatterns = 0;
+}
+
+void CMUCHighlight::init()
+{
+ DBVARIANT dbv = {0};
+
+ if(m_fInitialized)
+ cleanup(); // clean up first, if we were already initialized
+
+ m_fInitialized = true;
+
+ if(0 == M->GetTString(0, "Chat", "HighlightWords", &dbv)) {
+ m_TextPatternString = dbv.ptszVal;
+ _wsetlocale(LC_ALL, L"");
+ wcslwr(m_TextPatternString);
+ }
+
+ if(0 == M->GetTString(0, "Chat", "HighlightNames", &dbv))
+ m_NickPatternString = dbv.ptszVal;
+
+ m_dwFlags = M->GetByte("Chat", "HighlightEnabled", MATCH_TEXT);
+ m_fHighlightMe = (M->GetByte("Chat", "HighlightMe", 1) ? true : false);
+
+ __try {
+ tokenize(m_TextPatternString, m_TextPatterns, m_iTextPatterns);
+ tokenize(m_NickPatternString, m_NickPatterns, m_iNickPatterns);
+ }
+ __except(CGlobals::Ex_ShowDialog(GetExceptionInformation(), __FILE__, __LINE__, L"MUC_HLT_TOKENIZER", false)) {
+ m_Valid = false;
+ }
+}
+
+void CMUCHighlight::tokenize(TCHAR *tszString, TCHAR**& patterns, UINT& nr)
+{
+ if(tszString == 0)
+ return;
+
+ TCHAR *p = tszString;
+
+ if(*p == 0)
+ return;
+
+ nr = 0;
+
+ if(*p != ' ')
+ nr++;
+
+ while(*p) {
+ if(*p == ' ') {
+ p++;
+ while(*p && _istspace(*p))
+ p++;
+ if(*p)
+ nr++;
+ }
+ p++;
+ }
+ patterns = (TCHAR **)mir_alloc(nr * sizeof(TCHAR *));
+
+ p = tszString;
+ nr = 0;
+
+ if(*p != ' ')
+ patterns[nr++] = p;
+
+ while(*p) {
+ if(*p == ' ') {
+ *p++ = 0;
+ while(*p && _istspace(*p))
+ p++;
+ if(*p)
+ patterns[nr++] = p;
+ }
+ p++;
+ }
+}
+
+int CMUCHighlight::match(const GCEVENT *pgce, const SESSION_INFO *psi, DWORD dwFlags)
+{
+ int result = 0, nResult = 0;
+
+ if(pgce == 0 || m_Valid == false)
+ return(0);
+
+ __try {
+ if((m_dwFlags & MATCH_TEXT) && (dwFlags & MATCH_TEXT) && (m_fHighlightMe || m_iTextPatterns > 0) && psi != 0) {
+ #ifdef __HLT_PERFSTATS
+ int words = 0;
+ M->startTimer();
+ #endif
+ TCHAR *tszCleaned = ::RemoveFormatting(pgce->ptszText, true, true);
+ TCHAR *p = tszCleaned;
+ TCHAR *p1;
+ UINT i = 0;
+
+ TCHAR *tszMe = ((psi && psi->pMe) ? mir_tstrdup(psi->pMe->pszNick) : 0);
+ if(tszMe) {
+ _wsetlocale(LC_ALL, L"");
+ wcslwr(tszMe);
+ }
+
+ if(m_fHighlightMe && tszMe) {
+ result = wcsstr(p, tszMe) ? MATCH_TEXT : 0;
+ if(0 == m_iTextPatterns)
+ goto skip_textpatterns;
+ }
+ while(p && !result) {
+ while(*p && (*p == ' ' || *p == ',' || *p == '.' || *p == ':' || *p == ';' || *p == '?' || *p == '!'))
+ p++;
+
+ if(*p) {
+ p1 = p;
+ while(*p1 && *p1 != ' ' && *p1 != ',' && *p1 != '.' && *p1 != ':' && *p1 != ';' && *p1 != '?' && *p1 != '!')
+ p1++;
+
+ if(*p1)
+ *p1 = 0;
+ else
+ p1 = 0;
+
+ for(i = 0; i < m_iTextPatterns && !result; i++)
+ result = wildmatch(m_TextPatterns[i], p) ? MATCH_TEXT : 0;
+
+ if(p1) {
+ *p1 = ' ';
+ p = p1 + 1;
+ }
+ else
+ p = 0;
+ #ifdef __HLT_PERFSTATS
+ words++;
+ #endif
+ }
+ else
+ break;
+ }
+skip_textpatterns:
+
+ #ifdef __HLT_PERFSTATS
+ M->stopTimer(0);
+ if(psi && psi->dat) {
+ mir_sntprintf(psi->dat->szStatusBar, 100, _T("PERF text match: %d ticks = %f msec (%d words, %d patterns)"), (int)M->getTicks(), M->getMsec(), words, m_iTextPatterns);
+ if(psi->dat->pContainer->hwndStatus)
+ ::SendMessage(psi->dat->pContainer->hwndStatus, SB_SETTEXT, 0, (LPARAM)psi->dat->szStatusBar);
+ }
+ #endif
+ if(tszMe)
+ mir_free(tszMe);
+ }
+
+ /*
+ * optinally, match the nickname against the list of nicks to highlight
+ */
+ if((m_dwFlags & MATCH_NICKNAME) && (dwFlags & MATCH_NICKNAME) && pgce->ptszNick && m_iNickPatterns > 0) {
+ for(UINT i = 0; i < m_iNickPatterns && !nResult; i++) {
+ if(pgce->ptszNick)
+ nResult = wildmatch(m_NickPatterns[i], pgce->ptszNick) ? MATCH_NICKNAME : 0;
+ if((m_dwFlags & MATCH_UIN) && pgce->ptszUserInfo)
+ nResult = wildmatch(m_NickPatterns[i], pgce->ptszUserInfo) ? MATCH_NICKNAME : 0;
+ }
+ }
+
+ return(result | nResult);
+ }
+ __except(CGlobals::Ex_ShowDialog(GetExceptionInformation(), __FILE__, __LINE__, L"MUC_HIGHLIGHT_EXCEPTION", false)) {
+ m_Valid = false;
+ return(0);
+ }
+ return(0);
+}
+
+int CMUCHighlight::wildmatch(const TCHAR *pattern, const TCHAR *tszString) {
+
+ const TCHAR *cp = 0, *mp = 0;
+
+ while ((*tszString) && (*pattern != '*')) {
+ if ((*pattern != *tszString) && (*pattern != '?')) {
+ return 0;
+ }
+ pattern++;
+ tszString++;
+ }
+
+ while (*tszString) {
+ if (*pattern == '*') {
+ if (!*++pattern)
+ return 1;
+ mp = pattern;
+ cp = tszString + 1;
+ }
+ else if ((*pattern == *tszString) || (*pattern == '?')) {
+ pattern++;
+ tszString++;
+ }
+ else {
+ pattern = mp;
+ tszString = cp++;
+ }
+ }
+
+ while (*pattern == '*')
+ pattern++;
+
+ return(!*pattern);
+}
+
+/**
+ * Dialog procedure to handle global highlight settings
+ *
+ * @param Standard Windows dialog procedure parameters
+ */
+
+INT_PTR CALLBACK CMUCHighlight::dlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_INITDIALOG: {
+ DBVARIANT dbv = {0};
+
+ TranslateDialogDefault(hwndDlg);
+
+ if(0 == M->GetTString(0, "Chat", "HighlightWords", &dbv)) {
+ ::SetDlgItemTextW(hwndDlg, IDC_HIGHLIGHTTEXTPATTERN, dbv.ptszVal);
+ ::DBFreeVariant(&dbv);
+ }
+
+ if(0 == M->GetTString(0, "Chat", "HighlightNames", &dbv)) {
+ ::SetDlgItemTextW(hwndDlg, IDC_HIGHLIGHTNICKPATTERN, dbv.ptszVal);
+ ::DBFreeVariant(&dbv);
+ }
+
+ DWORD dwFlags = M->GetByte("Chat", "HighlightEnabled", MATCH_TEXT);
+
+ ::CheckDlgButton(hwndDlg, IDC_HIGHLIGHTNICKENABLE, dwFlags & MATCH_NICKNAME ? BST_CHECKED : BST_UNCHECKED);
+ ::CheckDlgButton(hwndDlg, IDC_HIGHLIGHTNICKUID, dwFlags & MATCH_UIN ? BST_CHECKED : BST_UNCHECKED);
+ ::CheckDlgButton(hwndDlg, IDC_HIGHLIGHTTEXTENABLE, dwFlags & MATCH_TEXT ? BST_CHECKED : BST_UNCHECKED);
+ ::CheckDlgButton(hwndDlg, IDC_HIGHLIGHTME, M->GetByte("Chat", "HighlightMe", 1) ? BST_CHECKED : BST_UNCHECKED);
+
+ ::SendMessageW(hwndDlg, WM_USER + 100, 0, 0);
+ return(TRUE);
+ }
+
+ case WM_USER + 100:
+ Utils::enableDlgControl(hwndDlg, IDC_HIGHLIGHTTEXTPATTERN,
+ ::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTTEXTENABLE) ? TRUE : FALSE);
+
+ Utils::enableDlgControl(hwndDlg, IDC_HIGHLIGHTNICKPATTERN,
+ ::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTNICKENABLE) ? TRUE : FALSE);
+
+ Utils::enableDlgControl(hwndDlg, IDC_HIGHLIGHTNICKUID,
+ ::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTNICKENABLE) ? TRUE : FALSE);
+
+ Utils::enableDlgControl(hwndDlg, IDC_HIGHLIGHTME,
+ ::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTTEXTENABLE) ? TRUE : FALSE);
+ return(FALSE);
+
+ case WM_COMMAND:
+ if ((LOWORD(wParam) == IDC_HIGHLIGHTNICKPATTERN
+ || LOWORD(wParam) == IDC_HIGHLIGHTTEXTPATTERN)
+ && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != ::GetFocus()))
+ return 0;
+
+ ::SendMessage(hwndDlg, WM_USER + 100, 0, 0);
+ if (lParam != (LPARAM)NULL)
+ ::SendMessage(::GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY: {
+ wchar_t* szBuf = 0;
+ int iLen = ::GetWindowTextLengthW(::GetDlgItem(hwndDlg, IDC_HIGHLIGHTNICKPATTERN));
+
+ if(iLen) {
+ szBuf = reinterpret_cast<wchar_t *>(mir_alloc((iLen + 2) * sizeof(wchar_t)));
+ ::GetDlgItemTextW(hwndDlg, IDC_HIGHLIGHTNICKPATTERN, szBuf, iLen + 1);
+ M->WriteTString(0, "Chat", "HighlightNames",szBuf);
+ }
+
+ iLen = ::GetWindowTextLengthW(::GetDlgItem(hwndDlg, IDC_HIGHLIGHTTEXTPATTERN));
+ if(iLen) {
+ szBuf = reinterpret_cast<TCHAR *>(mir_realloc(szBuf, sizeof(wchar_t) * (iLen + 2)));
+ ::GetDlgItemTextW(hwndDlg, IDC_HIGHLIGHTTEXTPATTERN, szBuf, iLen + 1);
+ M->WriteTString(0, "Chat", "HighlightWords", szBuf);
+ }
+ else
+ M->WriteTString(0, "Chat", "HighlightWords", L"");
+
+ mir_free(szBuf);
+ BYTE dwFlags = (::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTNICKENABLE) ? MATCH_NICKNAME : 0) |
+ (::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTTEXTENABLE) ? MATCH_TEXT : 0);
+
+ if(dwFlags & MATCH_NICKNAME)
+ dwFlags |= (::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTNICKUID) ? MATCH_UIN : 0);
+
+ M->WriteByte("Chat", "HighlightEnabled", dwFlags);
+ M->WriteByte("Chat", "HighlightMe", ::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTME) ? 1 : 0);
+ g_Settings.Highlight->init();
+ }
+ return TRUE;
+ }
+ default:
+ break;
+ }
+ break;
+ }
+ return(FALSE);
+}
+
+/**
+ * dialog procedure for the small "add user to highlight list" dialog box
+ * TODO: finish it
+ */
+INT_PTR CALLBACK CMUCHighlight::dlgProcAdd(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ UINT uCmd = ::GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
+ switch(msg) {
+ case WM_INITDIALOG: {
+ HFONT hFont = (HFONT)::SendDlgItemMessage(hwndDlg, IDC_ADDHIGHLIGHTTITLE, WM_GETFONT, 0, 0);
+ LOGFONTW lf = {0};
+
+ THighLightEdit *the = reinterpret_cast<THighLightEdit *>(lParam);
+ ::SetWindowLongPtr(hwndDlg, GWLP_USERDATA, the->uCmd);
+
+ ::GetObject(hFont, sizeof(lf), &lf);
+ lf.lfWeight = FW_BOLD;
+ lf.lfHeight = (int)(lf.lfHeight * 1.2);
+ hFont = ::CreateFontIndirectW(&lf);
+
+ ::SendDlgItemMessage(hwndDlg, IDC_ADDHIGHLIGHTTITLE, WM_SETFONT, (WPARAM)hFont, FALSE);
+ if(the->uCmd == THighLightEdit::CMD_ADD) {
+ Utils::showDlgControl(hwndDlg, IDC_ADDHIGHLIGHTEDITLIST, SW_HIDE);
+ ::SetDlgItemTextW(hwndDlg, IDC_ADDHIGHLIGHTTITLE, CTranslator::get(CTranslator::GEN_MUC_HIGHLIGHT_ADD));
+ ::SendDlgItemMessageW(hwndDlg, IDC_ADDHIGHLIGHTNAME, CB_INSERTSTRING, -1, (LPARAM)the->ui->pszNick);
+ ::SendDlgItemMessageW(hwndDlg, IDC_ADDHIGHLIGHTNAME, CB_INSERTSTRING, -1, (LPARAM)the->ui->pszUID);
+ ::SendDlgItemMessageW(hwndDlg, IDC_ADDHIGHLIGHTNAME, CB_SETCURSEL, 1, 0);
+ } else {
+ Utils::showDlgControl(hwndDlg, IDC_ADDHIGHLIGHTNAME, SW_HIDE);
+ Utils::showDlgControl(hwndDlg, IDC_ADDHIGHLIGHTEXPLAIN, SW_HIDE);
+ ::SetDlgItemTextW(hwndDlg, IDC_ADDHIGHLIGHTTITLE, CTranslator::get(CTranslator::GEN_MUC_HIGHLIGHT_EDIT));
+ }
+ break;
+ }
+
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORSTATIC:
+ {
+ HWND hwndChild = (HWND)lParam;
+ UINT id = ::GetDlgCtrlID(hwndChild);
+
+ if(hwndChild == ::GetDlgItem(hwndDlg, IDC_ADDHIGHLIGHTTITLE))
+ ::SetTextColor((HDC)wParam, RGB(60, 60, 150));
+ ::SetBkColor((HDC)wParam, ::GetSysColor(COLOR_WINDOW));
+ return (INT_PTR)::GetSysColorBrush(COLOR_WINDOW);
+ }
+
+ case WM_COMMAND: {
+ if(LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
+ ::DestroyWindow(hwndDlg);
+ break;
+ }
+
+ case WM_DESTROY: {
+ HFONT hFont = (HFONT)::SendDlgItemMessage(hwndDlg, IDC_ADDHIGHLIGHTTITLE, WM_GETFONT, 0, 0);
+ ::DeleteObject(hFont);
+ break;
+ }
+ }
+ return(FALSE);
+}
+