Using Enchant in a Windows App: Getting Started

Author albright | 20.02.2008 | Category Spelling, Developers

The following are notes toward getting started with incorporating Enchant into a Windows app.


Enchant is a spell-checking framework that allows you to use many different spell-checking backends, including Aspell, Hunspell, and Ispell.


You can get the source here.Building using MSVC is not difficult once all the dependencies are provided. The full build notes are here.


If you don’t want to bother with building it yourself, you can get binaries here.


libenchant.dll is the main library. It uses backend adapters for the providers: libenchant_aspell.dll, libenchant_ispell.dll, and libenchant_myspell.dll to proxy spell checking requests. (There are others available but if you want others, you will have to build it yourself.) There is also a .Net binding (Enchant.Net.dll) that can sit on top of libenchant.dll. libenchant_aspell.dll only works if you have aspell installed as well. If aspell-15.dll is not in your path, you must specify the dll file location in the registry key: HKCU or HKLM \Software\Enchant\Aspell\Module


By default, the providers (the backend adapters) are put into the subdirectory lib\enchant underneath the location of libenchant.dll


By default, you put dictionaries (like ispell and myspell) into the user’s appdata\enchant\[Provider Name] where [Provider Name] is MySpell or ISpell (But aspell get’s its dictionary from its installation location)


You can check your setup by running enchant-lsmod.exe. It will list the providers it finds and the dictionaries as well.


I’ll add more later.

Custom merging with Mercurial, on Windows

Author John Hatton | 07.02.2008 | Category Developers, WeSay

Today I had one of those 1/2 hour projects that turn into most of the day. I set out to try out mercurial and see how difficult it would be to get it to use a custom program to do a merge, based on the file extension. When the file type is a .lift (which is xml), I want it to run my program that knows about lift files. Simple enough. The web was littered with pages claiming ways to accomlish this… but like so often in open source stuff, a given page is for some past version on some other platform, though you as a newbie have no idea of this, so you spend all day trying things.

I’ll spare you the rest of sob story. Here’s what finally worked:

1) I installed a recent tortoisehg distribution.

2) I installed python 2.5, made sure python was part of my PATH

3) I grabbed the hgmerge.py python script

4) I learned enough python to make the script actually work (must have worked in some previous version of python… surely!)

The part of the script that inserts the values for the file paths had lines like this:

cmd.replace(’$base’, base)

Which I had to change to:

self.cmd = string.replace(self.cmd,’$base’, base)

Also the part that recognizes the “external” word didn’t work, so I rewrote it as:

elif string.find(inter, ‘external’) > -1:
start = string.find(inter, ‘external’)
tool = External()
tool.set_command(inter[9+start:])
return (noninteractive, tool, ext_filter)

5) in the .hg folder which is the mercurial repository, I edited the hgrc file:

[ui] merge = python E:\Users\John\Documents\WeSay\hgTest1\hgmerge.py

6) I edited the E:\Program Files\TortoiseHg\mercurial.ini file:

[hgmerge] ext.lift = external C:\WeSay\lib\LIFT\LIFTDotNet\output\debug\LiftMerge.exe $base $local $other $output

Beating the Disposal Blues

Author John Hatton | 18.01.2008 | Category Developers

This blog is largely a note to my future self, as I know I’ll be here again, and hopefully will google for the right terms to find this entry.


I had just added our standard code to ensure that a control was disposed of properly:


~DetailList()
{
if (!this._disposed)
{
throw new InvalidOperationException("Disposed not explicitly called on " + GetType().FullName + ".");
}
}

Using Resharper’s Unit Test Runner, all my tests passed. I checked it in, and fired up the build machine. The build uses NUNIT console to run its tests; they all passed there, too, but the build failed because this code was throwing this InvalidOperationException all over!


Notice, the key problem here is that this exception is thrown on the finalization thread, at indeterminate times. So ReSharper might not notice it at all, and no test runner really knows which test caused it. Even with Nunit, the message was listed under the wrong test method a couple of times; this is quite understandable; suddenly this exception comes through, how’s the test runner supposed to know that the fault was actually 8 tests back? If you have a thousand or so unit tests, it can be tough to figure out which one forgot to dispose of the object.


I got out of this mess by storing the stack trace, at the time of construction, with the object:


public DetailList()
{
#if DEBUG
_stackAtConstruction = new StackTrace();
#endif


Then, in the finalizer, I just cough that back up:

~DetailList()
{
if (!this._disposed)
{
string trace = "Was not recorded.";
if (_stackAtConstruction != null)
{
trace = _stackAtConstruction.ToString();
}
throw new InvalidOperationException("Disposed not explicitly called on " + GetType().FullName + ". Stack at creation was "+trace);
}
}

 


 

Steps toward running a Mono app on the OLPC XO

Author albright | 11.12.2007 | Category Developers, WeSay

I created a sd card image to boot the XO separately for our Mono environment.

  • Image the sd card using a developer image as documented here
  • Change all instances of ‘disk:\’ to ’sd:\’ in /boot/olpc.fth
  • add mono.repo to /etc/yum.repos.d as documented here and here
  • yum install mono-winforms

To launch a mono application, run: DISPLAY=:0.0 mono AppName.exe at the developer console. (Alt+= will bring up the developer console.)

We did find that the 200 dpi was not getting picked up by mono. In order to get that working, run echo 'Xft.dpi:200' | xrdb -merge at the developer console.

Giving new life to Spart

Author albright | 30.09.2007 | Category Developers, WeSay

As part of implementing our strategy for simplified sorting rules I needed to write a parser for the rules. Of course I started out looking at parser generators but wasn’t very excited by what I could find. Eventually I came across Spart (an implementation of Spirit in C#). I liked what I saw but it isn’t maintained anymore and it was written before .Net 2.0 so I cleaned it up a bit, took advantage of .Net 2.0 features, and added it to our Palaso library.

Running a Word macro on multiple files

Author albright | 28.08.2007 | Category Developers, WeSay

Last time I wrote about the need to save lots of Word files as another type. Since then, I needed to run a Word macro on a bunch of files so figured I could use the same process but just run a macro before saving the file so now I have added another little utility that will allow you to do that.

Mass conversion of Word documents to Office Open

Author albright | 24.07.2007 | Category Developers, WeSay

I needed to convert hundreds of documents from Word .doc files to standalone Office Open XML files. The Office Migration Planning Manager includes an Office File Converter utility for bulk conversions but best I can tell, it only produces the zipped docx variety. (See Doug Mahugh’s description). I need to process these with an XSLT file.

After much digging around, I found the PrimaryInteropAssembly redistributable for Office. I figured I could make a simple utility to do the conversion using that. After installing the PIA, it would not show up in the list of .Net assemblies and I was really puzzled until I finally looked in the COM assemblies. Sure enough there it was.

I ended up making a little utility that will open a Word document and save it as whatever type you specify. For multiple files, I just used the FOR command:

FOR %f IN (*.doc) DO WordConvert %f %~nf.xml FlatXML

Releasing the COM objects proved to be harder than I thought. When I first ran the application, (on fifty odd files) I got an instance of WinWord for each time it ran! Eventually had to force garbage collection twice at the end.