### 6.1 Through the C API

The Aspell library contains two main classes and several helper classes. The two main classes are `AspellConfig` and `AspellSpeller`. The `AspellConfig` class is used to set initial defaults and to change spell checker specific options. The `AspellSpeller` class does most of the real work. The `C API` is responsible for managing the dictionaries, checking if a word is in the dictionary, and coming up with suggestions among other things. There are many helper classes the important ones are `AspellWordList`, `AspellMutableWordList`, `Aspell*Enumeration`. The `AspellWordList` classes is used for accessing the suggestion list, as well as the personal and suggestion word list currently in use. The `AspellMutableWordList` is used to manage the personal, and perhaps other, word lists. The `Aspell*Enumeration` classes are used for iterating through a list.

#### 6.1.1 Usage

To use Aspell your application should include `aspell.h`. In order to ensure that all the necessary libraries are linked in libtool should be used to perform the linking. When using libtool simply linking with `-laspell` should be all that is necessary. When using shared libraries you might be able to simply link `-laspell`, but this is not recommended. This version of Aspell uses the CVS version of libtool however released versions of libtool should also work.

When your application first starts you should get a new configuration class with the command:

    AspellConfig * spell_config = new_aspell_config();

which will create a new `AspellConfig` class. It is allocated with `new` and it is your responsibility to delete it with `delete_aspell_config`. Once you have the config class you should set some variables. The most important one is the language variable. To do so use the command:

    aspell_config_replace(spell_config, "lang", "en_US");

which will set the default language to use to American English. The language is expected to be the standard two letter ISO 639 language code, with an optional two letter ISO 3166 country code after an underscore. You can set the preferred size via the `size` option, any extra info via the `variety` option, and the encoding via the `encoding` option. Other things you might want to set is the preferred spell checker to use, the search path for dictionaries, and the like — see The Options, for a list of all available options.

Whenever a new document is created a new `AspellSpeller` class should also be created. There should be one speller class per document. To create a new speller class use the `new_aspell_speller` and then cast it up using `to_aspell_speller` like so:

    AspellCanHaveError * possible_err = new_aspell_speller(spell_config);
    AspellSpeller * spell_checker = 0;
    if (aspell_error_number(possible_err) != 0)
      puts(aspell_error_message(possible_err));
    else
      spell_checker = to_aspell_speller(possible_err);

which will create a new `AspellSpeller` class using the defaults found in `spell_config`. To find out which dictionary is selected the `lang`, `size`, and `variety` options may be examined. To find out the exact name of the dictionary the `master` option may be examined as well as the `master-flags` options to see if there were any special flags that were passed on to the module. The `module` option way also be examined to figure out which speller module was selected, but since there is only one this option will always be the same.

If for some reason you want to use different defaults simply clone `spell_config` and change the setting like so:

    AspellConfig * spell_config2 = aspell_config_clone(spell_config);
    aspell_config_replace(spell_config2, "lang","nl");
    possible_err = new_aspell_speller(spell_config2);
    delete_aspell_config(spell_config2);

Once the speller class is created you can use the `check` method to see if a word in the document is correct like so:

    int correct = aspell_speller_check(spell_checker, word, size);

word is expected to be a `const char *` character string. size is the length of the string or `-1` if the string is null terminated. `aspell_speller_check` will return `0` if it is not found and non-zero otherwise.

If you are using the `ucs-2` or `ucs-4` encoding then the string is expected to be either a 2 or 4 byte wide integer (respectively) and the `_w` macro vesion should be used:

    int correct = aspell_speller_check_w(spell_checker, word, size);

The macro will cast the string to to the correct type and convert size into bytes for you and then a call the special wide version of the function that will make sure the encoding is correct for the type passed in. For compatibility with older versions of Aspell the normal non-wide functions can still be used provided that the size of the string, in bytes, is also passed in. Null terminated `ucs-2` or `ucs-4` are no longer supported when using the non-wide functions.

If the word is not correct, then the `suggest` method can be used to come up with likely replacements.

    AspellWordList * suggestions = aspell_speller_suggest(spell_checker,
                                                          word, size);
    AspellStringEnumeration * elements = aspell_word_list_elements(suggestions);
    const char * word;
    while ( (word = aspell_string_enumeration_next(aspell_elements)) != NULL )
    {
      // add to suggestion list
    }
    delete_aspell_string_enumeration(elements);

Notice how `elements` is deleted but `suggestions` is not. The value returned by `suggestions` is only valid to the next call to `suggest`.

If you are using the `ucs-2` or `ucs-4` encoding then, in addition to using the `_w` macro for the `suggest` method, you should also use the `_w` macro with the `next` method which will cast the string to the correct type for you. For example, if you are using the `ucs-2` encoding and the string is a `const uint16_t *` then you should use:

    AspellWordList * suggestions = aspell_speller_suggest_w(spell_checker,
                                                            word, size);
    AspellStringEnumeration * elements = aspell_word_list_elements(suggestions);
    const uint16_t * word;
    while ( (word = aspell_string_enumeration_next_w(uint16_t, aspell_elements)) != NULL )
    {
      // add to suggestion list
    }
    delete_aspell_string_enumeration(elements);

Once a replacement is made the `store_repl` method should be used to communicate the replacement pair back to the spell checker (for the reason, see Notes on Storing Replacement Pairs). Its usage is as follows:

    aspell_speller_store_repl(spell_checker, misspelled_word, size,
                              correctly_spelled_word, size);

If the user decided to add the word to the session or personal dictionary the the word can be be added using the `add_to_session` or `add_to_personal` methods respectively like so:

    aspell_speller_add_to_session|personal(spell_checker, word, size);

It is better to let the spell checker manage these words rather than doing it yourself so that the words have a chance of appearing in the suggestion list.

Finally, when the document is closed the `AspellSpeller` class should be deleted like so:

    delete_aspell_speller(spell_checker);

#### 6.1.2 API Reference

Methods that return a boolean result generally return `false` on error and `true` otherwise. To find out what went wrong use the `error_number` and `error_message` methods. Unless otherwise stated methods that return a `const char *` will return `NULL` on error. In general, the character string returned is only valid until the next method which returns a `const char *` is called.

For the details of the various classes please see the header files. In the future I will generate class references using some automated tool.

#### 6.1.3 Examples

Two simple examples are included in the examples directory. The `example-c` program demonstrates most of the Aspell library functionality and the `list-dicts` lists the available dictionaries.

#### 6.1.4 Notes About Thread Safety

Aspell should be thread safe, when used properly, as long as the underlying compiler, C and C++ library is thread safe. Aspell objects, including the AspellSpeller class, should not be used by multiple threads unless they are protected by locks or it is only accessed by read-only methods. A method is read-only only if a `const` object is passed in. Many methods that seam to be read-only are not because they may store state information in the object.