Perform spellcheck on each word in :region_lines:.

    Each word will be checked for existence in :valid_words_dictionary:.
    If it is not in :valid_words_dictionary: then corrections will be
    suggested.

    If the word isn't one which is an ordinary word, then it will be checked
    against the available symbols in :technical_words_dictionary: . If it is
    not in :technical_words_dictionary: then corrections will be suggested.

def spellcheck_region(region_lines,
                      valid_words_dictionary=None,
                      technical_words_dictionary=None,
                      user_dictionary_words=None):
    """Perform spellcheck on each word in :region_lines:.

    Each word will be checked for existence in :valid_words_dictionary:.
    If it is not in :valid_words_dictionary: then corrections will be
    suggested.

    If the word isn't one which is an ordinary word, then it will be checked
    against the available symbols in :technical_words_dictionary: . If it is
    not in :technical_words_dictionary: then corrections will be suggested.
    """
    user_dictionary_words = user_dictionary_words or set()
    spellcheckable_words_regex = re.compile(_SPELLCHECKABLE_WORDS)

    line_offset = 0
    for line in region_lines:
        for col_offset, word in _split_line_with_offsets(line):
            word = word.strip()
            if len(word) == 0:
                continue

            # If this word exists in the user dictionary, then always allow
            # it, even if it might be technical in nature
            if word in user_dictionary_words:
                continue

            if (valid_words_dictionary and
                    spellcheckable_words_regex.match(word)):
                error = _error_if_word_invalid(word,
                                               valid_words_dictionary,
                                               technical_words_dictionary,
                                               line_offset,
                                               col_offset)

                if error:
                    yield error

            # Check for symbols appearing in comments or
            # docstrings.
            elif technical_words_dictionary:
                for symbol_word in _split_into_symbol_words(word):
                    if not re.compile(_VALID_SYMBOL_WORDS).match(symbol_word):
                        continue

                    error = _error_if_symbol_unused(symbol_word,
                                                    technical_words_dictionary,
                                                    line_offset,
                                                    col_offset)

                    if error:
                        yield error

        line_offset += 1