summaryrefslogtreecommitdiff
path: root/plugins/BasicHistory/src/Searcher.cpp
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-07-05 13:27:02 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-07-05 13:27:02 +0000
commit3a56ba391bf176c11cc5bde6f860759a3ce4477c (patch)
treee6e82e3d87e43303e1e01fb2b206a812f3683af6 /plugins/BasicHistory/src/Searcher.cpp
parentcde14766d167f10dbad62c66acc0c7cc9d62f518 (diff)
BasicHistory: folder structure change
git-svn-id: http://svn.miranda-ng.org/main/trunk@773 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/BasicHistory/src/Searcher.cpp')
-rw-r--r--plugins/BasicHistory/src/Searcher.cpp388
1 files changed, 388 insertions, 0 deletions
diff --git a/plugins/BasicHistory/src/Searcher.cpp b/plugins/BasicHistory/src/Searcher.cpp
new file mode 100644
index 0000000000..c93685bcf3
--- /dev/null
+++ b/plugins/BasicHistory/src/Searcher.cpp
@@ -0,0 +1,388 @@
+/*
+Basic History plugin
+Copyright (C) 2011-2012 Krzysztof Kral
+
+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 version 2
+of the License.
+
+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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "StdAfx.h"
+#include "Searcher.h"
+#include "resource.h"
+
+Searcher::Searcher()
+ :lastFindSelection(-1),
+ findBack(false),
+ matchCase(false),
+ matchWholeWords(false),
+ onlyIn(false),
+ onlyOut(false),
+ context(NULL)
+{
+}
+
+void Searcher::ChangeFindDirection(bool isBack)
+{
+ if(isBack != findBack)
+ {
+ findBack = isBack;
+ ClearFind();
+ TBBUTTONINFO tbInfo;
+ tbInfo.cbSize = sizeof(TBBUTTONINFO);
+ tbInfo.dwMask = TBIF_TEXT | TBIF_IMAGE;
+ if(isBack)
+ {
+ tbInfo.pszText = TranslateT("Find Previous");
+ tbInfo.iImage = 1;
+ }
+ else
+ {
+ tbInfo.pszText = TranslateT("Find Next");
+ tbInfo.iImage = 0;
+ }
+ SendMessage(context->toolbarWindow, TB_SETBUTTONINFO, (WPARAM)IDM_FIND, (LPARAM)&tbInfo);
+ }
+
+ Find();
+}
+
+void Searcher::ClearFind()
+{
+ if(lastFindSelection != -1)
+ {
+ SendMessage(context->editWindow,EM_SETOPTIONS,ECOOP_AND,~ECO_NOHIDESEL);
+ lastFindSelection = -1;
+ }
+}
+
+inline TCHAR mytoupper(TCHAR a, std::locale* loc)
+{
+ return std::toupper<TCHAR>(a, *loc);
+}
+
+bool Searcher::CompareStr(std::wstring str, TCHAR *strFind)
+{
+ std::locale loc;
+ if(!matchCase)
+ std::transform(str.begin(), str.end(), str.begin(), std::bind2nd(std::ptr_fun(mytoupper), &loc));
+ if(!matchWholeWords)
+ return str.find(strFind) < str.length();
+ size_t findid = str.find(strFind);
+ size_t findLen = _tcslen(strFind);
+ while(findid < str.length())
+ {
+ if((findid == 0 || std::isspace(str[findid - 1], loc) || std::ispunct(str[findid - 1], loc)) &&
+ (findid + findLen >= str.length() || std::isspace(str[findid + findLen], loc) || std::ispunct(str[findid + findLen], loc)))
+ return true;
+ findid = str.find(strFind, findid + 1);
+ }
+
+ return false;
+}
+
+void Searcher::Find()
+{
+ FINDTEXTEX ft;
+ TCHAR str[128];
+ int curSel = 0;
+ bool isStart = false;
+ bool finished = false;
+ ft.chrg.cpMin = 0;
+ ft.chrg.cpMax = -1;
+ ft.lpstrText = str;
+ if(context->currentGroup.size() < 1)
+ {
+ SendMessage(context->editWindow,EM_SETOPTIONS,ECOOP_AND,~ECO_NOHIDESEL);
+ lastFindSelection = -1;
+ return;
+ }
+
+ GetWindowText(context->findWindow, str, 128);
+ if(!str[0])
+ {
+ TCHAR buf[256];
+ mir_sntprintf(buf, 256, TranslateT("\"%s\" not found"), str);
+ MessageBox(context->hWnd, buf, TranslateT("Search"), MB_OK | MB_ICONINFORMATION);
+ return;
+ }
+ if(!matchCase)
+ {
+ std::locale loc;
+ std::transform(str, str + _tcslen(str), str, std::bind2nd(std::ptr_fun(mytoupper), &loc));
+ }
+
+ bool findBack1 = findBack ^ !searchForInMes;
+ bool findBack2 = findBack ^ !searchForInLG;
+ int adder1 = findBack1 ? -1 : 1;
+ int adder2 = findBack2 ? -1 : 1;
+ WPARAM findStyle = (findBack1 ? 0 : FR_DOWN) | (matchCase ? FR_MATCHCASE : 0) | (matchWholeWords ? FR_WHOLEWORD : 0);
+ if(lastFindSelection >= 0 && lastFindSelection < (int)context->currentGroup.size())
+ {
+ if(onlyIn && context->currentGroup[lastFindSelection].isMe || onlyOut && !context->currentGroup[lastFindSelection].isMe)
+ {
+ curSel = lastFindSelection + adder1;
+ }
+ else
+ {
+ SendDlgItemMessage(context->hWnd,IDC_EDIT,EM_EXGETSEL,0,(LPARAM)&ft.chrg);
+ if(findBack1)
+ {
+ ft.chrg.cpMin = ft.chrg.cpMin < context->currentGroup[lastFindSelection].endPos ? ft.chrg.cpMin : context->currentGroup[lastFindSelection].endPos;
+ ft.chrg.cpMax = context->currentGroup[lastFindSelection].startPos;
+ }
+ else
+ {
+ ft.chrg.cpMin = ft.chrg.cpMax > context->currentGroup[lastFindSelection].startPos ? ft.chrg.cpMax : context->currentGroup[lastFindSelection].startPos;
+ ft.chrg.cpMax = context->currentGroup[lastFindSelection].endPos;
+ }
+ SendMessage(context->editWindow,EM_FINDTEXTEX, findStyle,(LPARAM)&ft);
+ if(ft.chrgText.cpMin < 0 || ft.chrgText.cpMax < 0)
+ {
+ curSel = lastFindSelection + adder1;
+ }
+ else
+ {
+ if(isFindContactChanged && startFindContact == context->hContact && isFindSelChanged && context->selected == startFindSel && ((!findBack1 && ft.chrg.cpMin >= startFindPos) || (findBack1 && ft.chrg.cpMax <= startFindPos)))
+ {
+ finished = true;
+ }
+ else
+ {
+ curSel = lastFindSelection;
+ SendMessage(context->editWindow,EM_EXSETSEL,0,(LPARAM)&ft.chrgText);
+ SendMessage(context->editWindow,EM_SETOPTIONS,ECOOP_OR,ECO_NOHIDESEL);
+ lastFindSelection = curSel;
+ return;
+ }
+ }
+ }
+ }
+ else
+ {
+ isStart = true;
+ SendMessage(context->editWindow,EM_SETOPTIONS,ECOOP_OR,ECO_NOHIDESEL);
+ SendMessage(context->editWindow,EM_EXGETSEL,0,(LPARAM)&ft.chrg);
+ startFindPos = findBack1 ? ft.chrg.cpMin : (ft.chrg.cpMax >= 0 ? ft.chrg.cpMax : ft.chrg.cpMin);
+ startFindSel = context->selected;
+ if(startFindPos < 0)
+ startFindPos = 0;
+ isFindSelChanged = false;
+ startFindContact = context->hContact;
+ isFindContactChanged = !allUsers;
+ if(findBack1)
+ for(curSel = (int)context->currentGroup.size() - 1; curSel >= 0; --curSel)
+ {
+ if(context->currentGroup[curSel].startPos < startFindPos)
+ break;
+ }
+ else
+ for(; curSel < (int)context->currentGroup.size(); ++curSel)
+ {
+ if(context->currentGroup[curSel].endPos > startFindPos)
+ break;
+ }
+ }
+
+ if(!finished)
+ {
+ for(; curSel < (int)context->currentGroup.size() && curSel >= 0; curSel += adder1)
+ {
+ if(onlyIn && context->currentGroup[curSel].isMe || onlyOut && !context->currentGroup[curSel].isMe)
+ continue;
+ if(CompareStr(context->currentGroup[curSel].description, str))
+ {
+ if(findBack1)
+ {
+ ft.chrg.cpMin = context->currentGroup[curSel].endPos;
+ ft.chrg.cpMax = context->currentGroup[curSel].startPos;
+ if(!isFindSelChanged && ft.chrg.cpMin > startFindPos)
+ ft.chrg.cpMin = startFindPos;
+ }
+ else
+ {
+ ft.chrg.cpMin = context->currentGroup[curSel].startPos;
+ ft.chrg.cpMax = context->currentGroup[curSel].endPos;
+ if(!isFindSelChanged && ft.chrg.cpMin < startFindPos)
+ ft.chrg.cpMin = startFindPos;
+ }
+ SendMessage(context->editWindow,EM_FINDTEXTEX, findStyle,(LPARAM)&ft);
+ if(!(ft.chrgText.cpMin < 0 || ft.chrgText.cpMax < 0))
+ {
+ if(isFindContactChanged && startFindContact == context->hContact && isFindSelChanged && context->selected == startFindSel && ((!findBack1 && ft.chrg.cpMin >= startFindPos) || (findBack1 && ft.chrg.cpMax <= startFindPos)))
+ {
+ finished = true;
+ break;
+ }
+ SendMessage(context->editWindow,EM_EXSETSEL,0,(LPARAM)&ft.chrgText);
+ SendMessage(context->editWindow,EM_SETOPTIONS,ECOOP_OR,ECO_NOHIDESEL);
+ lastFindSelection = curSel;
+ return;
+ }
+ }
+ }
+ }
+
+ if(isFindContactChanged && startFindContact == context->hContact && isFindSelChanged && context->selected == startFindSel)
+ {
+ finished = true;
+ }
+
+ if(!finished)
+ {
+ isFindSelChanged = true;
+ if(onlyGroup)
+ {
+ if(IsInSel(context->selected, str))
+ {
+ CHARRANGE ch;
+ ch.cpMin = ch.cpMax = findBack1 ? MAXLONG : 0;
+ SendMessage(context->editWindow,EM_EXSETSEL,0,(LPARAM)&ch);
+ lastFindSelection = findBack1 ? (int)context->currentGroup.size() - 1 : 0;
+ Find();
+ return;
+ }
+ }
+ else
+ {
+ for(int sel = context->selected + adder2; ; sel += adder2)
+ {
+ if(sel < 0)
+ {
+ isFindContactChanged = true;
+ if(allUsers)
+ {
+ HANDLE hNext = context->hContact;
+ do
+ {
+ hNext = context->GetNextContact(hNext, adder2);
+ }
+ while(hNext != startFindContact && !context->SearchInContact(hNext, str, this));
+ context->SelectContact(hNext);
+ }
+
+ sel = (int)context->eventList.size() - 1;
+ }
+ else if(sel >= (int)context->eventList.size())
+ {
+ isFindContactChanged = true;
+ if(allUsers)
+ {
+ HANDLE hNext = context->hContact;
+ do
+ {
+ hNext = context->GetNextContact(hNext, adder2);
+ }
+ while(hNext != startFindContact && !context->SearchInContact(hNext, str, this));
+ context->SelectContact(hNext);
+ }
+
+ sel = 0;
+ }
+ if(IsInSel(sel, str))
+ {
+ LVITEM item = {0};
+ item.mask = LVIF_STATE;
+ item.iItem = context->selected;
+ item.state = 0;
+ item.stateMask = LVIS_SELECTED;
+ ListView_SetItem(context->listWindow, &item);
+ item.iItem = sel;
+ item.state = LVIS_SELECTED;
+ ListView_SetItem(context->listWindow, &item);
+ ListView_EnsureVisible(context->listWindow, sel, FALSE);
+ CHARRANGE ch;
+ ch.cpMin = ch.cpMax = findBack1 ? MAXLONG : 0;
+ SendMessage(context->editWindow,EM_EXSETSEL,0,(LPARAM)&ch);
+ SendMessage(context->editWindow,EM_SETOPTIONS,ECOOP_OR,ECO_NOHIDESEL);
+ lastFindSelection = findBack1 ? (int)context->currentGroup.size() - 1 : 0;
+ isFindSelChanged = true;
+ Find();
+ return;
+ }
+ if(startFindContact == context->hContact && sel == startFindSel)
+ break;
+ }
+ }
+ }
+
+ if(startFindContact != context->hContact)
+ {
+ context->SelectContact(startFindContact);
+ }
+
+ if(startFindSel != context->selected)
+ {
+ LVITEM item = {0};
+ item.mask = LVIF_STATE;
+ item.iItem = context->selected;
+ item.state = 0;
+ item.stateMask = LVIS_SELECTED;
+ ListView_SetItem(context->listWindow, &item);
+ item.iItem = startFindSel;
+ item.state = LVIS_SELECTED;
+ ListView_SetItem(context->listWindow, &item);
+ ListView_EnsureVisible(context->listWindow, startFindSel, FALSE);
+ context->SelectEventGroup(startFindSel);
+ SendMessage(context->editWindow,EM_SETOPTIONS,ECOOP_OR,ECO_NOHIDESEL);
+ }
+ ft.chrgText.cpMin = startFindPos;
+ ft.chrgText.cpMax = startFindPos;
+ SendMessage(context->editWindow,EM_EXSETSEL,0,(LPARAM)&ft.chrgText);
+ SendMessage(context->editWindow,EM_SETOPTIONS,ECOOP_AND,~ECO_NOHIDESEL);
+ lastFindSelection = -1;
+ if(isStart)
+ {
+ TCHAR buf[256];
+ GetWindowText(context->findWindow, str, 128);
+ mir_sntprintf(buf, 256, TranslateT("\"%s\" not found"), str);
+ MessageBox(context->hWnd, buf, TranslateT("Search"), MB_OK | MB_ICONINFORMATION);
+ }
+ else
+ {
+ MessageBox(context->hWnd, TranslateTS(onlyGroup ? LPGENT("You have reached the end of the group.") : LPGENT("You have reached the end of the history.")), TranslateT("Search"), MB_OK | MB_ICONINFORMATION);
+ }
+}
+
+bool Searcher::IsInSel(int sel, TCHAR *strFind)
+{
+ if(sel < 0 || sel >= (int)context->eventList.size())
+ return false;
+
+ TCHAR str[MAXSELECTSTR + 8]; // for safety reason
+ EventList::EventData data;
+ for(std::deque<EventList::EventIndex>::iterator it = context->eventList[sel].begin(); it != context->eventList[sel].end(); ++it)
+ {
+ EventList::EventIndex hDbEvent = *it;
+ if(context->GetEventData(hDbEvent, data))
+ {
+ bool isMe = data.isMe;
+ if(onlyIn && isMe || onlyOut && !isMe)
+ continue;
+ context->GetEventMessage(hDbEvent, str);
+ if(CompareStr(str, strFind))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool Searcher::Compare(const bool isMe, const std::wstring& message, TCHAR *strFind)
+{
+ if(onlyIn && isMe || onlyOut && !isMe)
+ return false;
+
+ return CompareStr(message, strFind);
+}