diff options
| author | Eliseo Martínez <eliseomarmol@gmail.com> | 2014-05-12 02:25:17 +0200 |
|---|---|---|
| committer | Eliseo Martínez <eliseomarmol@gmail.com> | 2014-05-15 20:46:01 +0200 |
| commit | da51dc9cf202772f60bd2da975dbef257bd9237c (patch) | |
| tree | 5c16b93238a153f55634e9323077f30c8133970c /src/spell.c | |
| parent | ffe61e5ba1721340ca51d56bae3ddaca415fb5bc (diff) | |
| download | rneovim-da51dc9cf202772f60bd2da975dbef257bd9237c.tar.gz rneovim-da51dc9cf202772f60bd2da975dbef257bd9237c.tar.bz2 rneovim-da51dc9cf202772f60bd2da975dbef257bd9237c.zip | |
Introduce nvim namespace: Move files.
Move files from src/ to src/nvim/.
- src/nvim/ becomes the new root dir for nvim executable sources.
- src/libnvim/ is planned to become root dir of the neovim library.
Diffstat (limited to 'src/spell.c')
| -rw-r--r-- | src/spell.c | 13611 |
1 files changed, 0 insertions, 13611 deletions
diff --git a/src/spell.c b/src/spell.c deleted file mode 100644 index 5392fe4a70..0000000000 --- a/src/spell.c +++ /dev/null @@ -1,13611 +0,0 @@ -// VIM - Vi IMproved by Bram Moolenaar -// -// Do ":help uganda" in Vim to read copying and usage conditions. -// Do ":help credits" in Vim to see a list of people who contributed. -// See README.txt for an overview of the Vim source code. - -// spell.c: code for spell checking -// -// The spell checking mechanism uses a tree (aka trie). Each node in the tree -// has a list of bytes that can appear (siblings). For each byte there is a -// pointer to the node with the byte that follows in the word (child). -// -// A NUL byte is used where the word may end. The bytes are sorted, so that -// binary searching can be used and the NUL bytes are at the start. The -// number of possible bytes is stored before the list of bytes. -// -// The tree uses two arrays: "byts" stores the characters, "idxs" stores -// either the next index or flags. The tree starts at index 0. For example, -// to lookup "vi" this sequence is followed: -// i = 0 -// len = byts[i] -// n = where "v" appears in byts[i + 1] to byts[i + len] -// i = idxs[n] -// len = byts[i] -// n = where "i" appears in byts[i + 1] to byts[i + len] -// i = idxs[n] -// len = byts[i] -// find that byts[i + 1] is 0, idxs[i + 1] has flags for "vi". -// -// There are two word trees: one with case-folded words and one with words in -// original case. The second one is only used for keep-case words and is -// usually small. -// -// There is one additional tree for when not all prefixes are applied when -// generating the .spl file. This tree stores all the possible prefixes, as -// if they were words. At each word (prefix) end the prefix nr is stored, the -// following word must support this prefix nr. And the condition nr is -// stored, used to lookup the condition that the word must match with. -// -// Thanks to Olaf Seibert for providing an example implementation of this tree -// and the compression mechanism. -// LZ trie ideas: -// http://www.irb.hr/hr/home/ristov/papers/RistovLZtrieRevision1.pdf -// More papers: http://www-igm.univ-mlv.fr/~laporte/publi_en.html -// -// Matching involves checking the caps type: Onecap ALLCAP KeepCap. -// -// Why doesn't Vim use aspell/ispell/myspell/etc.? -// See ":help develop-spell". - -// Use SPELL_PRINTTREE for debugging: dump the word tree after adding a word. -// Only use it for small word lists! - -// Use DEBUG_TRIEWALK to print the changes made in suggest_trie_walk() for a -// specific word. - -// Use this to adjust the score after finding suggestions, based on the -// suggested word sounding like the bad word. This is much faster than doing -// it for every possible suggestion. -// Disadvantage: When "the" is typed as "hte" it sounds quite different ("@" -// vs "ht") and goes down in the list. -// Used when 'spellsuggest' is set to "best". -#define RESCORE(word_score, sound_score) ((3 * word_score + sound_score) / 4) - -// Do the opposite: based on a maximum end score and a known sound score, -// compute the maximum word score that can be used. -#define MAXSCORE(word_score, sound_score) ((4 * word_score - sound_score) / 3) - -// Vim spell file format: <HEADER> -// <SECTIONS> -// <LWORDTREE> -// <KWORDTREE> -// <PREFIXTREE> -// -// <HEADER>: <fileID> <versionnr> -// -// <fileID> 8 bytes "VIMspell" -// <versionnr> 1 byte VIMSPELLVERSION -// -// -// Sections make it possible to add information to the .spl file without -// making it incompatible with previous versions. There are two kinds of -// sections: -// 1. Not essential for correct spell checking. E.g. for making suggestions. -// These are skipped when not supported. -// 2. Optional information, but essential for spell checking when present. -// E.g. conditions for affixes. When this section is present but not -// supported an error message is given. -// -// <SECTIONS>: <section> ... <sectionend> -// -// <section>: <sectionID> <sectionflags> <sectionlen> (section contents) -// -// <sectionID> 1 byte number from 0 to 254 identifying the section -// -// <sectionflags> 1 byte SNF_REQUIRED: this section is required for correct -// spell checking -// -// <sectionlen> 4 bytes length of section contents, MSB first -// -// <sectionend> 1 byte SN_END -// -// -// sectionID == SN_INFO: <infotext> -// <infotext> N bytes free format text with spell file info (version, -// website, etc) -// -// sectionID == SN_REGION: <regionname> ... -// <regionname> 2 bytes Up to 8 region names: ca, au, etc. Lower case. -// First <regionname> is region 1. -// -// sectionID == SN_CHARFLAGS: <charflagslen> <charflags> -// <folcharslen> <folchars> -// <charflagslen> 1 byte Number of bytes in <charflags> (should be 128). -// <charflags> N bytes List of flags (first one is for character 128): -// 0x01 word character CF_WORD -// 0x02 upper-case character CF_UPPER -// <folcharslen> 2 bytes Number of bytes in <folchars>. -// <folchars> N bytes Folded characters, first one is for character 128. -// -// sectionID == SN_MIDWORD: <midword> -// <midword> N bytes Characters that are word characters only when used -// in the middle of a word. -// -// sectionID == SN_PREFCOND: <prefcondcnt> <prefcond> ... -// <prefcondcnt> 2 bytes Number of <prefcond> items following. -// <prefcond> : <condlen> <condstr> -// <condlen> 1 byte Length of <condstr>. -// <condstr> N bytes Condition for the prefix. -// -// sectionID == SN_REP: <repcount> <rep> ... -// <repcount> 2 bytes number of <rep> items, MSB first. -// <rep> : <repfromlen> <repfrom> <reptolen> <repto> -// <repfromlen> 1 byte length of <repfrom> -// <repfrom> N bytes "from" part of replacement -// <reptolen> 1 byte length of <repto> -// <repto> N bytes "to" part of replacement -// -// sectionID == SN_REPSAL: <repcount> <rep> ... -// just like SN_REP but for soundfolded words -// -// sectionID == SN_SAL: <salflags> <salcount> <sal> ... -// <salflags> 1 byte flags for soundsalike conversion: -// SAL_F0LLOWUP -// SAL_COLLAPSE -// SAL_REM_ACCENTS -// <salcount> 2 bytes number of <sal> items following -// <sal> : <salfromlen> <salfrom> <saltolen> <salto> -// <salfromlen> 1 byte length of <salfrom> -// <salfrom> N bytes "from" part of soundsalike -// <saltolen> 1 byte length of <salto> -// <salto> N bytes "to" part of soundsalike -// -// sectionID == SN_SOFO: <sofofromlen> <sofofrom> <sofotolen> <sofoto> -// <sofofromlen> 2 bytes length of <sofofrom> -// <sofofrom> N bytes "from" part of soundfold -// <sofotolen> 2 bytes length of <sofoto> -// <sofoto> N bytes "to" part of soundfold -// -// sectionID == SN_SUGFILE: <timestamp> -// <timestamp> 8 bytes time in seconds that must match with .sug file -// -// sectionID == SN_NOSPLITSUGS: nothing -// -// sectionID == SN_WORDS: <word> ... -// <word> N bytes NUL terminated common word -// -// sectionID == SN_MAP: <mapstr> -// <mapstr> N bytes String with sequences of similar characters, -// separated by slashes. -// -// sectionID == SN_COMPOUND: <compmax> <compminlen> <compsylmax> <compoptions> -// <comppatcount> <comppattern> ... <compflags> -// <compmax> 1 byte Maximum nr of words in compound word. -// <compminlen> 1 byte Minimal word length for compounding. -// <compsylmax> 1 byte Maximum nr of syllables in compound word. -// <compoptions> 2 bytes COMP_ flags. -// <comppatcount> 2 bytes number of <comppattern> following -// <compflags> N bytes Flags from COMPOUNDRULE items, separated by -// slashes. -// -// <comppattern>: <comppatlen> <comppattext> -// <comppatlen> 1 byte length of <comppattext> -// <comppattext> N bytes end or begin chars from CHECKCOMPOUNDPATTERN -// -// sectionID == SN_NOBREAK: (empty, its presence is what matters) -// -// sectionID == SN_SYLLABLE: <syllable> -// <syllable> N bytes String from SYLLABLE item. -// -// <LWORDTREE>: <wordtree> -// -// <KWORDTREE>: <wordtree> -// -// <PREFIXTREE>: <wordtree> -// -// -// <wordtree>: <nodecount> <nodedata> ... -// -// <nodecount> 4 bytes Number of nodes following. MSB first. -// -// <nodedata>: <siblingcount> <sibling> ... -// -// <siblingcount> 1 byte Number of siblings in this node. The siblings -// follow in sorted order. -// -// <sibling>: <byte> [ <nodeidx> <xbyte> -// | <flags> [<flags2>] [<region>] [<affixID>] -// | [<pflags>] <affixID> <prefcondnr> ] -// -// <byte> 1 byte Byte value of the sibling. Special cases: -// BY_NOFLAGS: End of word without flags and for all -// regions. -// For PREFIXTREE <affixID> and -// <prefcondnr> follow. -// BY_FLAGS: End of word, <flags> follow. -// For PREFIXTREE <pflags>, <affixID> -// and <prefcondnr> follow. -// BY_FLAGS2: End of word, <flags> and <flags2> -// follow. Not used in PREFIXTREE. -// BY_INDEX: Child of sibling is shared, <nodeidx> -// and <xbyte> follow. -// -// <nodeidx> 3 bytes Index of child for this sibling, MSB first. -// -// <xbyte> 1 byte Byte value of the sibling. -// -// <flags> 1 byte Bitmask of: -// WF_ALLCAP word must have only capitals -// WF_ONECAP first char of word must be capital -// WF_KEEPCAP keep-case word -// WF_FIXCAP keep-case word, all caps not allowed -// WF_RARE rare word -// WF_BANNED bad word -// WF_REGION <region> follows -// WF_AFX <affixID> follows -// -// <flags2> 1 byte Bitmask of: -// WF_HAS_AFF >> 8 word includes affix -// WF_NEEDCOMP >> 8 word only valid in compound -// WF_NOSUGGEST >> 8 word not used for suggestions -// WF_COMPROOT >> 8 word already a compound -// WF_NOCOMPBEF >> 8 no compounding before this word -// WF_NOCOMPAFT >> 8 no compounding after this word -// -// <pflags> 1 byte Bitmask of: -// WFP_RARE rare prefix -// WFP_NC non-combining prefix -// WFP_UP letter after prefix made upper case -// -// <region> 1 byte Bitmask for regions in which word is valid. When -// omitted it's valid in all regions. -// Lowest bit is for region 1. -// -// <affixID> 1 byte ID of affix that can be used with this word. In -// PREFIXTREE used for the required prefix ID. -// -// <prefcondnr> 2 bytes Prefix condition number, index in <prefcond> list -// from HEADER. -// -// All text characters are in 'encoding', but stored as single bytes. - -// Vim .sug file format: <SUGHEADER> -// <SUGWORDTREE> -// <SUGTABLE> -// -// <SUGHEADER>: <fileID> <versionnr> <timestamp> -// -// <fileID> 6 bytes "VIMsug" -// <versionnr> 1 byte VIMSUGVERSION -// <timestamp> 8 bytes timestamp that must match with .spl file -// -// -// <SUGWORDTREE>: <wordtree> (see above, no flags or region used) -// -// -// <SUGTABLE>: <sugwcount> <sugline> ... -// -// <sugwcount> 4 bytes number of <sugline> following -// -// <sugline>: <sugnr> ... NUL -// -// <sugnr>: X bytes word number that results in this soundfolded word, -// stored as an offset to the previous number in as -// few bytes as possible, see offset2bytes()) - -#include <string.h> -#include <stdlib.h> - -#include "vim.h" -#include "spell.h" -#include "buffer.h" -#include "charset.h" -#include "edit.h" -#include "eval.h" -#include "ex_cmds.h" -#include "ex_cmds2.h" -#include "ex_docmd.h" -#include "fileio.h" -#include "getchar.h" -#include "hashtab.h" -#include "mbyte.h" -#include "memline.h" -#include "memory.h" -#include "message.h" -#include "misc1.h" -#include "misc2.h" -#include "garray.h" -#include "normal.h" -#include "option.h" -#include "os_unix.h" -#include "path.h" -#include "regexp.h" -#include "screen.h" -#include "search.h" -#include "syntax.h" -#include "term.h" -#include "ui.h" -#include "undo.h" -#include "os/os.h" - -#ifndef UNIX // it's in os_unix_defs.h for Unix -# include <time.h> // for time_t -#endif - -#define MAXWLEN 250 // Assume max. word len is this many bytes. - // Some places assume a word length fits in a - // byte, thus it can't be above 255. - -// Type used for indexes in the word tree need to be at least 4 bytes. If int -// is 8 bytes we could use something smaller, but what? -typedef int idx_T; - -# define SPL_FNAME_TMPL "%s.%s.spl" -# define SPL_FNAME_ADD ".add." -# define SPL_FNAME_ASCII ".ascii." - -// Flags used for a word. Only the lowest byte can be used, the region byte -// comes above it. -#define WF_REGION 0x01 // region byte follows -#define WF_ONECAP 0x02 // word with one capital (or all capitals) -#define WF_ALLCAP 0x04 // word must be all capitals -#define WF_RARE 0x08 // rare word -#define WF_BANNED 0x10 // bad word -#define WF_AFX 0x20 // affix ID follows -#define WF_FIXCAP 0x40 // keep-case word, allcap not allowed -#define WF_KEEPCAP 0x80 // keep-case word - -// for <flags2>, shifted up one byte to be used in wn_flags -#define WF_HAS_AFF 0x0100 // word includes affix -#define WF_NEEDCOMP 0x0200 // word only valid in compound -#define WF_NOSUGGEST 0x0400 // word not to be suggested -#define WF_COMPROOT 0x0800 // already compounded word, COMPOUNDROOT -#define WF_NOCOMPBEF 0x1000 // no compounding before this word -#define WF_NOCOMPAFT 0x2000 // no compounding after this word - -// only used for su_badflags -#define WF_MIXCAP 0x20 // mix of upper and lower case: macaRONI - -#define WF_CAPMASK (WF_ONECAP | WF_ALLCAP | WF_KEEPCAP | WF_FIXCAP) - -// flags for <pflags> -#define WFP_RARE 0x01 // rare prefix -#define WFP_NC 0x02 // prefix is not combining -#define WFP_UP 0x04 // to-upper prefix -#define WFP_COMPPERMIT 0x08 // prefix with COMPOUNDPERMITFLAG -#define WFP_COMPFORBID 0x10 // prefix with COMPOUNDFORBIDFLAG - -// Flags for postponed prefixes in "sl_pidxs". Must be above affixID (one -// byte) and prefcondnr (two bytes). -#define WF_RAREPFX (WFP_RARE << 24) // rare postponed prefix -#define WF_PFX_NC (WFP_NC << 24) // non-combining postponed prefix -#define WF_PFX_UP (WFP_UP << 24) // to-upper postponed prefix -#define WF_PFX_COMPPERMIT (WFP_COMPPERMIT << 24) // postponed prefix with - // COMPOUNDPERMITFLAG -#define WF_PFX_COMPFORBID (WFP_COMPFORBID << 24) // postponed prefix with - // COMPOUNDFORBIDFLAG - - -// flags for <compoptions> -#define COMP_CHECKDUP 1 // CHECKCOMPOUNDDUP -#define COMP_CHECKREP 2 // CHECKCOMPOUNDREP -#define COMP_CHECKCASE 4 // CHECKCOMPOUNDCASE -#define COMP_CHECKTRIPLE 8 // CHECKCOMPOUNDTRIPLE - -// Special byte values for <byte>. Some are only used in the tree for -// postponed prefixes, some only in the other trees. This is a bit messy... -#define BY_NOFLAGS 0 // end of word without flags or region; for - // postponed prefix: no <pflags> -#define BY_INDEX 1 // child is shared, index follows -#define BY_FLAGS 2 // end of word, <flags> byte follows; for - // postponed prefix: <pflags> follows -#define BY_FLAGS2 3 // end of word, <flags> and <flags2> bytes - // follow; never used in prefix tree -#define BY_SPECIAL BY_FLAGS2 // highest special byte value - -// Info from "REP", "REPSAL" and "SAL" entries in ".aff" file used in si_rep, -// si_repsal, sl_rep, and si_sal. Not for sl_sal! -// One replacement: from "ft_from" to "ft_to". -typedef struct fromto_S { - char_u *ft_from; - char_u *ft_to; -} fromto_T; - -// Info from "SAL" entries in ".aff" file used in sl_sal. -// The info is split for quick processing by spell_soundfold(). -// Note that "sm_oneof" and "sm_rules" point into sm_lead. -typedef struct salitem_S { - char_u *sm_lead; // leading letters - int sm_leadlen; // length of "sm_lead" - char_u *sm_oneof; // letters from () or NULL - char_u *sm_rules; // rules like ^, $, priority - char_u *sm_to; // replacement. - int *sm_lead_w; // wide character copy of "sm_lead" - int *sm_oneof_w; // wide character copy of "sm_oneof" - int *sm_to_w; // wide character copy of "sm_to" -} salitem_T; - -typedef int salfirst_T; - -// Values for SP_*ERROR are negative, positive values are used by -// read_cnt_string(). -#define SP_TRUNCERROR -1 // spell file truncated error -#define SP_FORMERROR -2 // format error in spell file -#define SP_OTHERERROR -3 // other error while reading spell file - -// Structure used to store words and other info for one language, loaded from -// a .spl file. -// The main access is through the tree in "sl_fbyts/sl_fidxs", storing the -// case-folded words. "sl_kbyts/sl_kidxs" is for keep-case words. -// -// The "byts" array stores the possible bytes in each tree node, preceded by -// the number of possible bytes, sorted on byte value: -// <len> <byte1> <byte2> ... -// The "idxs" array stores the index of the child node corresponding to the -// byte in "byts". -// Exception: when the byte is zero, the word may end here and "idxs" holds -// the flags, region mask and affixID for the word. There may be several -// zeros in sequence for alternative flag/region/affixID combinations. -typedef struct slang_S slang_T; -struct slang_S { - slang_T *sl_next; // next language - char_u *sl_name; // language name "en", "en.rare", "nl", etc. - char_u *sl_fname; // name of .spl file - int sl_add; // TRUE if it's a .add file. - - char_u *sl_fbyts; // case-folded word bytes - idx_T *sl_fidxs; // case-folded word indexes - char_u *sl_kbyts; // keep-case word bytes - idx_T *sl_kidxs; // keep-case word indexes - char_u *sl_pbyts; // prefix tree word bytes - idx_T *sl_pidxs; // prefix tree word indexes - - char_u *sl_info; // infotext string or NULL - - char_u sl_regions[17]; // table with up to 8 region names plus NUL - - char_u *sl_midword; // MIDWORD string or NULL - - hashtab_T sl_wordcount; // hashtable with word count, wordcount_T - - int sl_compmax; // COMPOUNDWORDMAX (default: MAXWLEN) - int sl_compminlen; // COMPOUNDMIN (default: 0) - int sl_compsylmax; // COMPOUNDSYLMAX (default: MAXWLEN) - int sl_compoptions; // COMP_* flags - garray_T sl_comppat; // CHECKCOMPOUNDPATTERN items - regprog_T *sl_compprog; // COMPOUNDRULE turned into a regexp progrm - // (NULL when no compounding) - char_u *sl_comprules; // all COMPOUNDRULE concatenated (or NULL) - char_u *sl_compstartflags; // flags for first compound word - char_u *sl_compallflags; // all flags for compound words - char_u sl_nobreak; // When TRUE: no spaces between words - char_u *sl_syllable; // SYLLABLE repeatable chars or NULL - garray_T sl_syl_items; // syllable items - - int sl_prefixcnt; // number of items in "sl_prefprog" - regprog_T **sl_prefprog; // table with regprogs for prefixes - - garray_T sl_rep; // list of fromto_T entries from REP lines - short sl_rep_first[256]; // indexes where byte first appears, -1 if - // there is none - garray_T sl_sal; // list of salitem_T entries from SAL lines - salfirst_T sl_sal_first[256]; // indexes where byte first appears, -1 if - // there is none - int sl_followup; // SAL followup - int sl_collapse; // SAL collapse_result - int sl_rem_accents; // SAL remove_accents - int sl_sofo; // SOFOFROM and SOFOTO instead of SAL items: - // "sl_sal_first" maps chars, when has_mbyte - // "sl_sal" is a list of wide char lists. - garray_T sl_repsal; // list of fromto_T entries from REPSAL lines - short sl_repsal_first[256]; // sl_rep_first for REPSAL lines - int sl_nosplitsugs; // don't suggest splitting a word - - // Info from the .sug file. Loaded on demand. - time_t sl_sugtime; // timestamp for .sug file - char_u *sl_sbyts; // soundfolded word bytes - idx_T *sl_sidxs; // soundfolded word indexes - buf_T *sl_sugbuf; // buffer with word number table - int sl_sugloaded; // TRUE when .sug file was loaded or failed to - // load - - int sl_has_map; // TRUE if there is a MAP line - hashtab_T sl_map_hash; // MAP for multi-byte chars - int sl_map_array[256]; // MAP for first 256 chars - hashtab_T sl_sounddone; // table with soundfolded words that have - // handled, see add_sound_suggest() -}; - -// First language that is loaded, start of the linked list of loaded -// languages. -static slang_T *first_lang = NULL; - -// Flags used in .spl file for soundsalike flags. -#define SAL_F0LLOWUP 1 -#define SAL_COLLAPSE 2 -#define SAL_REM_ACCENTS 4 - -// Structure used in "b_langp", filled from 'spelllang'. -typedef struct langp_S { - slang_T *lp_slang; // info for this language - slang_T *lp_sallang; // language used for sound folding or NULL - slang_T *lp_replang; // language used for REP items or NULL - int lp_region; // bitmask for region or REGION_ALL -} langp_T; - -#define LANGP_ENTRY(ga, i) (((langp_T *)(ga).ga_data) + (i)) - -#define REGION_ALL 0xff // word valid in all regions - -#define VIMSPELLMAGIC "VIMspell" // string at start of Vim spell file -#define VIMSPELLMAGICL 8 -#define VIMSPELLVERSION 50 - -#define VIMSUGMAGIC "VIMsug" // string at start of Vim .sug file -#define VIMSUGMAGICL 6 -#define VIMSUGVERSION 1 - -// Section IDs. Only renumber them when VIMSPELLVERSION changes! -#define SN_REGION 0 // <regionname> section -#define SN_CHARFLAGS 1 // charflags section -#define SN_MIDWORD 2 // <midword> section -#define SN_PREFCOND 3 // <prefcond> section -#define SN_REP 4 // REP items section -#define SN_SAL 5 // SAL items section -#define SN_SOFO 6 // soundfolding section -#define SN_MAP 7 // MAP items section -#define SN_COMPOUND 8 // compound words section -#define SN_SYLLABLE 9 // syllable section -#define SN_NOBREAK 10 // NOBREAK section -#define SN_SUGFILE 11 // timestamp for .sug file -#define SN_REPSAL 12 // REPSAL items section -#define SN_WORDS 13 // common words -#define SN_NOSPLITSUGS 14 // don't split word for suggestions -#define SN_INFO 15 // info section -#define SN_END 255 // end of sections - -#define SNF_REQUIRED 1 // <sectionflags>: required section - -// Result values. Lower number is accepted over higher one. -#define SP_BANNED -1 -#define SP_OK 0 -#define SP_RARE 1 -#define SP_LOCAL 2 -#define SP_BAD 3 - -// file used for "zG" and "zW" -static char_u *int_wordlist = NULL; - -typedef struct wordcount_S { - uint16_t wc_count; // nr of times word was seen - char_u wc_word[1]; // word, actually longer -} wordcount_T; - -static wordcount_T dumwc; -#define WC_KEY_OFF (unsigned)(dumwc.wc_word - (char_u *)&dumwc) -#define HI2WC(hi) ((wordcount_T *)((hi)->hi_key - WC_KEY_OFF)) -#define MAXWORDCOUNT 0xffff - -// Information used when looking for suggestions. -typedef struct suginfo_S { - garray_T su_ga; // suggestions, contains "suggest_T" - int su_maxcount; // max. number of suggestions displayed - int su_maxscore; // maximum score for adding to su_ga - int su_sfmaxscore; // idem, for when doing soundfold words - garray_T su_sga; // like su_ga, sound-folded scoring - char_u *su_badptr; // start of bad word in line - int su_badlen; // length of detected bad word in line - int su_badflags; // caps flags for bad word - char_u su_badword[MAXWLEN]; // bad word truncated at su_badlen - char_u su_fbadword[MAXWLEN]; // su_badword case-folded - char_u su_sal_badword[MAXWLEN]; // su_badword soundfolded - hashtab_T su_banned; // table with banned words - slang_T *su_sallang; // default language for sound folding -} suginfo_T; - -// One word suggestion. Used in "si_ga". -typedef struct suggest_S { - char_u *st_word; // suggested word, allocated string - int st_wordlen; // STRLEN(st_word) - int st_orglen; // length of replaced text - int st_score; // lower is better - int st_altscore; // used when st_score compares equal - int st_salscore; // st_score is for soundalike - int st_had_bonus; // bonus already included in score - slang_T *st_slang; // language used for sound folding -} suggest_T; - -#define SUG(ga, i) (((suggest_T *)(ga).ga_data)[i]) - -// TRUE if a word appears in the list of banned words. -#define WAS_BANNED(su, word) (!HASHITEM_EMPTY(hash_find(&su->su_banned, word))) - -// Number of suggestions kept when cleaning up. We need to keep more than -// what is displayed, because when rescore_suggestions() is called the score -// may change and wrong suggestions may be removed later. -#define SUG_CLEAN_COUNT(su) ((su)->su_maxcount < \ - 130 ? 150 : (su)->su_maxcount + 20) - -// Threshold for sorting and cleaning up suggestions. Don't want to keep lots -// of suggestions that are not going to be displayed. -#define SUG_MAX_COUNT(su) (SUG_CLEAN_COUNT(su) + 50) - -// score for various changes -#define SCORE_SPLIT 149 // split bad word -#define SCORE_SPLIT_NO 249 // split bad word with NOSPLITSUGS -#define SCORE_ICASE 52 // slightly different case -#define SCORE_REGION 200 // word is for different region -#define SCORE_RARE 180 // rare word -#define SCORE_SWAP 75 // swap two characters -#define SCORE_SWAP3 110 // swap two characters in three -#define SCORE_REP 65 // REP replacement -#define SCORE_SUBST 93 // substitute a character -#define SCORE_SIMILAR 33 // substitute a similar character -#define SCORE_SUBCOMP 33 // substitute a composing character -#define SCORE_DEL 94 // delete a character -#define SCORE_DELDUP 66 // delete a duplicated character -#define SCORE_DELCOMP 28 // delete a composing character -#define SCORE_INS 96 // insert a character -#define SCORE_INSDUP 67 // insert a duplicate character -#define SCORE_INSCOMP 30 // insert a composing character -#define SCORE_NONWORD 103 // change non-word to word char - -#define SCORE_FILE 30 // suggestion from a file -#define SCORE_MAXINIT 350 // Initial maximum score: higher == slower. - // 350 allows for about three changes. - -#define SCORE_COMMON1 30 // subtracted for words seen before -#define SCORE_COMMON2 40 // subtracted for words often seen -#define SCORE_COMMON3 50 // subtracted for words very often seen -#define SCORE_THRES2 10 // word count threshold for COMMON2 -#define SCORE_THRES3 100 // word count threshold for COMMON3 - -// When trying changed soundfold words it becomes slow when trying more than -// two changes. With less then two changes it's slightly faster but we miss a -// few good suggestions. In rare cases we need to try three of four changes. -#define SCORE_SFMAX1 200 // maximum score for first try -#define SCORE_SFMAX2 300 // maximum score for second try -#define SCORE_SFMAX3 400 // maximum score for third try - -#define SCORE_BIG SCORE_INS * 3 // big difference -#define SCORE_MAXMAX 999999 // accept any score -#define SCORE_LIMITMAX 350 // for spell_edit_score_limit() - -// for spell_edit_score_limit() we need to know the minimum value of -// SCORE_ICASE, SCORE_SWAP, SCORE_DEL, SCORE_SIMILAR and SCORE_INS -#define SCORE_EDIT_MIN SCORE_SIMILAR - -// Structure to store info for word matching. -typedef struct matchinf_S { - langp_T *mi_lp; // info for language and region - - // pointers to original text to be checked - char_u *mi_word; // start of word being checked - char_u *mi_end; // end of matching word so far - char_u *mi_fend; // next char to be added to mi_fword - char_u *mi_cend; // char after what was used for - // mi_capflags - - // case-folded text - char_u mi_fword[MAXWLEN + 1]; // mi_word case-folded - int mi_fwordlen; // nr of valid bytes in mi_fword - - // for when checking word after a prefix - int mi_prefarridx; // index in sl_pidxs with list of - // affixID/condition - int mi_prefcnt; // number of entries at mi_prefarridx - int mi_prefixlen; // byte length of prefix - int mi_cprefixlen; // byte length of prefix in original - // case - - // for when checking a compound word - int mi_compoff; // start of following word offset - char_u mi_compflags[MAXWLEN]; // flags for compound words used - int mi_complen; // nr of compound words used - int mi_compextra; // nr of COMPOUNDROOT words - - // others - int mi_result; // result so far: SP_BAD, SP_OK, etc. - int mi_capflags; // WF_ONECAP WF_ALLCAP WF_KEEPCAP - win_T *mi_win; // buffer being checked - - // for NOBREAK - int mi_result2; // "mi_resul" without following word - char_u *mi_end2; // "mi_end" without following word -} matchinf_T; - -// The tables used for recognizing word characters according to spelling. -// These are only used for the first 256 characters of 'encoding'. -typedef struct spelltab_S { - char_u st_isw[256]; // flags: is word char - char_u st_isu[256]; // flags: is uppercase char - char_u st_fold[256]; // chars: folded case - char_u st_upper[256]; // chars: upper case -} spelltab_T; - -static spelltab_T spelltab; -static int did_set_spelltab; - -#define CF_WORD 0x01 -#define CF_UPPER 0x02 - -static void clear_spell_chartab(spelltab_T *sp); -static int set_spell_finish(spelltab_T *new_st); -static int spell_iswordp(char_u *p, win_T *wp); -static int spell_iswordp_nmw(char_u *p, win_T *wp); -static int spell_mb_isword_class(int cl, win_T *wp); -static int spell_iswordp_w(int *p, win_T *wp); -static int write_spell_prefcond(FILE *fd, garray_T *gap); - -// For finding suggestions: At each node in the tree these states are tried: -typedef enum { - STATE_START = 0, // At start of node check for NUL bytes (goodword - // ends); if badword ends there is a match, otherwise - // try splitting word. - STATE_NOPREFIX, // try without prefix - STATE_SPLITUNDO, // Undo splitting. - STATE_ENDNUL, // Past NUL bytes at start of the node. - STATE_PLAIN, // Use each byte of the node. - STATE_DEL, // Delete a byte from the bad word. - STATE_INS_PREP, // Prepare for inserting bytes. - STATE_INS, // Insert a byte in the bad word. - STATE_SWAP, // Swap two bytes. - STATE_UNSWAP, // Undo swap two characters. - STATE_SWAP3, // Swap two characters over three. - STATE_UNSWAP3, // Undo Swap two characters over three. - STATE_UNROT3L, // Undo rotate three characters left - STATE_UNROT3R, // Undo rotate three characters right - STATE_REP_INI, // Prepare for using REP items. - STATE_REP, // Use matching REP items from the .aff file. - STATE_REP_UNDO, // Undo a REP item replacement. - STATE_FINAL // End of this node. -} state_T; - -// Struct to keep the state at each level in suggest_try_change(). -typedef struct trystate_S { - state_T ts_state; // state at this level, STATE_ - int ts_score; // score - idx_T ts_arridx; // index in tree array, start of node - short ts_curi; // index in list of child nodes - char_u ts_fidx; // index in fword[], case-folded bad word - char_u ts_fidxtry; // ts_fidx at which bytes may be changed - char_u ts_twordlen; // valid length of tword[] - char_u ts_prefixdepth; // stack depth for end of prefix or - // PFD_PREFIXTREE or PFD_NOPREFIX - char_u ts_flags; // TSF_ flags - char_u ts_tcharlen; // number of bytes in tword character - char_u ts_tcharidx; // current byte index in tword character - char_u ts_isdiff; // DIFF_ values - char_u ts_fcharstart; // index in fword where badword char started - char_u ts_prewordlen; // length of word in "preword[]" - char_u ts_splitoff; // index in "tword" after last split - char_u ts_splitfidx; // "ts_fidx" at word split - char_u ts_complen; // nr of compound words used - char_u ts_compsplit; // index for "compflags" where word was spit - char_u ts_save_badflags; // su_badflags saved here - char_u ts_delidx; // index in fword for char that was deleted, - // valid when "ts_flags" has TSF_DIDDEL -} trystate_T; - -// values for ts_isdiff -#define DIFF_NONE 0 // no different byte (yet) -#define DIFF_YES 1 // different byte found -#define DIFF_INSERT 2 // inserting character - -// values for ts_flags -#define TSF_PREFIXOK 1 // already checked that prefix is OK -#define TSF_DIDSPLIT 2 // tried split at this point -#define TSF_DIDDEL 4 // did a delete, "ts_delidx" has index - -// special values ts_prefixdepth -#define PFD_NOPREFIX 0xff // not using prefixes -#define PFD_PREFIXTREE 0xfe // walking through the prefix tree -#define PFD_NOTSPECIAL 0xfd // highest value that's not special - -// mode values for find_word -#define FIND_FOLDWORD 0 // find word case-folded -#define FIND_KEEPWORD 1 // find keep-case word -#define FIND_PREFIX 2 // find word after prefix -#define FIND_COMPOUND 3 // find case-folded compound word -#define FIND_KEEPCOMPOUND 4 // find keep-case compound word - -static slang_T *slang_alloc(char_u *lang); -static void slang_free(slang_T *lp); -static void slang_clear(slang_T *lp); -static void slang_clear_sug(slang_T *lp); -static void find_word(matchinf_T *mip, int mode); -static int match_checkcompoundpattern(char_u *ptr, int wlen, - garray_T *gap); -static int can_compound(slang_T *slang, char_u *word, char_u *flags); -static int can_be_compound(trystate_T *sp, slang_T *slang, char_u *compflags, - int flag); -static int match_compoundrule(slang_T *slang, char_u *compflags); -static int valid_word_prefix(int totprefcnt, int arridx, int flags, - char_u *word, slang_T *slang, - int cond_req); -static void find_prefix(matchinf_T *mip, int mode); -static int fold_more(matchinf_T *mip); -static int spell_valid_case(int wordflags, int treeflags); -static int no_spell_checking(win_T *wp); -static void spell_load_ |