|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
Application featuresSmartLexicon is a multi-lingual dictionary engine. I've created this program because I wanted to have an effective tool for browsing the dictionary databases available freely in the Web. After some consideration, I've concluded that my program should have the following features:
These are the main features of SmartLexicon. If you want to give it a try, download the installer. A Help file that describes the use of the program is included. You must also download one or more databases. These are some locations for free dictionary databases:
Please note that SmartLexicon has only been tested in Windows XP platforms. It is a Unicode application, therefore it won't run in Windows 98 systems. Unfortunately, I haven't tested it with right-to-left languages. If you are also interested in how the application was coded, keep reading. LexEngine DesignSmartLexicon is an MFC application. The solution consists of three projects:
In the present article, I will only describe LexEngine. I'll start from the class that represents a dictionary entry: // Not a full listing! class WordEntry { CString word; // Word CString meaning; // Meaning CString category; // Category (verb, adj, adv) CString pronouncation; // Pronouncation CString forms; // Grammatical forms (plural, gender) CStringArray examples; CStringArray examplesMeaning; CStringArray synonyms; }; Most of the dictionary formats support only a few of the defined properties. However, I've tried to define a class as general as possible, since it will be shared by all the dictionary formats. I've also defined the copy constructor and the assignment operator for this class, so that it would be easier to work with I've decided to represent a dictionary format by two abstract classes, // Not a full listing! class CLexIndexFileBase { public: CLexIndexFileBase(); virtual ~CLexIndexFileBase(void); static CLexIndexFileBase* CreateNew(); virtual int LoadNew(CLexSourceFileBase *aSourceFile) = 0; virtual int Load(CLexSourceFileBase *aSourceFile, CString aName) = 0; virtual int FindWords(const CString& wordStart, vector<int> *wordAppearancesVector, BOOL completeWord = FALSE, BOOL exactMatch = FALSE) = 0; void GetName(CString& aName) {aName = name;}; void SetLang(CLang* l) { lang = l; }; CLang* GetLang() { return(lang); }; protected: CString name; private: CLang* lang; }; An object of
// Not a full listing class CLexSourceFileBase { public: CLexSourceFileBase(void)}; virtual ~CLexSourceFileBase(void) {}; static CLexSourceFileBase* CreateNew(); virtual BOOL Open(const CString& aName) = 0; virtual BOOL Analyse() = 0; virtual BOOL IsOpen() = 0; virtual void GetWordEntryAt(int index, vector<WordEntry> &v) = 0; virtual CString GetHeadWord(int index) = 0; virtual CString GetHeadWord(int index, CString& wordToSearch) = 0; virtual CString GetHeadWordLabel(int index, CString& wordToSearch) = 0; virtual int GetLineCount() {return(lineCount);}; virtual int GetSize() {return(size);}; virtual void GetName(CString& aName) { aName = name;}; void SetLang(CLang* l) { lang = l; }; CLang* GetLang() { return(lang); }; protected: CString name; int type; private: CLang* lang; }; The For every dictionary format, two classes that implement the above interfaces are created. The concept idea is that the user of the engine needs to know nothing about the intricacies of the different formats. It just handles them the same, by using the interface methods. You may have noticed in the previous code listings that the class CLang : public CObject { public: CLang(void); ~CLang(void); virtual BOOL IsAlpha(TCHAR c); virtual int Compare(CString& str1, CString& str2); virtual int CompareNoCase(CString& str1, CString& str2); virtual int CompareNoStrict(CString& str1, CString& str2); virtual void MakeSimple(CString& str); virtual void ToUpper(CString& str); virtual void ToLower(CString& str); void GetName(CString &aName) { aName = name; }; void GetLocale(CString &aLocale) { aLocale = locale; }; protected: CString name; CString locale; }; Most of the defined methods are actually wrappers for the standard class CNewLang : public CLang { public: CLang(void) { name = "name of the language"; locale = "Locale to be used"; } }; To be able to use the above interfaces and classes effectively and seamlessly, a management system has to be designed. The following UML class diagram illustrates the relationship between the elements of this system:
CLexIndexFileBase* CLexManagement::CreateNewIndexFile(int type) { if (type < (int) newIndexFileFnVector.size()) return( (newIndexFileFnVector.at(type))()); return(NULL); } A language, implemented by a // Language Registration void CLexManagement::LangRegistration() { registeredLangArray.Add(&langDefault); // Register languages here REGISTER_LANGUAGE(CLang); REGISTER_LANGUAGE(CLangFrench); REGISTER_LANGUAGE(CLangGerman); REGISTER_LANGUAGE(CLangGreek); REGISTER_LANGUAGE(CLangItalian); REGISTER_LANGUAGE(CLangSpanish); } // Type Registration void CLexManagement::TypeRegistration() { // Register types here REGISTER_TYPE(_T("Text"), CLexIndexFileText, CLexSourceFileText); REGISTER_TYPE(_T("Ding"), CLexIndexFileDing, CLexSourceFileDing); REGISTER_TYPE(_T("Dict"), CLexIndexFileDict, CLexSourceFileDict); } This is the only place in code where non-abstract derivatives from
Finally, just a few words about how the sorting with lexicographic order is performed. As mentioned before, the typedef multimap<wstring, int, less_locale<wstring> > MultimapKeyWord; Instead of the default less-binary predicate, a new predicate based on template <class T> class less_locale { public: bool operator() (const T& s1, const T& s2) { return (wcsicoll(s1.c_str(), s2.c_str()) < 0); } }; Web-browser integrationThe browser integration was easy for Internet Explorer. Everything I needed was right here in CodeProject. One article showed me how to extend Internet Explorer's context menu. Another one described how a COM interface could be added to an existing MFC application. That was all. I added an For Mozilla/Firefox, it is a little bit trickier. The only way to do it is to create a Mozilla extension. Thankfully, there are many online resources available for the subject. You can also have a look at the source code of the many available extensions. The second option worked better with me. Autocopy and downloadwith extensions have been most helpful. I've actually created an extension that adds an entry to the browser's pop-up menu and calls a helper application with the selected text as argument. In the current version, the helper application's path is hard-coded to SmartLexicon's default installation path (C:\Program Files\SmartLexicon). A more experienced Mozilla developer could add a Properties dialog for the extension and ask the user to configure the path. The helper application is a Win32 program with no GUI, that invokes SmartLexicon through its Mobile versionsIf you own a Symbian 7.0 phone, then you can use S60Dict to browse dict dictionaries offline. If you just own a simple J2ME MIDP 2.0 phone, then you can find in my home page a program to convert any dictionary in plain text format to a J2ME dictionary. AcknowledgementsSmartLexicon uses the following software components:
Internet Explorer integration is based on ideas by:
I have also used ideas/code snippets from numerous CodeProject articles. Thanks to all CodeProject contributors for the help they've provided. CodeProject has really been the most valuable resource of information for me. History
|
||||||||||||||||||||||