/* This file is a part of SmartLexicon, a multi-lingual dictionary engine.
Copyright (C) 2005, Kostas Giannakakis
SmartLexicon 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.
SmartLexicon 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 SmartLexicon; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "stdafx.h"
#include "SmartLexicon.h"
#include "SmartLexiconDoc.h"
#include "SmartLexiconView.h"
#include "MeaningView.h"
#include "SettingsDlg.h"
#include "LoadingDlg.h"
#include <locale>
#define REG_EX_SUPPORT
#ifdef REG_EX_SUPPORT
#include <boost/regex.hpp>
#endif //REG_EX_SUPPORT
using namespace std;
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#define HORIZONTAL_EXTENT_START 100
// CSmartLexiconView
IMPLEMENT_DYNCREATE(CSmartLexiconView, CListView)
BEGIN_MESSAGE_MAP(CSmartLexiconView, CListView)
ON_WM_CREATE()
ON_NOTIFY_REFLECT(LVN_ITEMCHANGED, OnLvnItemchanged)
ON_NOTIFY_REFLECT(LVN_GETDISPINFO, OnLvnGetdispinfo)
END_MESSAGE_MAP()
// CSmartLexiconView construction/destruction
CSmartLexiconView::CSmartLexiconView()
{
#ifdef _TEST
TRACE0("Testing started!\n");
LexEngineTest();
TRACE0("Testing ended!\n");
#endif
wordToSearch = _T("");
regExSearch = FALSE;
dlg = new CStartUpDlg(this);
dlg->Create(IDD_INIT_DIALOG);
dlg->ShowWindow(SW_SHOW);
newDictMsg = RegisterWindowMessage(UWM_START_UP_DIALOG_NEW_DICT_LOADED);
LoadDictionaries();
dlg->DestroyWindow();
delete dlg;
horizontalBorder = 0;
}
CSmartLexiconView::~CSmartLexiconView()
{
}
BOOL CSmartLexiconView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName,
DWORD dwStyle, const RECT& rect, CWnd* pParentWnd,
UINT nID, CCreateContext* pContext)
{
// TODO: Add your specialized code here and/or call the base class
dwStyle |= LVS_OWNERDATA;
return CListView::Create(lpszClassName, lpszWindowName, dwStyle,
rect, pParentWnd, nID, pContext);
}
BOOL CSmartLexiconView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CListView::PreCreateWindow(cs);
}
void CSmartLexiconView::OnInitialUpdate()
{
CListView::OnInitialUpdate();
// TODO: You may populate your ListView with items by directly accessing
// its list control through a call to GetListCtrl().
ModifyStyle(LVS_TYPEMASK, LVS_REPORT & LVS_TYPEMASK);
ModifyStyle(LVS_TYPESTYLEMASK, LVS_NOCOLUMNHEADER & LVS_TYPESTYLEMASK);
ModifyStyle(0, LVS_SINGLESEL);
horizontalExtent = 0;
GetListCtrl().InsertColumn(0, _T(""), 0, HORIZONTAL_EXTENT_START);
indexItemMax = -1;
//GetListCtrl().SetColumnWidth(0, LVSCW_AUTOSIZE);
if (dictionaryNames.GetCount() > 0)
{
GetDocument()->SetTitle(dictionaryNames.GetAt(0));
}
else
{
GetDocument()->SetTitle(_T("No dictionary loaded"));
}
}
// CSmartLexiconView diagnostics
#ifdef _DEBUG
void CSmartLexiconView::AssertValid() const
{
CListView::AssertValid();
}
void CSmartLexiconView::Dump(CDumpContext& dc) const
{
CListView::Dump(dc);
}
CSmartLexiconDoc* CSmartLexiconView::GetDocument() const // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSmartLexiconDoc)));
return (CSmartLexiconDoc*)m_pDocument;
}
#endif //_DEBUG
// Implementation Functions
void CSmartLexiconView::LoadDictionaries()
{
currentLexicon = -1;
lexDB.LoadDictionariesTable(_T("Software\\KG\\SmartLexicon"));
CString name, sourceFilePath, indexFilePath, lang1, lang2;
BOOL autoload;
int type, state;
CLexiconObject *lexObject;
int dictionariesCount = lexDB.GetDictionariesTableSize();
for(int i=0; i<dictionariesCount; i++)
{
if (lexDB.GetDictionaryProperties(i, name, sourceFilePath, indexFilePath,
lang1, lang2, type, autoload, state))
{
dlg->SendMessage(newDictMsg,
(WPARAM) &name,
(i & 0xFF) | ((dictionariesCount << 8) & 0xFF00));
if (autoload)
{
lexObject = lexMng.CreateNewObject(type, lang1);
lexObject->SetName(name);
lexObject->SetSourceFileName(sourceFilePath);
lexObject->SetSourceFilePath(sourceFilePath);
}
else
{
lexDB.UpdateDictionaryProperties(i,name,autoload,
CLexDataBaseEntry::UNLOADED);
continue;
}
BOOL OK = lexObject->GetSourceFile()->Open(sourceFilePath);
if (!OK)
{
lexMng.Delete(lexObject);
lexDB.UpdateDictionaryProperties(i,name,autoload,
CLexDataBaseEntry::CORRUPT);
continue;
}
lexObject->GetSourceFile()->Analyse();
int result = lexObject->GetIndexFile()->Load(lexObject->GetSourceFile(),
indexFilePath);
if (result!=CLexIndexFileBase::LOADING_SUCCESSFUL)
{
if (result == CLexIndexFileBase::LOADING_PENDING)
{
lexObject->GetIndexFile()->StopLoading();
}
lexMng.Delete(lexObject);
lexDB.UpdateDictionaryProperties(i,name,autoload,
CLexDataBaseEntry::CORRUPT);
continue;
}
else
{
dictionaryNames.Add(name);
lexDB.LoadDictionary(i,name,autoload);
}
}
else
{
break;
}
}
currentLexicon = -1;
if (lexDB.GetDictionariesLoadedCount()>0)
{
int pos = lexDB.GetLoadedDictIndex(0);
ASSERT(pos == 0);
if (pos >= 0)
{
currentLexicon = 0;
lexObject = (CLexiconObject *) lexMng.GetAt(pos);
lexSourceFile = lexObject->GetSourceFile();
lexIndexFile = lexObject->GetIndexFile();
}
}
}
int CSmartLexiconView::SearchWord(CString aWordToSearch,
BOOL exactMatch,
BOOL completeWord)
{
CWaitCursor waitCursor;
int count = 0;
wordToSearch = aWordToSearch;
GetDocument()->mWordEntryVector.clear();
keyWordTable.clear();
wordAppearancesVector.clear();
GetListCtrl().DeleteAllItems();
indexItemMax = -1;
horizontalExtent = 0;
GetListCtrl().SetColumnWidth(0, HORIZONTAL_EXTENT_START);
GetListCtrl().SetItemCount(0);
if (wordToSearch.GetLength() > 0)
{
if (!regExSearch)
{
count = lexIndexFile->FindWords(wordToSearch,
&wordAppearancesVector,
completeWord,
exactMatch);
}
else
{
#ifdef REG_EX_SUPPORT
CString keyWord;
try
{
boost::wregex regEx(wordToSearch.GetBuffer());
int index = 0;
keyWord = lexSourceFile->GetHeadWord(index);
while (keyWord != _T(""))
{
if (boost::regex_match(keyWord.GetBuffer(), regEx))
{
wordAppearancesVector.push_back(index);
count++;
}
index++;
keyWord = lexSourceFile->GetHeadWord(index);
}
}
catch (...)
{
}
#endif //REG_EX_SUPPORT
}
vector<int>::iterator it;
int i = 0;
CLang *lang = lexSourceFile->GetLang();
CString tempLocale;
lang->GetLocale(tempLocale);
_wsetlocale(LC_ALL, tempLocale);
for(it = wordAppearancesVector.begin(); it < wordAppearancesVector.end(); it++)
{
int entryLine = *it;
CString entryWord = lexSourceFile->GetHeadWord(*it, wordToSearch);
if (entryWord!= _T(""))
{
wstring wstr(entryWord.GetBuffer());
//keyWordTable.insert(pair<CString, int>(entryWord, entryLine));
keyWordTable.insert(pair<wstring, int>(wstr, entryLine));
}
}
_wsetlocale(LC_ALL, L"C");
GetListCtrl().SetItemCount((int) keyWordTable.size());
//GetListCtrl().SetColumnWidth(0, LVSCW_AUTOSIZE);
if (keyWordTable.size() > 0)
{
GetListCtrl().SetItemState(0,
LVIS_SELECTED,
LVIS_SELECTED);
}
}
return (int) keyWordTable.size();
}
void CSmartLexiconView::UpdateDictionariesList()
{
CString name, sourceFilePath, indexFilePath, lang1, lang2;
BOOL autoload;
int type, state;
CLexiconObject *lexObject;
dictionaryNames.RemoveAll();
for(int i=0; i<lexDB.GetDictionariesTableSize(); i++)
{
if (lexDB.GetDictionaryProperties(i, name, sourceFilePath, indexFilePath,
lang1, lang2, type, autoload, state))
{
if (state == CLexDataBaseEntry::LOADED)
dictionaryNames.Add(name);
}
else
{
break;
}
}
if (lexDB.GetDictionariesLoadedCount()>0)
{
currentLexicon = 0;
int pos = lexDB.GetLoadedDictIndex(currentLexicon);
if (pos >= 0)
{
lexObject = (CLexiconObject *) lexMng.GetAt(pos);
lexSourceFile = lexObject->GetSourceFile();
lexIndexFile = lexObject->GetIndexFile();
GetDocument()->SetTitle(dictionaryNames.GetAt(0));
}
else
{
currentLexicon = -1;
GetDocument()->mWordEntryVector.clear();
GetDocument()->SetTitle(_T("No dictionary loaded"));
}
}
else
{
currentLexicon = - 1;
GetDocument()->mWordEntryVector.clear();
GetDocument()->SetTitle(_T("No dictionary loaded"));
}
GetDocument()->UpdateAllViews(this);
}
int CSmartLexiconView::GetDictionariesCount()
{
return (int) dictionaryNames.GetCount();
}
BOOL CSmartLexiconView::GetDictionaryName(int index, CString& name)
{
if (index<0 || index>= GetDictionariesCount())
return FALSE;
name = dictionaryNames.GetAt(index);
return TRUE;
}
void CSmartLexiconView::ChangeDictionary(int index)
{
CLexiconObject *lexObj;
int count = lexDB.GetDictionariesLoadedCount();
if (count > 0 &&
index >=0 &&
index < count)
{
currentLexicon = index;
int pos = lexDB.GetLoadedDictIndex(currentLexicon);
lexObj = lexMng.GetAt(pos);
lexSourceFile = lexObj->GetSourceFile();
lexIndexFile = lexObj->GetIndexFile();
GetDocument()->SetTitle(dictionaryNames.GetAt(index));
}
}
// CSmartLexiconView message handlers
int CSmartLexiconView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CListView::OnCreate(lpCreateStruct) == -1)
return -1;
GetDocument()->mSmartLexiconView = this;
return 0;
}
void CSmartLexiconView::OnLvnItemchanged(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
*pResult = 0;
int itemIndex = pNMLV->iItem;
if ((pNMLV->uNewState & LVIS_SELECTED) == LVIS_SELECTED)
{
vector<WordEntry>::iterator it;
MultimapKeyWord::iterator mm_it = keyWordTable.begin();
for(int i=0; i<itemIndex; i++)
mm_it++;
lexSourceFile->GetWordEntryAt(mm_it->second,
GetDocument()->mWordEntryVector);
GetDocument()->UpdateAllViews(this);
}
}
void CSmartLexiconView::SetListBoxExtent(CString &newStr)
{
CDC* pDC = GetListCtrl().GetDC();
CFont* pFont = GetListCtrl().GetFont();
// Select the listbox font, save the old font
CFont* pOldFont = pDC->SelectObject(pFont);
// Get size of text
CSize sz = pDC->GetTextExtent(newStr);
if (horizontalBorder == 0)
{
TEXTMETRIC tm;
// Get the text metrics for avg char width
pDC->GetTextMetrics(&tm);
// Add the avg width to prevent clipping
horizontalBorder = 5 + tm.tmMaxCharWidth;
}
// Select the old font back into the DC
pDC->SelectObject(pOldFont);
GetListCtrl().ReleaseDC(pDC);
if (sz.cx > horizontalExtent)
{
horizontalExtent = sz.cx;
GetListCtrl().SetColumnWidth(0, horizontalExtent + horizontalBorder);
}
}
void CSmartLexiconView::OnLvnGetdispinfo(NMHDR *pNMHDR, LRESULT *pResult)
{
NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
*pResult = 0;
if (wordToSearch == _T(""))
return;
LV_ITEM* pItem= &(pDispInfo)->item;
int itemIndex = pItem->iItem;
if (pItem->mask & LVIF_TEXT) //valid text buffer?
{
CString str;
MultimapKeyWord::iterator mm_it = keyWordTable.begin();
for(int i=0; i<itemIndex; i++)
mm_it++;
str = lexSourceFile->GetHeadWordLabel(mm_it->second,
wordToSearch);
if (pItem->iSubItem == 0)
{
lstrcpy(pItem->pszText, str);
if (itemIndex > indexItemMax)
{
indexItemMax = itemIndex;
SetListBoxExtent(str);
}
}
}
}
void CSmartLexiconView::OnLexNew()
{
CLexiconObject *lexObj;
CLoadingDlg loadingDlg;
BOOL OK;
CString name, path, indexFilePath, lang1, lang2;
BOOL autoload;
int type;
loadingDlg.Initialise(&lexDB, &lexMng);
OK = (loadingDlg.DoModal() == IDOK);
lexObj = loadingDlg.GetLexObject();
loadingDlg.GetProperties(lang1, lang2, autoload, type);
if (OK && lexObj != NULL)
{
lexObj->GetName(name);
lexObj->GetSourceFilePath(path);
lexObj->GetIndexFile()->GetName(indexFilePath);
int lex = (int) dictionaryNames.Add(name);
if (lex >= 0)
{
int lexMngCount = lexMng.GetCount();
currentLexicon = lex;
ASSERT(currentLexicon == lexMngCount - 1);
ASSERT(currentLexicon == lexDB.GetDictionariesLoadedCount());
lexDB.AddDictionary(name, path, indexFilePath,
lang1, lang2, type,
CLexDataBaseEntry::LOADED,
autoload);
GetDocument()->SetTitle(dictionaryNames.GetAt(lex));
}
else
{
lexMng.Delete(lexObj);
lexObj = NULL;
OK = FALSE;
}
}
if (lexObj)
{
lexSourceFile = lexObj->GetSourceFile();
lexIndexFile = lexObj->GetIndexFile();
}
}
void CSmartLexiconView::OnLexOpen()
{
CSettingsDlg settingsDlg;
GetListCtrl().SetItemCount(0);
settingsDlg.SetLexDB(&lexDB, &lexMng);
//int i;
//TRACE("BEFORE\n");
//for(i=0; i<lexDB.GetDictionariesLoadedCount(); i++)
//{
// int pos = lexDB.GetLoadedDictIndex(i);
// CLexiconObject *obj = lexMng.GetAt(pos);
// TRACE3("%d: %X %X\n", pos, obj->GetSourceFile(), obj->GetIndexFile());
//}
settingsDlg.DoModal();
//TRACE("AFTER\n");
//for(i=0; i<lexDB.GetDictionariesLoadedCount(); i++)
//{
// int pos = lexDB.GetLoadedDictIndex(i);
// CLexiconObject *obj = lexMng.GetAt(pos);
// TRACE3("%d: %X %X\n", pos, obj->GetSourceFile(), obj->GetIndexFile());
//}
UpdateDictionariesList();
}
#ifdef _TEST
#include "LangSpanish.h"
#include "LangItalian.h"
void CSmartLexiconView::LexEngineTest()
{
//CLexDataBaseStoreTest lexDBStoreTest;
//lexDBStoreTest.Test1();
//lexDBStoreTest.Test2();
//lexDBStoreTest.Test3();
//CLexDataBaseTest lexDBTest;
//lexDBTest.Test1();
//lexDBTest.Test2();
//lexDBTest.Test3();
//lexDBTest.Test4();
//lexDBTest.Test5();
//lexDBTest.Test6();
//lexDBTest.Test7();
//lexDBTest.Test8();
//lexDBTest.Test9();
//lexDBTest.Test10();
//CLangSpanishTest::TestAll();
//CLangItalianTest::TestAll();
}
#endif