From 24ec98f0fc5cd8533aa59746c03a5b540c504d34 Mon Sep 17 00:00:00 2001 From: Jakub Bogusz Date: Mon, 6 Aug 2001 22:48:19 +0000 Subject: [PATCH] - added ispell patch with online spell checking feature (conditional as it's non-standard feature and not heavily tested) Changed files: vim-ispell.patch -> 1.1 vim.spec -> 1.75 --- vim-ispell.patch | 7232 ++++++++++++++++++++++++++++++++++++++++++++++ vim.spec | 3 + 2 files changed, 7235 insertions(+) create mode 100644 vim-ispell.patch diff --git a/vim-ispell.patch b/vim-ispell.patch new file mode 100644 index 0000000..0bba1fc --- /dev/null +++ b/vim-ispell.patch @@ -0,0 +1,7232 @@ +diff -Nur vim60am.old/src/Makefile vim60am/src/Makefile +--- vim60am.old/src/Makefile Wed Jul 4 20:42:09 2001 ++++ vim60am/src/Makefile Tue Jul 3 18:55:58 2001 +@@ -1077,6 +1077,22 @@ + # Use this for cproto 3 patchlevel 7 or above (use "cproto -V" to check): + PROTO_FLAGS = -m -M__ARGS -d -E"$(CPP)" $(NO_ATTR) + ++SPELL_SRC = spell.c \ ++ spell/good.c \ ++ spell/lookup.c \ ++ spell/hash.c \ ++ spell/makedent.c \ ++ spell/tree.c \ ++ spell/tgood.c \ ++ spell/util.c ++SPELL_OBJ = objects/spell.o \ ++ objects/good.o \ ++ objects/lookup.o \ ++ objects/hash.o \ ++ objects/makedent.o \ ++ objects/tree.o \ ++ objects/tgood.o \ ++ objects/util.o + + ################################################ + ## no changes required below this line ## +@@ -1087,7 +1103,7 @@ + .SUFFIXES: + .SUFFIXES: .cc .c .o .pro + +-PRE_DEFS = -Iproto $(DEFS) $(GUI_DEFS) $(GUI_IPATH) $(CPPFLAGS) $(EXTRA_IPATHS) ++PRE_DEFS = -Iproto -Ispell $(DEFS) $(GUI_DEFS) $(GUI_IPATH) $(CPPFLAGS) $(EXTRA_IPATHS) + POST_DEFS = $(X_CFLAGS) $(PERL_CFLAGS) $(PYTHON_CFLAGS) $(TCL_CFLAGS) $(RUBY_CFLAGS) $(EXTRA_DEFS) + + ALL_CFLAGS = $(PRE_DEFS) $(CFLAGS) $(POST_DEFS) +@@ -1167,6 +1183,7 @@ + screen.c \ + search.c \ + syntax.c \ ++ $(SPELL_SRC) \ + tag.c \ + term.c \ + ui.c \ +@@ -1232,6 +1249,7 @@ + objects/screen.o \ + objects/search.o \ + objects/syntax.o \ ++ $(SPELL_OBJ) \ + $(SNIFF_OBJ) \ + objects/tag.o \ + objects/term.o \ +@@ -2094,6 +2112,9 @@ + objects/undo.o: undo.c + $(CCC) -o $@ undo.c + ++objects/spell.o: spell.c spell/local.h ++ $(CCC) -o $@ spell.c ++ + objects/window.o: window.c + $(CCC) -o $@ window.c + +@@ -2212,6 +2233,9 @@ + objects/search.o: search.c vim.h auto/config.h feature.h os_unix.h \ + auto/osdef.h ascii.h keymap.h term.h macros.h structs.h regexp.h \ + gui.h option.h ex_cmds.h proto.h globals.h farsi.h ++objects/spell.o: spell.c vim.h spell/config.h feature.h os_unix.h auto/osdef.h ascii.h \ ++ keymap.h term.h macros.h regexp.h structs.h gui.h globals.h farsi.h \ ++ option.h ex_cmds.h proto.h spell/local.h spell/wm.h spell/ispell.h + objects/syntax.o: syntax.c vim.h auto/config.h feature.h os_unix.h \ + auto/osdef.h ascii.h keymap.h term.h macros.h structs.h regexp.h \ + gui.h option.h ex_cmds.h proto.h globals.h farsi.h +@@ -2334,3 +2358,26 @@ + objects/integration.o: integration.c vim.h auto/config.h feature.h os_unix.h \ + auto/osdef.h ascii.h keymap.h term.h macros.h structs.h regexp.h \ + gui.h option.h ex_cmds.h proto.h globals.h farsi.h integration.h ++ ++SPELL_CFLAGS=$(CFLAGS) -pedantic -DUSG=1 ++ ++objects/good.o: spell/good.c spell/config.h spell/ispell.h spell/i_proto.h spell/msgs.h spell/local.h ++ $(CC) -c $(SPELL_CFLAGS) spell/good.c -o objects/good.o ++ ++objects/lookup.o: spell/lookup.c spell/config.h spell/ispell.h spell/i_proto.h spell/msgs.h spell/local.h ++ $(CC) -c $(SPELL_CFLAGS) spell/lookup.c -o objects/lookup.o ++ ++objects/hash.o: spell/hash.c spell/config.h spell/ispell.h spell/i_proto.h spell/local.h ++ $(CC) -c $(SPELL_CFLAGS) spell/hash.c -o objects/hash.o ++ ++objects/makedent.o: spell/makedent.c spell/config.h spell/ispell.h spell/i_proto.h spell/msgs.h spell/local.h ++ $(CC) -c $(SPELL_CFLAGS) spell/makedent.c -o objects/makedent.o ++ ++objects/tree.o: spell/tree.c spell/config.h spell/ispell.h spell/i_proto.h spell/msgs.h spell/local.h ++ $(CC) -c $(SPELL_CFLAGS) spell/tree.c -o objects/tree.o ++ ++objects/tgood.o: spell/tgood.c spell/config.h spell/ispell.h spell/i_proto.h spell/local.h ++ $(CC) -c $(SPELL_CFLAGS) spell/tgood.c -o objects/tgood.o ++ ++objects/util.o: spell/util.c spell/config.h spell/ispell.h spell/i_proto.h spell/local.h ++ $(CC) -c $(SPELL_CFLAGS) spell/util.c -o objects/util.o +diff -Nur vim60am.old/src/edit.c vim60am/src/edit.c +--- vim60am.old/src/edit.c Wed Jul 4 20:42:09 2001 ++++ vim60am/src/edit.c Tue Jul 3 18:50:12 2001 +@@ -613,7 +613,11 @@ + if (c == Ctrl_V && ctrl_x_mode == CTRL_X_CMDLINE) + goto docomplete; + #endif +- if (c == Ctrl_V || c == Ctrl_Q) ++ if (c == Ctrl_V ++#ifndef FEAT_SPELL_HL /* WM */ ++ || c == Ctrl_Q ++#endif ++ ) + { + ins_ctrl_v(); + c = Ctrl_V; /* pretend CTRL-V is last typed character */ +@@ -1133,6 +1137,20 @@ + continue_status = 0; + break; + #endif /* FEAT_INS_EXPAND */ ++#ifdef FEAT_SPELL_HL /* WM */ ++ case Ctrl_Q: ++ if(set_to_private_dict( ++ ml_get_buf(curbuf, curwin->w_cursor.lnum, FALSE), ++ curwin->w_cursor.col, FALSE)) ++ vim_beep(); ++ break; ++ case Ctrl_S: ++ if(set_to_private_dict( ++ ml_get_buf(curbuf, curwin->w_cursor.lnum, FALSE), ++ curwin->w_cursor.col, TRUE)) ++ vim_beep(); ++ break; ++#endif + + case Ctrl_Y: /* copy from previous line or scroll down */ + case Ctrl_E: /* copy from next line or scroll up */ +diff -Nur vim60am.old/src/ex_cmds.h vim60am/src/ex_cmds.h +--- vim60am.old/src/ex_cmds.h Wed Jul 4 20:42:09 2001 ++++ vim60am/src/ex_cmds.h Tue Jul 3 18:49:12 2001 +@@ -700,6 +700,8 @@ + RANGE|WHOLEFOLD|EXTRA|CMDWIN|MODIFY), + EX(CMD_source, "source", ex_source, + BANG|FILE1|TRLBAR|SBOXOK|CMDWIN), ++EX(CMD_spell, "spell", ex_spell, ++ EXTRA|NOTRLCOM|CMDWIN), + EX(CMD_split, "split", ex_splitview, + BANG|FILE1|RANGE|NOTADR|EDITCMD|ARGOPT|TRLBAR), + EX(CMD_sprevious, "sprevious", ex_previous, +diff -Nur vim60am.old/src/ex_docmd.c vim60am/src/ex_docmd.c +--- vim60am.old/src/ex_docmd.c Wed Jul 4 20:42:09 2001 ++++ vim60am/src/ex_docmd.c Tue Jul 3 18:47:38 2001 +@@ -218,6 +218,9 @@ + #ifndef FEAT_SYN_HL + # define ex_syntax ex_ni + #endif ++#ifndef FEAT_SPELL_HL ++# define ex_spell ex_ni ++#endif + #ifndef FEAT_PERL + # define ex_perl ex_ni + # define ex_perldo ex_ni +@@ -2546,6 +2549,12 @@ + set_context_in_syntax_cmd(xp, arg); + break; + #endif ++#ifdef FEAT_SPELL_HL ++ case CMD_spell: ++ return arg; ++ break; ++#endif ++ + #ifdef FEAT_EVAL + case CMD_let: + case CMD_if: +diff -Nur vim60am.old/src/feature.h vim60am/src/feature.h +--- vim60am.old/src/feature.h Wed Jul 4 20:42:09 2001 ++++ vim60am/src/feature.h Tue Jul 3 18:46:14 2001 +@@ -315,6 +315,12 @@ + # endif + # define FEAT_FKMAP + #endif ++#ifdef FEAT_BIG ++#undef FEAT_RIGHTLEFT ++#undef FEAT_FKMAP ++#define FEAT_SPELL_HL /*WM*/ ++#endif ++/* # define FEAT_PRINTER */ + + /* + * +emacs_tags When FEAT_EMACS_TAGS defined: Include support for +diff -Nur vim60am.old/src/globals.h vim60am/src/globals.h +--- vim60am.old/src/globals.h Wed Jul 4 20:42:09 2001 ++++ vim60am/src/globals.h Tue Jul 3 18:45:54 2001 +@@ -718,6 +718,9 @@ + #ifdef USE_TERM_CONSOLE + EXTERN int term_console INIT(= FALSE); /* set to TRUE when console used */ + #endif ++#ifdef FEAT_SPELL_HL ++EXTERN char_u hashname[MAXPATHL]; /* name of the dictionary */ ++#endif + EXTERN int termcap_active INIT(= FALSE); /* set by starttermcap() */ + EXTERN int cur_tmode INIT(= TMODE_COOK); /* input terminal mode */ + EXTERN int bangredo INIT(= FALSE); /* set to TRUE whith ! command */ +diff -Nur vim60am.old/src/main.c vim60am/src/main.c +--- vim60am.old/src/main.c Wed Jul 4 20:42:09 2001 ++++ vim60am/src/main.c Tue Jul 3 18:45:08 2001 +@@ -1901,6 +1901,9 @@ + } + } + #endif /* FEAT_VIMINFO */ ++#ifdef FEAT_SPELL_HL ++ spell_save_private_dict(); ++#endif + + #ifdef FEAT_AUTOCMD + apply_autocmds(EVENT_VIMLEAVE, NULL, NULL, FALSE, curbuf); +diff -Nur vim60am.old/src/normal.c vim60am/src/normal.c +--- vim60am.old/src/normal.c Wed Jul 4 20:42:09 2001 ++++ vim60am/src/normal.c Tue Jul 3 18:44:28 2001 +@@ -85,6 +85,10 @@ + #ifdef FEAT_VISUAL + static int get_visual_text __ARGS((cmdarg_T *cap, char_u **pp, int *lenp)); + #endif ++#ifdef FEAT_SPELL_HL ++static void nv_settodict_q __ARGS((cmdarg_T *cap)); ++static void nv_settodict_s __ARGS((cmdarg_T *cap)); ++#endif + static void nv_tagpop __ARGS((cmdarg_T *cap)); + static void nv_scroll __ARGS((cmdarg_T *cap)); + static void nv_kright __ARGS((cmdarg_T *cap)); +@@ -226,9 +230,17 @@ + {Ctrl_N, nv_down, NV_STS, FALSE}, + {Ctrl_O, nv_ctrlo, 0, 0}, + {Ctrl_P, nv_up, NV_STS, FALSE}, ++#ifdef FEAT_SPELL_HL ++ {Ctrl_Q, nv_settodict_q, 0, 0}, ++#else + {Ctrl_Q, nv_ignore, 0, 0}, ++#endif + {Ctrl_R, nv_redo, 0, 0}, ++#ifdef FEAT_SPELL_HL ++ {Ctrl_S, nv_settodict_s, 0, 0}, ++#else + {Ctrl_S, nv_ignore, 0, 0}, ++#endif + {Ctrl_T, nv_tagpop, NV_NCW, 0}, + {Ctrl_U, nv_halfpage, 0, 0}, + #ifdef FEAT_VISUAL +@@ -7316,6 +7328,28 @@ + #endif + } + ++#ifdef FEAT_SPELL_HL ++static void ++nv_settodict_q(cap) ++ cmdarg_T *cap; ++{ ++ if(set_to_private_dict( ++ ml_get_buf(curbuf, curwin->w_cursor.lnum, FALSE), ++ curwin->w_cursor.col, FALSE)) ++ clearopbeep(cap->oap); ++} ++ ++static void ++nv_settodict_s(cap) ++ cmdarg_T *cap; ++{ ++ if(set_to_private_dict( ++ ml_get_buf(curbuf, curwin->w_cursor.lnum, FALSE), ++ curwin->w_cursor.col, TRUE)) ++ clearopbeep(cap->oap); ++} ++#endif ++ + #ifdef FEAT_VISUAL + /* + * In exclusive Visual mode, may include the last character. +diff -Nur vim60am.old/src/option.c vim60am/src/option.c +--- vim60am.old/src/option.c Wed Jul 4 20:42:09 2001 ++++ vim60am/src/option.c Tue Jul 3 18:42:14 2001 +@@ -116,6 +116,8 @@ + , PV_SW + , PV_SWF + , PV_SYN ++ , PV_SPELL_DIR ++ , PV_SPELL_LANG + , PV_TAGS + , PV_TS + , PV_TSR +@@ -216,6 +218,10 @@ + #ifdef FEAT_SYN_HL + static char_u *p_syn; + #endif ++#ifdef FEAT_SPELL_HL ++static char_u *p_spelldirectory; ++static char_u *p_language; ++#endif + static long p_ts; + static long p_tw; + static int p_tx; +@@ -1001,7 +1007,7 @@ + {(char_u *)FALSE, (char_u *)0L}}, + {"highlight", "hl", P_STRING|P_VI_DEF|P_RCLR|P_COMMA|P_NODUP, + (char_u *)&p_hl, PV_NONE, +- {(char_u *)"8:SpecialKey,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText", ++ {(char_u *)"8:SpecialKey,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,Z:Spell", + (char_u *)0L}}, + {"history", "hi", P_NUM|P_VIM, + (char_u *)&p_hi, PV_NONE, +@@ -1247,6 +1253,13 @@ + (char_u *)NULL, PV_NONE, + #endif + {(char_u *)"", (char_u *)0L}}, ++ {"language", "lang", P_STRING|P_ALLOCED|P_VI_DEF, ++#ifdef FEAT_SPELL_HL ++ (char_u *)&p_language, PV_SPELL_LANG, ++#else ++ (char_u *)NULL, PV_NONE, ++#endif ++ {(char_u *)"", (char_u *)0L}}, + {"laststatus", "ls", P_NUM|P_VI_DEF|P_RALL, + #ifdef FEAT_WINDOWS + (char_u *)&p_ls, PV_NONE, +@@ -1815,6 +1828,14 @@ + {"sourceany", NULL, P_BOOL|P_VI_DEF, + (char_u *)NULL, PV_NONE, + {(char_u *)FALSE, (char_u *)0L}}, ++ {"spelldirectory", "spelldir", P_STRING|P_ALLOCED|P_VI_DEF|P_EXPAND, ++#ifdef FEAT_SPELL_HL ++ (char_u *)&p_spelldirectory, PV_SPELL_DIR, ++ {(char_u *)"/usr/lib/ispell", (char_u *)0L}}, ++#else ++ (char_u *)NULL, PV_NONE, ++ {(char_u *)"", (char_u *)0L}}, ++#endif + {"splitbelow", "sb", P_BOOL|P_VI_DEF, + #ifdef FEAT_WINDOWS + (char_u *)&p_sb, PV_NONE, +@@ -4337,6 +4357,26 @@ + errmsg = e_invarg; + } + #endif ++#ifdef FEAT_SPELL_HL ++ else if (varp == &p_spell_dir) ++ { ++ STRCPY(hashname, p_spell_dir); ++ STRCAT(hashname, "/"); ++ STRCAT(hashname, p_spell_lang); ++ STRCAT(hashname, ".hash"); ++ reload_dict(); ++ redraw_all_later(NOT_VALID); ++ } ++ else if (varp == &p_spell_lang) ++ { ++ STRCPY(hashname, p_spell_dir); ++ STRCAT(hashname, "/"); ++ STRCAT(hashname, p_spell_lang); ++ STRCAT(hashname, ".hash"); ++ reload_dict(); ++ redraw_all_later(NOT_VALID); ++ } ++#endif + + #ifdef FEAT_MBYTE + /* 'encoding' and 'fileencoding' */ +@@ -6998,6 +7038,10 @@ + case PV_SWF: return (char_u *)&(curbuf->b_p_swf); + #ifdef FEAT_SYN_HL + case PV_SYN: return (char_u *)&(curbuf->b_p_syn); ++#endif ++#ifdef FEAT_SPELL_HL ++ case PV_SPELL_DIR: return (char_u *)&(p_spell_dir); ++ case PV_SPELL_LANG: return (char_u *)&(p_spell_lang); + #endif + case PV_SW: return (char_u *)&(curbuf->b_p_sw); + case PV_TS: return (char_u *)&(curbuf->b_p_ts); +diff -Nur vim60am.old/src/option.h vim60am/src/option.h +--- vim60am.old/src/option.h Wed Jul 4 20:42:09 2001 ++++ vim60am/src/option.h Tue Jul 3 18:40:28 2001 +@@ -336,6 +336,8 @@ + EXTERN char_u *p_dex; /* 'diffexpr' */ + # endif + #endif ++EXTERN char_u *p_spell_dir; /* directory with spell hash*/ ++EXTERN char_u *p_spell_lang; /* name of language (spell hash file)*/ + #ifdef FEAT_INS_EXPAND + EXTERN char_u *p_dict; /* 'dictionary' */ + #endif +diff -Nur vim60am.old/src/os_msdos.c vim60am/src/os_msdos.c +--- vim60am.old/src/os_msdos.c Wed Jul 4 20:42:09 2001 ++++ vim60am/src/os_msdos.c Tue Jul 3 18:39:48 2001 +@@ -78,7 +78,7 @@ + */ + + unsigned long S_ulScreenBase = 0xb8000; +-unsigned short S_uiAttribute = 0; ++unsigned short S_uiAttribute = 7 << 8; + int S_iCurrentRow = 0; /* These are 0 offset */ + int S_iCurrentColumn = 0; + int S_iLeft = 0; /* Scroll window; these are 1 offset */ +@@ -248,6 +248,9 @@ + } + else + { ++ if(iChar == ' ') ++ uiValue = ((S_uiAttribute & 0xf700) | 0x700) | ' '; ++ else + uiValue = S_uiAttribute | (unsigned char)iChar; + + /* +@@ -309,6 +312,7 @@ + mytextattr(int iAttribute) + { + S_uiAttribute = (unsigned short)iAttribute << 8; ++ textattr(iAttribute); /* for delline() etc */ + } + + static void +@@ -322,6 +326,7 @@ + { + S_uiAttribute = (unsigned short)((S_uiAttribute & 0xf000) + | (unsigned short)iTextColor << 8); ++ textattr(S_uiAttribute >> 8); /* for delline() etc */ + } + + static void +@@ -329,6 +334,7 @@ + { + S_uiAttribute = (unsigned short)((S_uiAttribute & 0x0f00) + | (unsigned short)(iBkgColor << 12)); ++ textattr(S_uiAttribute >> 8); /* for delline() etc */ + } + /* + * Getdigits: Get a number from a string and skip over it. +@@ -470,6 +476,7 @@ + static union REGS regs; + static int saved = FALSE; + ++ return; /* WM */ + if (restore) + { + if (saved) +@@ -495,6 +502,7 @@ + mch_set_cursor_shape(int thickness) + { + union REGS regs; ++ return; /* WM */ + + regs.h.ch = 7 - thickness; /*Starting Line*/ + regs.h.cl = 7; /*Ending Line*/ +@@ -508,6 +516,7 @@ + int idx; + int thickness; + ++ return; /* WM */ + /* + * How the cursor is drawn depends on the current mode. + */ +@@ -2226,6 +2235,7 @@ + char * + djgpp_setlocale(void) + { ++ char *country; + __dpmi_regs regs; + struct { char id; unsigned short off, seg; } __attribute__ ((packed)) info; + unsigned char buffer[0x82], lower, upper; +@@ -2267,6 +2277,127 @@ + __dj_ctype_tolower[upper+1] = lower; + } + } ++ if ((country = getenv("COUNTRY")) != NULL) ++ { ++ if(!strcmp(country, "MAZOWIA")) ++ { ++ __dj_ctype_flags[(unsigned char)'†' + 1] = LOCASE; ++ __dj_ctype_flags[(unsigned char)'' + 1] = UPCASE; ++ __dj_ctype_flags[(unsigned char)'' + 1] = LOCASE; ++ __dj_ctype_flags[(unsigned char)'•' + 1] = UPCASE; ++ __dj_ctype_flags[(unsigned char)'‘' + 1] = LOCASE; ++ __dj_ctype_flags[(unsigned char)'' + 1] = UPCASE; ++ __dj_ctype_flags[(unsigned char)'’' + 1] = LOCASE; ++ __dj_ctype_flags[(unsigned char)'œ' + 1] = UPCASE; ++ __dj_ctype_flags[(unsigned char)'¤' + 1] = LOCASE; ++ __dj_ctype_flags[(unsigned char)'¥' + 1] = UPCASE; ++ __dj_ctype_flags[(unsigned char)'¢' + 1] = LOCASE; ++ __dj_ctype_flags[(unsigned char)'£' + 1] = UPCASE; ++ __dj_ctype_flags[(unsigned char)'ž' + 1] = LOCASE; ++ __dj_ctype_flags[(unsigned char)'˜' + 1] = UPCASE; ++ __dj_ctype_flags[(unsigned char)'¦' + 1] = LOCASE; ++ __dj_ctype_flags[(unsigned char)' ' + 1] = UPCASE; ++ __dj_ctype_flags[(unsigned char)'§' + 1] = LOCASE; ++ __dj_ctype_flags[(unsigned char)'¡' + 1] = UPCASE; ++ ++ __dj_ctype_toupper[(unsigned char)'†'+ 1] = (unsigned char)''; ++ __dj_ctype_toupper[(unsigned char)''+ 1] = (unsigned char)''; ++ __dj_ctype_toupper[(unsigned char)''+ 1] = (unsigned char)'•'; ++ __dj_ctype_toupper[(unsigned char)'•'+ 1] = (unsigned char)'•'; ++ __dj_ctype_toupper[(unsigned char)'‘'+ 1] = (unsigned char)''; ++ __dj_ctype_toupper[(unsigned char)''+ 1] = (unsigned char)''; ++ __dj_ctype_toupper[(unsigned char)'’'+ 1] = (unsigned char)'œ'; ++ __dj_ctype_toupper[(unsigned char)'œ'+ 1] = (unsigned char)'œ'; ++ __dj_ctype_toupper[(unsigned char)'¤'+ 1] = (unsigned char)'¥'; ++ __dj_ctype_toupper[(unsigned char)'¥'+ 1] = (unsigned char)'¥'; ++ __dj_ctype_toupper[(unsigned char)'¢'+ 1] = (unsigned char)'£'; ++ __dj_ctype_toupper[(unsigned char)'£'+ 1] = (unsigned char)'£'; ++ __dj_ctype_toupper[(unsigned char)'ž'+ 1] = (unsigned char)'˜'; ++ __dj_ctype_toupper[(unsigned char)'˜'+ 1] = (unsigned char)'˜'; ++ __dj_ctype_toupper[(unsigned char)'¦'+ 1] = (unsigned char)' '; ++ __dj_ctype_toupper[(unsigned char)' '+ 1] = (unsigned char)' '; ++ __dj_ctype_toupper[(unsigned char)'§'+ 1] = (unsigned char)'¡'; ++ __dj_ctype_toupper[(unsigned char)'¡'+ 1] = (unsigned char)'¡'; ++ ++ __dj_ctype_tolower[(unsigned char)'†'+ 1] = (unsigned char)'†'; ++ __dj_ctype_tolower[(unsigned char)''+ 1] = (unsigned char)'†'; ++ __dj_ctype_tolower[(unsigned char)''+ 1] = (unsigned char)''; ++ __dj_ctype_tolower[(unsigned char)'•'+ 1] = (unsigned char)''; ++ __dj_ctype_tolower[(unsigned char)'‘'+ 1] = (unsigned char)'‘'; ++ __dj_ctype_tolower[(unsigned char)''+ 1] = (unsigned char)'‘'; ++ __dj_ctype_tolower[(unsigned char)'’'+ 1] = (unsigned char)'’'; ++ __dj_ctype_tolower[(unsigned char)'œ'+ 1] = (unsigned char)'’'; ++ __dj_ctype_tolower[(unsigned char)'¤'+ 1] = (unsigned char)'¤'; ++ __dj_ctype_tolower[(unsigned char)'¥'+ 1] = (unsigned char)'¤'; ++ __dj_ctype_tolower[(unsigned char)'¢'+ 1] = (unsigned char)'¢'; ++ __dj_ctype_tolower[(unsigned char)'£'+ 1] = (unsigned char)'¢'; ++ __dj_ctype_tolower[(unsigned char)'ž'+ 1] = (unsigned char)'ž'; ++ __dj_ctype_tolower[(unsigned char)'˜'+ 1] = (unsigned char)'ž'; ++ __dj_ctype_tolower[(unsigned char)'¦'+ 1] = (unsigned char)'¦'; ++ __dj_ctype_tolower[(unsigned char)' '+ 1] = (unsigned char)'¦'; ++ __dj_ctype_tolower[(unsigned char)'§'+ 1] = (unsigned char)'§'; ++ __dj_ctype_tolower[(unsigned char)'¡'+ 1] = (unsigned char)'§'; ++ } ++ else if(!strcmp(country, "CP1250")) ++ { ++ __dj_ctype_flags[(unsigned char)'9' + 1] = LOCASE; ++ __dj_ctype_flags[(unsigned char)'%' + 1] = UPCASE; ++ __dj_ctype_flags[(unsigned char)'f' + 1] = LOCASE; ++ __dj_ctype_flags[(unsigned char)'F' + 1] = UPCASE; ++ __dj_ctype_flags[(unsigned char)'j' + 1] = LOCASE; ++ __dj_ctype_flags[(unsigned char)'J' + 1] = UPCASE; ++ __dj_ctype_flags[(unsigned char)'3' + 1] = LOCASE; ++ __dj_ctype_flags[(unsigned char)'#' + 1] = UPCASE; ++ __dj_ctype_flags[(unsigned char)'q' + 1] = LOCASE; ++ __dj_ctype_flags[(unsigned char)'Q' + 1] = UPCASE; ++ __dj_ctype_flags[(unsigned char)'s' + 1] = LOCASE; ++ __dj_ctype_flags[(unsigned char)'S' + 1] = UPCASE; ++ __dj_ctype_flags[(unsigned char)'' + 1] = LOCASE; ++ __dj_ctype_flags[(unsigned char)' ' + 1] = UPCASE; ++ __dj_ctype_flags[(unsigned char)'' + 1] = LOCASE; ++ __dj_ctype_flags[(unsigned char)'' + 1] = UPCASE; ++ __dj_ctype_flags[(unsigned char)'?' + 1] = LOCASE; ++ __dj_ctype_flags[(unsigned char)'/' + 1] = UPCASE; ++ ++ __dj_ctype_toupper[(unsigned char)'9'+ 1] = (unsigned char)'%'; ++ __dj_ctype_toupper[(unsigned char)'%'+ 1] = (unsigned char)'%'; ++ __dj_ctype_toupper[(unsigned char)'f'+ 1] = (unsigned char)'F'; ++ __dj_ctype_toupper[(unsigned char)'F'+ 1] = (unsigned char)'F'; ++ __dj_ctype_toupper[(unsigned char)'j'+ 1] = (unsigned char)'J'; ++ __dj_ctype_toupper[(unsigned char)'J'+ 1] = (unsigned char)'J'; ++ __dj_ctype_toupper[(unsigned char)'3'+ 1] = (unsigned char)'#'; ++ __dj_ctype_toupper[(unsigned char)'#'+ 1] = (unsigned char)'#'; ++ __dj_ctype_toupper[(unsigned char)'q'+ 1] = (unsigned char)'Q'; ++ __dj_ctype_toupper[(unsigned char)'Q'+ 1] = (unsigned char)'Q'; ++ __dj_ctype_toupper[(unsigned char)'s'+ 1] = (unsigned char)'S'; ++ __dj_ctype_toupper[(unsigned char)'S'+ 1] = (unsigned char)'S'; ++ __dj_ctype_toupper[(unsigned char)''+ 1] = (unsigned char)' '; ++ __dj_ctype_toupper[(unsigned char)' '+ 1] = (unsigned char)' '; ++ __dj_ctype_toupper[(unsigned char)''+ 1] = (unsigned char)''; ++ __dj_ctype_toupper[(unsigned char)''+ 1] = (unsigned char)''; ++ __dj_ctype_toupper[(unsigned char)'?'+ 1] = (unsigned char)'/'; ++ __dj_ctype_toupper[(unsigned char)'/'+ 1] = (unsigned char)'/'; ++ ++ __dj_ctype_tolower[(unsigned char)'9'+ 1] = (unsigned char)'9'; ++ __dj_ctype_tolower[(unsigned char)'%'+ 1] = (unsigned char)'9'; ++ __dj_ctype_tolower[(unsigned char)'f'+ 1] = (unsigned char)'f'; ++ __dj_ctype_tolower[(unsigned char)'F'+ 1] = (unsigned char)'f'; ++ __dj_ctype_tolower[(unsigned char)'j'+ 1] = (unsigned char)'j'; ++ __dj_ctype_tolower[(unsigned char)'J'+ 1] = (unsigned char)'j'; ++ __dj_ctype_tolower[(unsigned char)'3'+ 1] = (unsigned char)'3'; ++ __dj_ctype_tolower[(unsigned char)'#'+ 1] = (unsigned char)'3'; ++ __dj_ctype_tolower[(unsigned char)'q'+ 1] = (unsigned char)'q'; ++ __dj_ctype_tolower[(unsigned char)'Q'+ 1] = (unsigned char)'q'; ++ __dj_ctype_tolower[(unsigned char)'s'+ 1] = (unsigned char)'s'; ++ __dj_ctype_tolower[(unsigned char)'S'+ 1] = (unsigned char)'s'; ++ __dj_ctype_tolower[(unsigned char)''+ 1] = (unsigned char)''; ++ __dj_ctype_tolower[(unsigned char)' '+ 1] = (unsigned char)''; ++ __dj_ctype_tolower[(unsigned char)''+ 1] = (unsigned char)''; ++ __dj_ctype_tolower[(unsigned char)''+ 1] = (unsigned char)''; ++ __dj_ctype_tolower[(unsigned char)'?'+ 1] = (unsigned char)'?'; ++ __dj_ctype_tolower[(unsigned char)'/'+ 1] = (unsigned char)'?'; ++ } ++ } + + return "C"; + } +diff -Nur vim60am.old/src/proto/spell.pro vim60am/src/proto/spell.pro +--- vim60am.old/src/proto/spell.pro Thu Jan 1 01:00:00 1970 ++++ vim60am/src/proto/spell.pro Wed Jun 27 19:19:35 2001 +@@ -0,0 +1,5 @@ ++int reload_dict(void); ++void ex_spell(exarg_T *eap); ++int get_spell_attr(colnr_T spell_col, colnr_T col, char_u *line); ++int set_to_private_dict(char *line, int cursor_col, int convert_to_lower); ++void spell_save_private_dict(void); +diff -Nur vim60am.old/src/proto.h vim60am/src/proto.h +--- vim60am.old/src/proto.h Wed Jul 4 20:42:09 2001 ++++ vim60am/src/proto.h Tue Jul 3 18:38:16 2001 +@@ -64,6 +64,9 @@ + # include "os_qnx.pro" + # endif + ++#ifdef FEAT_SPELL_HL ++# include "spell.pro" ++#endif + # include "buffer.pro" + # include "charset.pro" + # ifdef UNIX +diff -Nur vim60am.old/src/screen.c vim60am/src/screen.c +--- vim60am.old/src/screen.c Wed Jul 4 20:42:09 2001 ++++ vim60am/src/screen.c Tue Jul 3 18:37:48 2001 +@@ -115,6 +115,9 @@ + static match_T match_hl; /* used for ":match" highlight matching */ + #endif + ++#ifdef FEAT_SPELL_HL ++extern int spell_flag; ++#endif + #ifdef FEAT_FOLDING + static foldinfo_T win_foldinfo; /* info for 'foldcolumn' */ + #endif +@@ -2333,6 +2336,9 @@ + int syntax_attr = 0; /* attributes desired by syntax */ + int has_syntax = FALSE; /* this buffer has syntax highl. */ + #endif ++#ifdef FEAT_SPELL_HL ++ int spell_attr = 0; ++#endif + int extra_check; /* has syntax or linebreak */ + #ifdef FEAT_MBYTE + int multi_attr = 0; /* attributes desired by multibyte */ +@@ -2406,8 +2412,18 @@ + #else + extra_check = 0; + #endif ++#if defined(FEAT_SYN_HL) || defined(FEAT_SPELL_HL) ++ if ( + #ifdef FEAT_SYN_HL +- if (syntax_present(wp->w_buffer)) ++ syntax_present(wp->w_buffer) ++#else ++ 0 ++#endif ++#ifdef FEAT_SPELL_HL ++ || ++ spell_flag ++#endif ++ ) + { + syntax_start(wp, lnum); + has_syntax = TRUE; +@@ -3004,6 +3020,10 @@ + else if (search_attr == 0 && has_syntax) + char_attr = syntax_attr; + #endif ++#ifdef FEAT_SPELL_HL ++ else if (spell_flag) ++ char_attr = spell_attr; ++#endif + else + char_attr = search_attr; + +@@ -3238,6 +3258,15 @@ + + if (area_attr == 0 && search_attr == 0) + char_attr = syntax_attr; ++ } ++#endif ++#ifdef FEAT_SPELL_HL ++ if (spell_flag) ++ { ++ v = ptr - line; ++ spell_attr = get_spell_attr((colnr_T)v - 1, col, ml_get_buf(wp->w_buffer, lnum, FALSE)); ++ if (!area_attr && !char_attr) ++ char_attr = spell_attr; + } + #endif + #ifdef FEAT_LINEBREAK +diff -Nur vim60am.old/src/spell/config.h vim60am/src/spell/config.h +--- vim60am.old/src/spell/config.h Thu Jan 1 01:00:00 1970 ++++ vim60am/src/spell/config.h Wed Jun 27 19:16:50 2001 +@@ -0,0 +1,846 @@ ++#include "local.h" /* local definitions for options */ ++ ++/* ++** Major-differences selection. The default system is BSD; for USG ++** or non-UNIX systems you should add the appropriate #define to local.h. ++*/ ++#ifndef USG ++#undef USG /* Define this in local.h for System V machines */ ++#endif /* USG */ ++ ++#ifndef WIN32 ++#include ++#include ++#endif ++#ifndef USG ++# ifndef FEAT_SPELL_HL ++# if HAVE_DIRENT_H ++# include ++# ifndef NAMLEN ++# define NAMLEN(dirent) strlen((dirent)->d_name) ++# endif ++# else ++# define dirent direct ++# define NAMLEN(dirent) (dirent)->d_namlen ++# if HAVE_SYS_NDIR_H ++# include ++# endif ++# if HAVE_SYS_DIR_H ++# include ++# endif ++# if HAVE_NDIR_H ++# include ++# endif ++# endif ++# endif ++#endif /* USG */ ++ ++/* ++** Things that normally go in a Makefile. Define these just like you ++** might in the Makefile, except you should use #define instead of ++** make's assignment syntax. Everything must be double-quoted, and ++** (unlike make) you can't use any sort of $-syntax to pick up the ++** values of other definitions. ++*/ ++#ifndef CC ++#define CC "cc" ++#endif /* CC */ ++#ifndef EMACS ++#define EMACS "emacs" ++#endif /* EMACS */ ++#ifndef LINT ++#define LINT "lint" ++#endif /* LINT */ ++#ifndef CFLAGS ++#define CFLAGS "-O" ++#endif /* CFLAGS */ ++#ifndef LINTFLAGS ++#define LINTFLAGS "" ++#endif /* LINTFLAGS */ ++#ifndef YACC ++#define YACC "yacc" ++#endif /* YACC */ ++ ++/* ++** Libraries that may need to be added to the cc line to get ispell to ++** link. Normally, this should be null. ++*/ ++#ifndef LIBES ++#define LIBES "" ++#endif ++ ++/* ++** TERMLIB - where to get the termcap library. Should be -ltermcap or ++** -lcurses on most systems. ++*/ ++#ifndef TERMLIB ++#define TERMLIB "-lncurses" ++#endif ++ ++/* ++** REGLIB - where to get the regular-expression routines, if ++** REGEX_LOOKUP is defined. Should be -lPW on USG systems, null on ++** BSD systems. ++*/ ++#ifndef REGLIB ++#define REGLIB "" ++#endif ++ ++/* ++** Where to install various components of ispell. BINDIR contains ++** binaries. LIBDIR contains hash tables and affix files. ELISPDIR ++** contains emacs lisp files (if any) and TEXINFODIR contains emacs ++** TeXinfo files. MAN1DIR and MAN4DIR will hold the chapter-1 and ++** chapter-4 manual pages, respectively. ++** ++** If you intend to use multiple dictionary files, I would suggest ++** LIBDIR be a directory which will contain nothing else, so sensible ++** names can be constructed for the -d option without conflict. ++*/ ++#ifndef BINDIR ++#define BINDIR "/usr/bin" ++#endif ++#ifndef LIBDIR ++#define LIBDIR "/usr/lib/ispell" ++#endif ++#ifndef ELISPDIR ++#define ELISPDIR "/usr/lib/emacs/site-lisp" ++#endif ++#ifndef TEXINFODIR ++#define TEXINFODIR "/usr/share/info" ++#endif ++#ifndef MAN1DIR ++#define MAN1DIR "/usr/share/man/man1" ++#endif ++#ifndef MAN4DIR ++#define MAN4DIR "/usr/share/man/man4" ++#endif ++ ++/* ++** Extensions to put on manual pages. Usually these are ".1" or ".1l". ++*/ ++#ifndef MAN1EXT ++#define MAN1EXT ".1" ++#endif ++#ifndef MAN4EXT ++#define MAN4EXT ".4" ++#endif ++ ++/* ++** List of all hash files (languages) which will be supported by ispell. ++** ++** This variable has a complex format so that many options can be ++** specified. The format is as follows: ++** ++** [,...] [ [, ...] ...] ++** ++** where ++** ++** language is the name of a subdirectory of the ++** "languages" directory ++** make-options are options that are to be passed to "make" in ++** the specified directory. The make-options ++** should not, in general, specify a target, as ++** this will be provided by the make process. ++** ++** For example, if LANGUAGES is: ++** ++** "{american,MASTERDICTS=american.med+,HASHFILES=americanmed+.hash,EXTRADICT=/usr/dict/words /usr/dict/web2} {deutsch,DICTALWAYS=deutsch.sml,DICTOPTIONS=}" ++** ++** then the American-English and Deutsch (German) languages will be supported, ++** and the following variable settings will be passed to the two Makefiles: ++** ++** American: ++** ++** MASTERDICTS='american.med+' ++** HASHFILES='americanmed+.hash' ++** EXTRADICT='/usr/dict/words /usr/dict/web2' ++** ++** Deutsch: ++** ++** DICTALWAYS='deutsch.sml' ++** DICTOPTIONS='' ++** ++** Notes on the syntax: The makefile is not very robust. If you have ++** make problems, or if make seems to fail in the language-subdirs ++** dependency, check your syntax. The makefile adds single quotes to ++** the individual variables in the LANGUAGES specification, so don't ++** use quotes of any kind. ++** ++** In the future, the first language listed in this variable will ++** become the default, and the DEFHASH, DEFLANG, and DEFPAFF, ++** variables will all become obsolete. So be sure to put your default ++** language first, to make later conversion easier! ++** ++** Notes on options for the various languages will be found in the ++** Makefiles for those languages. Some of those languages may require ++** you to also change various limits limits like MASKBITS or the ++** length parameters. ++** ++** A special note on the English language: because the British and ++** American dialects use different spelling, you should usually select ++** one or the other of these. If you select both, the setting of ++** MASTERHASH will determine which becomes the language linked to ++** DEFHASH (which will usually be named english.hash). ++** ++** On MSDOS systems you must use names which are consistent with the ++** 8+3 filename restrictions, or you will risk filename collision. See ++** the file pc/local.djgpp for details. ++*/ ++#ifndef LANGUAGES ++#define LANGUAGES "{american,MASTERDICTS=american.med+,HASHFILES=americanmed+.hash,EXTRADICT=/usr/dict/words}" ++#endif /* LANGUAGES */ ++ ++/* ++** Master hash file for DEFHASH. This is the name of a hash file ++** built by a language Makefile. It should be the most-popular hash ++** file on your system, because it is the one that will be used by ++** default. It must be listed in LANGUAGES, above. ++*/ ++#ifndef MASTERHASH ++#define MASTERHASH "polish+.hash" ++#endif ++ ++/* ++** Default native-language hash file. This is the name given to the ++** hash table that will be used if no language is specified to ++** ispell. It is a link to MASTERHASH, above. ++*/ ++#ifndef DEFHASH ++#define DEFHASH "polish.hash" ++#endif ++ ++/* ++** Language tables for the default language. This must be the name of ++** the affix file that was used to generate the MASTERHASH/DEFHASH, ++** above. ++*/ ++#ifndef DEFLANG ++#define DEFLANG "polish.aff" ++#endif ++ ++/* ++** Language to use for error messages. If there are no messages in this ++** language, English will be used instead. ++*/ ++#ifndef MSGLANG ++#define MSGLANG "polish" ++#endif /* MSGLANG */ ++ ++/* ++** If your sort command accepts the -T switch to set temp file ++** locations (try it out; it exists but is undocumented on some ++** systems), make the following variable the null string. Otherwise ++** leave it as the sed script. ++*/ ++#ifndef SORTTMP ++#define SORTTMP "-e '/!!SORTTMP!!/s/=.*$/=/'" ++#endif ++ ++/* ++** If your sort command accepts the -T switch (see above), make the ++** following variable refer to a temporary directory with lots of ++** space. Otherwise make it the null string. ++*/ ++#ifndef MAKE_SORTTMP ++#define MAKE_SORTTMP "-T ${TMPDIR-/usr/tmp}" ++#endif ++ ++/* ++** If your shell needs ": Use /bin/sh" at the first line of a shell ++** script, make the following variable the null string. Otherwise ++** leave it as this sed script which will put a "#!/bin/sh" there. ++*/ ++#ifndef MAKE_POUND_BANG ++#define MAKE_POUND_BANG "-e 1s,^:.*Use.*/bin/sh,#!/bin/sh," ++#endif ++ ++ ++/* ++** INSTALL program. Could be a copy program like cp or something fancier ++** like /usr/ucb/install -c ++*/ ++#ifndef INSTALL ++#define INSTALL "cp" ++#endif ++ ++/* ++** If your system has the rename(2) system call, define HAS_RENAME and ++** ispell will use that call to rename backup files. Otherwise, it ++** will use link/unlink. There is no harm in this except on MS-DOS, ++** which doesn't support link/unlink. ++*/ ++#ifndef HAS_RENAME ++#undef HAS_RENAME ++#endif /* HAS_RENAME */ ++ ++/* type given to signal() by signal.h */ ++#ifndef SIGNAL_TYPE ++#define SIGNAL_TYPE void ++#endif ++ ++/* environment variable for user's word list */ ++#ifndef PDICTVAR ++#define PDICTVAR "WORDLIST" ++#endif ++ ++/* prefix part of default word list */ ++#ifndef DEFPDICT ++#define DEFPDICT ".ispell_" ++#endif ++ ++/* ++** suffix part of default word list ++*/ ++#ifndef DEFPAFF ++#define DEFPAFF "words" ++#endif ++ ++/* old place to look for default word list */ ++#ifndef OLDPDICT ++#define OLDPDICT ".ispell_" ++#endif /* OLDPDICT */ ++#ifndef OLDPAFF ++#define OLDPAFF "words" ++#endif /* OLDPAFF */ ++ ++/* environment variable for include file string */ ++#ifndef INCSTRVAR ++#define INCSTRVAR "INCLUDE_STRING" ++#endif ++ ++/* default include string */ ++#ifndef DEFINCSTR ++#define DEFINCSTR "&Include_File&" ++#endif ++ ++/* mktemp template for temporary file - MUST contain 6 consecutive X's */ ++#ifndef TEMPNAME ++#define TEMPNAME "/tmp/ispellXXXXXX" ++#endif ++ ++/* ++** If REGEX_LOOKUP is undefined, the lookup command (L) will use the look(1) ++** command (if available) or the egrep command. If REGEX_LOOKUP is defined, ++** the lookup command will use the internal dictionary and the ++** regular-expression library (which you must supply separately. There is ++** a public-domain library available; libraries are also distributed with ++** both BSD and System V. ++** ++** The advantage of no REGEX_LOOKUP is that it is often much faster, especially ++** if the look(1) command is available, that the words found are presented ++** in alphabetical order, and that the list of words searched is larger. ++** The advantage of REGEX_LOOKUP is that ispell doesn't need to spawn another ++** program, and the list of words searched is exactly the list of (root) words ++** that ispell will accept. (However, note that words formed with affixes will ++** not be found; this can produce some artifacts. For example, since ++** "brother" can be formed as "broth+er", a lookup command might fail to ++** find "brother.") ++*/ ++#ifndef REGEX_LOOKUP ++#undef REGEX_LOOKUP ++#endif /* REGEX_LOOKUP */ ++ ++/* ++** Choose the proper type of regular-expression routines here. BSD ++** and public-domain systems have routines called re_comp and re_exec; ++** System V uses regcmp and regex. ++** ++** REGCTYPE is the type of a variable to hold the compiled regexp ++** REGCMP(re,str) is the function which compiles a regexp in `str' into ++** a compiled regexp `re' declared as REGCTYPE and ++** returns `re'. ++** REGEX(re,str,dummy) is a function which matches `str' against a compiled ++** regexp in `re' and returns a non-NULL pointer if it ++** matches, NULL otherwise. ++** REGFREE(re) is anything that should be done when the compiled ++** regexp `re' is no longer needed. It can be also used ++** to allocate any structures required to compile a ++** regexp, since it is called *before* compiling a new ++** regexp (that's where we know that the old one will no ++** longer be used). ++** ++** Here is one way of defining these if you have POSIX regexp functions: ++** ++** #include ++** #include ++** #define REGCTYPE regex_t * ++** #define REGCMP(re,str) (regcomp (re, str, 0), re) ++** #define REGEX(re, str, dummy) \ ++** (re != 0 && regexec (re, str, 0, 0, 0) == 0 ? (char *)1 : NULL) ++** #define REGFREE(re) \ ++** do { \ ++** if (re == 0) \ ++** re = (regex_t *)calloc (1, sizeof (regex_t)); \ ++** else \ ++** regfree(re); \ ++** } while (0) ++** ++*/ ++#ifdef REGEX_LOOKUP ++#ifndef REGCMP ++#ifdef USG ++#define REGCTYPE char * ++#define REGCMP(re,str) regcmp (str, (char *) 0) ++#define REGEX(re, str, dummy) regex (re, str, dummy, dummy, dummy, dummy, \ ++ dummy, dummy, dummy, dummy, dummy, dummy) ++#define REGFREE(re) do {if (re != NULL) free (re); re = NULL;} \ ++ while (0) ++#else /* USG */ ++#define REGCTYPE char * ++#define REGFREE(re) (void)0 ++#define REGCMP(re,str) re_comp (str) ++#define REGEX(re, str, dummy) re_exec (str) ++#endif /* USG */ ++#endif /* REGCMP */ ++#endif /* REGEX_LOOKUP */ ++ ++/* look command (if look(1) MAY BE available - ignored if not) */ ++#ifndef REGEX_LOOKUP ++#ifndef LOOK ++#define LOOK "look -df" ++#endif ++#endif /* REGEX_LOOKUP */ ++ ++/* path to egrep (use speeded up version if available) */ ++#ifndef EGREPCMD ++#ifdef USG ++#define EGREPCMD "/bin/egrep" ++#else ++#define EGREPCMD "/usr/bin/egrep -i" ++#endif ++#endif ++ ++/* path to wordlist for Lookup command (typically /usr/dict/{words|web2}) */ ++/* note that /usr/dict/web2 is usually a bad idea due to obscure words */ ++#ifndef WORDS ++#define WORDS "/usr/dict/words" ++#endif ++ ++/* buffer size to use for file names if not in sys/param.h */ ++#ifndef MAXPATHLEN ++#define MAXPATHLEN 240 ++#endif ++ ++/* max file name length (will truncate to fit BAKEXT) if not in sys/param.h */ ++#ifndef MAXNAMLEN ++#define MAXNAMLEN 14 ++#endif ++ ++/* define if you want .bak file names truncated to MAXNAMLEN characters */ ++#ifndef TRUNCATEBAK ++#undef TRUNCATEBAK ++#endif /* TRUNCATEBAK */ ++ ++/* largest word accepted from a file by any input routine, plus one */ ++#ifndef INPUTWORDLEN ++#define INPUTWORDLEN 100 ++#endif ++ ++/* largest amount that a word might be extended by adding affixes */ ++#ifndef MAXAFFIXLEN ++#define MAXAFFIXLEN 20 ++#endif ++ ++/* ++** Define the following to suppress the 8-bit character feature. ++** Unfortunately, this doesn't work as well as it might, because ispell ++** only strips the 8th bit in some places. For example, it calls strcmp() ++** quite often without first stripping parity. However, I really wonder ++** about the utility of this option, so I haven't bothered to fix it. If ++** you think the stripping feature of NO8BIT is useful, you might let me ++** (Geoff Kuenning) know. ++** ++** Nevertheless, NO8BIT is a useful option for other reasons. If NO8BIT ++** is defined, ispell will probably use 8-bit characters internally; ++** this improves time efficiency and saves a small amount of space ++** in the hash file. Thus, I recommend you specify NO8BIT unless you ++** actually expect to be spelling files which use a 256-character set. ++*/ ++#ifndef NO8BIT ++#undef NO8BIT ++#endif /* NO8BIT */ ++ ++/* ++** Number of mask bits (affix flags) supported. Must be 32, 64, 128, or ++** 256. If MASKBITS is 32 or 64, there are really only 26 or 58 flags ++** available, respectively. If it is 32, the flags are named with the ++** 26 English uppercase letters; lowercase will be converted to uppercase. ++** If MASKBITS is 64, the 58 flags are named 'A' through 'z' in ASCII ++** order, including the 6 special characters from 'Z' to 'a': "[\]^_`". ++** If MASKBITS is 128 or 256, all the 7-bit or 8-bit characters, ++** respectively, are theoretically available, though a few (newline, slash, ++** null byte) are pretty hard to actually use successfully. ++** ++** Note that a number of non-English affix files depend on having a ++** larger value for MASKBITS. See the affix files for more ++** information. ++*/ ++#ifndef MASKBITS ++#define MASKBITS 64 ++#endif ++ ++/* ++** C type to use for masks. This should be a type that the processor ++** accesses efficiently. ++** ++** MASKTYPE_WIDTH must correctly reflect the number of bits in a ++** MASKTYPE. Unfortunately, it is also required to be a constant at ++** preprocessor time, which means you can't use the sizeof operator to ++** define it. ++** ++** Note that MASKTYPE *must* match MASKTYPE_WIDTH or you may get ++** division-by-zero errors! ++*/ ++#ifndef MASKTYPE ++#define MASKTYPE long ++#endif ++#ifndef MASKTYPE_WIDTH ++#define MASKTYPE_WIDTH 32 ++#endif ++#if MASKBITS < MASKTYPE_WIDTH ++#undef MASKBITS ++#define MASKBITS MASKTYPE_WIDTH ++#endif /* MASKBITS < MASKTYPE_WIDTH */ ++ ++ ++/* maximum number of include files supported by xgets; set to 0 to disable */ ++#ifndef MAXINCLUDEFILES ++#define MAXINCLUDEFILES 5 ++#endif ++ ++/* ++** Maximum hash table fullness percentage. Larger numbers trade space ++** for time. ++**/ ++#ifndef MAXPCT ++#define MAXPCT 70 /* Expand table when 70% full */ ++#endif ++ ++/* ++** Maximum number of "string" characters that can be defined in a ++** language (affix) file. Don't forget that an upper/lower string ++** character counts as two! ++*/ ++#ifndef MAXSTRINGCHARS ++#define MAXSTRINGCHARS 100 ++#endif /* MAXSTRINGCHARS */ ++ ++/* ++** Maximum length of a "string" character. The default is appropriate for ++** nroff-style characters starting with a backslash. ++*/ ++#ifndef MAXSTRINGCHARLEN ++#define MAXSTRINGCHARLEN 10 ++#endif /* MAXSTRINGCHARLEN */ ++ ++/* ++** the S_NOPARITY mask is applied to user input characters from the terminal ++** in order to mask out the parity bit. ++*/ ++#ifdef NO8BIT ++#define S_NOPARITY 0x7f ++#else ++#define S_NOPARITY 0xff ++#endif ++ ++ ++/* ++** the terminal mode for ispell, set to CBREAK or RAW ++** ++*/ ++#ifndef TERM_MODE ++#define TERM_MODE CBREAK ++#endif ++ ++/* ++** Define this if you want your columns of words to be of equal length. ++** This will spread short word lists across the screen instead of down it. ++*/ ++#ifndef EQUAL_COLUMNS ++#undef EQUAL_COLUMNS ++#endif /* EQUAL_COLUMNS */ ++ ++/* ++** This is the extension that will be added to backup files ++*/ ++#ifndef BAKEXT ++#define BAKEXT ".bak" ++#endif ++ ++/* ++** Define this if you want to suppress the capitalization-checking ++** feature. This will reduce the size of the hashed dictionary on ++** most 16-bit and some 32-bit machines. This option is not ++** recommended. ++*/ ++#ifndef NO_CAPITALIZATION_SUPPORT ++#undef NO_CAPITALIZATION_SUPPORT ++#endif /* NO_CAPITALIZATION_SUPPORT */ ++ ++/* ++** Define this if you want your personal dictionary sorted. This may take ++** a long time for very large dictionaries. Dictionaries larger than ++** SORTPERSONAL words will not be sorted. Define SORTPERSONAL as zero ++** to disable this feature. ++*/ ++#ifndef SORTPERSONAL ++#define SORTPERSONAL 1000 ++#endif ++ ++/* ++** Define this if you want to use the shell for interpretation of commands ++** issued via the "L" command, "^Z" under System V, and "!". If this is ++** not defined then a direct fork()/exec() will be used in place of the ++** normal system(). This may speed up these operations greately on some ++** systems. ++*/ ++#ifndef USESH ++#undef USESH ++#endif /* USESH */ ++ ++/* ++** Maximum language-table search size. Smaller numbers make ispell ++** run faster, at the expense of more memory (the lowest reasonable value ++** is 2). If a given character appears in a significant position in ++** more than MAXSEARCH suffixes, it will be given its own index table. ++** If you change this, define INDEXDUMP in lookup.c to be sure your ++** index table looks reasonable. ++*/ ++#ifndef MAXSEARCH ++#define MAXSEARCH 4 ++#endif ++ ++/* ++** Define this if you want to be able to type any command at a "type space ++** to continue" prompt. ++*/ ++#ifndef COMMANDFORSPACE ++#undef COMMANDFORSPACE ++#endif /* COMMANDFORSPACE */ ++ ++/* ++** Memory-allocation increment. Buildhash allocates memory in chunks ++** of this size, and then subdivides it to get its storage. This saves ++** much malloc execution time. A good number for this is the system ++** page size less the malloc storage overhead. ++** ++** Define this to zero to revert to using malloc/realloc. This is normally ++** useful only on systems with limited memory. ++*/ ++#ifndef MALLOC_INCREMENT ++#define MALLOC_INCREMENT 0 ++#endif ++ ++/* ++** Maximum number of "hits" expected on a word. This is basically the ++** number of different ways different affixes can produce the same word. ++** For example, with "english.aff", "brothers" can be produced 3 ways: ++** "brothers," "brother+s", or "broth+ers". If this is too low, no major ++** harm will be done, but ispell may occasionally forget a capitalization. ++*/ ++#ifndef MAX_HITS ++#define MAX_HITS 10 ++#endif ++ ++/* ++** Maximum number of capitalization variations expected in any word. ++** Besides the obvious all-lower, all-upper, and capitalized versions, ++** this includes followcase variants. If this is too low, no real ++** harm will be done, but ispell may occasionally fail to suggest a ++** correct capitalization. ++*/ ++#ifndef MAX_CAPS ++#define MAX_CAPS 10 ++#endif /* MAX_CAPS */ ++ ++/* Define this to ignore spelling check of entire LaTeX bibliography listings */ ++#ifndef IGNOREBIB ++#undef IGNOREBIB ++#endif ++ ++/* ++** Default nroff and TeX special characters. Normally, you won't want to ++** change this; instead you would override it in the language-definition ++** file. ++*/ ++#ifndef TEXSPECIAL ++#define TEXSPECIAL "{}$*.%#&?,;:!@~-" ++#endif ++ ++#ifndef NRSPECIAL ++#define NRSPECIAL "().\\*" ++#endif ++ ++/* ++** Defaults for certain command-line flags. ++*/ ++#ifndef DEFNOBACKUPFLAG ++#define DEFNOBACKUPFLAG 0 /* Don't suppress backup file */ ++#endif ++#ifndef DEFTEXFLAG ++#define DEFTEXFLAG 0 /* Default to nroff mode */ ++#endif ++ ++/* ++** Define this if you want ispell to place a limitation on the maximum ++** size of the screen. On windowed workstations with very large windows, ++** the size of the window can be too much of a good thing, forcing the ++** user to look back and forth between the bottom and top of the screen. ++** If MAX_SCREEN_SIZE is nonzero, screens larger than this will be treated ++** as if they have only MAX_SCREEN_SIZE lines. A good value for this ++** variable is 24 or 30. Define it as zero to suppress the feature. ++*/ ++#ifndef MAX_SCREEN_SIZE ++#define MAX_SCREEN_SIZE 0 ++#endif ++ ++/* ++** The next three variables are used to provide a variable-size context ++** display at the bottom of the screen. Normally, the user will see ++** a number of lines equal to CONTEXTPCT of his screen, rounded down ++** (thus, with CONTEXTPCT == 10, a 24-line screen will produce two lines ++** of context). The context will never be greater than MAXCONTEXT or ++** less than MINCONTEXT. To disable this feature entirely, set MAXCONTEXT ++** and MINCONTEXT to the same value. To round context percentages up, ++** define CONTEXTROUNDUP. ++** ++** Warning: don't set MAXCONTEXT ridiculously large. There is a ++** static buffer of size MAXCONTEXT*BUFSIZ; since BUFSIZ is frequently ++** 1K or larger, this can create a remarkably large executable. ++*/ ++#ifndef CONTEXTPCT ++#define CONTEXTPCT 10 /* Use 10% of the screen for context */ ++#endif ++#ifndef MINCONTEXT ++#define MINCONTEXT 2 /* Always show at least 2 lines of context */ ++#endif ++#ifndef MAXCONTEXT ++#define MAXCONTEXT 10 /* Never show more than 10 lines of context */ ++#endif ++#ifndef CONTEXTROUNDUP ++#undef CONTEXTROUNDUP /* Don't round context up */ ++#endif ++ ++/* ++** Define this if you want the context lines to be displayed at the ++** bottom of the screen, the way they used to be, rather than at the top. ++*/ ++#ifndef BOTTOMCONTEXT ++#undef BOTTOMCONTEXT ++#endif /* BOTTOMCONTEXT */ ++ ++/* ++** Define this if you want the "mini-menu," which gives the most important ++** options at the bottom of the screen, to be the default (in any case, it ++** can be controlled with the "-M" switch). ++*/ ++#ifndef MINIMENU ++#undef MINIMENU ++#endif ++ ++/* ++** You might want to change this to zero if your users want to check ++** single-letter words against the dictionary. However, you should try ++** some sample runs using the -W switch before you try it out; you'd ++** be surprised how many single letters appear in documents. If you increase ++** MINWORD beyond 1, don't say I didn't warn you that it was a bad idea. ++*/ ++#ifndef MINWORD ++#define MINWORD 1 /* Words this short and shorter are always ok */ ++#endif ++ ++/* ++** ANSI C compilers are supposed to provide an include file, ++** "stdlib.h", which gives function prototypes for all library ++** routines. Define NO_STDLIB_H if you have a compiler that claims to ++** be ANSI, but doesn't provide this include file. ++*/ ++#ifndef NO_STDLIB_H ++#ifndef __STDC__ ++#define NO_STDLIB_H ++#endif /* __STDC__ */ ++#endif /* NO_STDLIB_H */ ++ ++/* ++** The following define is used by the ispell developer to help ++** double-check the software. Leave it undefined on other systems ++** unless you are especially fond of warning messages, or are pursuing ++** an inexplicable bug that might be related to a type mismatch. ++*/ ++#ifndef GENERATE_LIBARARY_PROTOS ++#undef GENERATE_LIBARARY_PROTOS ++#endif /* GENERATE_LIBARARY_PROTOS */ ++ ++/* ++** Symbols below this point are generally intended to cater to ++** idiosyncracies of specific machines and operating systems. ++** ++** MS-DOS users should also define HAS_RENAME, above, if appropriate. ++** ++** Define PIECEMEAL_HASH_WRITES if your system can't handle huge write ++** operations. This is known to be a problem on MS-DOS systems when ++** a 16-bit compiler is used to compile Ispell. ++*/ ++#ifndef PIECEMEAL_HASH_WRITES ++#undef PIECEMEAL_HASH_WRITES ++#endif /* PIECEMEAL_HASH_WRITES */ ++ ++/* ++** Redefine GETKEYSTROKE() to getkey() on some MS-DOS systems where ++** getchar() doesn't operate properly in raw mode. ++*/ ++#ifndef GETKEYSTROKE ++#define GETKEYSTROKE() getchar () ++#endif /* GETKEYSTROKE */ ++ ++/* ++** Define MSDOS_BINARY_OPEN to 0x8000 on MS-DOS systems. This can be ++** done by adding "#include fcntl.h" to your local.h file. ++*/ ++#ifndef MSDOS_BINARY_OPEN ++#ifdef O_BINARY ++#define MSDOS_BINARY_OPEN O_BINARY ++#else /* O_BINARY */ ++#define MSDOS_BINARY_OPEN 0 ++#endif /* O_BINARY */ ++#endif /* MSDOS_BINARY_OPEN */ ++ ++/* ++** Environment variable to use to locate the home directory. On DOS ++** systems you might want to set this to ISPELL_HOME to avoid ++** conflicts with other programs that look for a HOME environment ++** variable; on all other systems it should be just HOME. ++*/ ++#ifndef HOME ++#define HOME "HOME" ++#endif /* HOME */ ++ ++/* ++** On MS-DOS systems, define PDICTHOME to be the name of a directory ++** to be used to contain the personal dictionary (.ispell_english, ++** etc.). On other systems, you can leave it undefined. ++*/ ++#ifndef PDICTHOME ++#undef PDICTHOME ++#endif /* PDICTHOME */ ++ ++/* ++** On MS-DOS systems, you can rename the following variables so that ++** ispell's files have 3-character suffixes. Note that, if you do ++** this, you will have to redefine any variable above that incorporates ++** one of the suffixes. (Most MS-DOS environments will silently truncate ++** excess characters beyond the 8+3 limit, so you usually don't need to ++** change the suffixes just because they are longer than 3 characters.) ++*/ ++#ifndef HASHSUFFIX ++#define HASHSUFFIX ".hash" ++#endif /* HASHSUFFIX */ ++#ifndef STATSUFFIX ++#define STATSUFFIX ".sta" ++#endif /* STATSUFFIX */ ++#ifndef COUNTSUFFIX ++#define COUNTSUFFIX ".cnt" ++#endif /* COUNTSUFFIX */ ++#define SIGNAL_TYPE_STRING "void" ++#define MASKTYPE_STRING "long" +diff -Nur vim60am.old/src/spell/good.c vim60am/src/spell/good.c +--- vim60am.old/src/spell/good.c Thu Jan 1 01:00:00 1970 ++++ vim60am/src/spell/good.c Wed Jun 27 19:16:51 2001 +@@ -0,0 +1,400 @@ ++#ifndef lint ++static char Rcs_Id[] = ++ "$Id$"; ++#endif ++ ++/* ++ * good.c - see if a word or its root word ++ * is in the dictionary. ++ * ++ * Pace Willisson, 1983 ++ * ++ * Copyright 1992, 1993, Geoff Kuenning, Granada Hills, CA ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All modifications to the source code must be clearly marked as ++ * such. Binary redistributions based on modified source code ++ * must be clearly marked as modified versions in the documentation ++ * and/or other materials provided with the distribution. ++ * 4. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgment: ++ * This product includes software developed by Geoff Kuenning and ++ * other unpaid contributors. ++ * 5. The name of Geoff Kuenning may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY GEOFF KUENNING AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL GEOFF KUENNING OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++/* ++ * $Log$ ++ * Revision 1.43 1994/11/02 06:56:05 geoff ++ * Remove the anyword feature, which I've decided is a bad idea. ++ * ++ * Revision 1.42 1994/10/25 05:45:59 geoff ++ * Add support for an affix that will work with any word, even if there's ++ * no explicit flag. ++ * ++ * Revision 1.41 1994/05/24 06:23:06 geoff ++ * Let tgood decide capitalization questions, rather than doing it ourselves. ++ * ++ * Revision 1.40 1994/05/17 06:44:10 geoff ++ * Add support for controlled compound formation and the COMPOUNDONLY ++ * option to affix flags. ++ * ++ * Revision 1.39 1994/01/25 07:11:31 geoff ++ * Get rid of all old RCS log lines in preparation for the 3.1 release. ++ * ++ */ ++ ++#include ++#include "ispell.h" ++ ++#ifndef NO_CAPITALIZATION_SUPPORT ++Public Logical cap_ok (ichar_t * word, struct success * hit, int len); ++Local Logical entryhasaffixes (struct dent * dent, struct success * hit); ++#endif /* NO_CAPITALIZATION_SUPPORT */ ++Public void flagpr (ichar_t * word, int preflag, int prestrip, ++ int preadd, int sufflag, int sufadd); ++Local ichar_t * orig_word; ++ ++Public int ++#ifndef NO_CAPITALIZATION_SUPPORT ++good (ichar_t *w, int ignoreflagbits, int allhits, int pfxopts, int sfxopts) ++#else ++/* ARGSUSED */ ++good (ichar_t *w, int ignoreflagbits, int dummy, int pfxopts, int sfxopts) ++#define allhits 0 /* Never actually need more than one hit */ ++#endif ++ ++{ ++ ichar_t nword[INPUTWORDLEN + MAXAFFIXLEN]; ++ register ichar_t *p; ++ register ichar_t *q; ++ register n; ++ register struct dent *dp; ++ ++ /* ++ ** Make an uppercase copy of the word we are checking. ++ */ ++ for (p = w, q = nword; *p; ) ++ *q++ = mytoupper (*p++); ++ *q = 0; ++ n = q - nword; ++ ++ numhits = 0; ++ ++ if (cflag) ++ { ++ (void) printf ("%s", ichartosstr (w, 0)); ++ orig_word = w; ++ } ++ else if ((dp = lookup (nword, 1)) != NULL) ++ { ++ hits[0].dictent = dp; ++ hits[0].prefix = NULL; ++ hits[0].suffix = NULL; ++#ifndef NO_CAPITALIZATION_SUPPORT ++ if (allhits || cap_ok (w, &hits[0], n)) ++ numhits = 1; ++#else ++ numhits = 1; ++#endif ++ /* ++ * If we're looking for compounds, and this root doesn't ++ * participate in compound formation, undo the hit. ++ */ ++ if (compoundflag == COMPOUND_CONTROLLED ++ && ((pfxopts | sfxopts) & FF_COMPOUNDONLY) != 0 ++ && hashheader.compoundbit >= 0 ++ && TSTMASKBIT (dp->mask, hashheader.compoundbit) == 0) ++ numhits = 0; ++ } ++ if (numhits && !allhits) ++ return 1; ++ ++ /* try stripping off affixes */ ++ ++#if 0 ++ numchars = icharlen (nword); ++ if (numchars < 4) ++ { ++ if (cflag) ++ (void) putchar ('\n'); ++ return numhits || (numchars == 1); ++ } ++#endif ++ ++ chk_aff (w, nword, n, ignoreflagbits, allhits, pfxopts, sfxopts); ++ ++ if (cflag) ++ (void) putchar ('\n'); ++ ++ return numhits; ++} ++ ++#ifndef NO_CAPITALIZATION_SUPPORT ++Public Logical ++cap_ok (register ichar_t *word, register struct success *hit, int len) ++{ ++ register ichar_t * dword; ++ register ichar_t * w; ++ register struct dent * dent; ++ ichar_t dentword[INPUTWORDLEN + MAXAFFIXLEN]; ++ int preadd; ++ int prestrip; ++ int sufadd; ++ ichar_t * limit; ++ long thiscap; ++ long dentcap; ++ ++ thiscap = whatcap (word); ++ /* ++ ** All caps is always legal, regardless of affixes. ++ */ ++ preadd = prestrip = sufadd = 0; ++ if (thiscap == ALLCAPS) ++ return 1; ++ else if (thiscap == FOLLOWCASE) ++ { ++ /* Set up some constants for the while(1) loop below */ ++ if (hit->prefix) ++ { ++ preadd = hit->prefix->affl; ++ prestrip = hit->prefix->stripl; ++ } ++ else ++ preadd = prestrip = 0; ++ sufadd = hit->suffix ? hit->suffix->affl : 0; ++ } ++ /* ++ ** Search the variants for one that matches what we have. Note ++ ** that thiscap can't be ALLCAPS, since we already returned ++ ** for that case. ++ */ ++ dent = hit->dictent; ++ while(True) ++ { ++ dentcap = captype (dent->flagfield); ++ if (dentcap != thiscap) ++ { ++ if (dentcap == ANYCASE && thiscap == CAPITALIZED ++ && entryhasaffixes (dent, hit)) ++ return True; ++ } ++ else /* captypes match */ ++ { ++ if (thiscap != FOLLOWCASE) ++ { ++ if (entryhasaffixes (dent, hit)) ++ return True; ++ } ++ else ++ { ++ /* ++ ** Make sure followcase matches exactly. ++ ** Life is made more difficult by the ++ ** possibility of affixes. Start with ++ ** the prefix. ++ */ ++ (void) strtoichar (dentword, dent->word, INPUTWORDLEN, 1); ++ dword = dentword; ++ limit = word + preadd; ++ if (myupper (dword[prestrip])) ++ { ++ for (w = word; w < limit; w++) ++ { ++ if (mylower (*w)) ++ goto doublecontinue; ++ } ++ } ++ else ++ { ++ for (w = word; w < limit; w++) ++ { ++ if (myupper (*w)) ++ goto doublecontinue; ++ } ++ } ++ dword += prestrip; ++ /* Do root part of word */ ++ limit = dword + len - preadd - sufadd; ++ while (dword < limit) ++ { ++ if (*dword++ != *w++) ++ goto doublecontinue; ++ } ++ /* Do suffix */ ++ dword = limit - 1; ++ if (myupper (*dword)) ++ { ++ for ( ; *w; w++) ++ { ++ if (mylower (*w)) ++ goto doublecontinue; ++ } ++ } ++ else ++ { ++ for ( ; *w; w++) ++ { ++ if (myupper (*w)) ++ goto doublecontinue; ++ } ++ } ++ /* ++ ** All failure paths go to "doublecontinue," ++ ** so if we get here it must match. ++ */ ++ if (entryhasaffixes (dent, hit)) ++ return True; ++doublecontinue: ; ++ } ++ } ++ if ((dent->flagfield & MOREVARIANTS) == 0) ++ break; ++ dent = dent->next; ++ } ++ ++ /* No matches found */ ++ return False; ++} ++ ++/* ++** See if this particular capitalization (dent) is legal with these ++** particular affixes. ++*/ ++Local Logical ++entryhasaffixes (register struct dent *dent, register struct success *hit) ++{ ++ ++ if (hit->prefix && !TSTMASKBIT (dent->mask, hit->prefix->flagbit)) ++ return False; ++ if (hit->suffix && !TSTMASKBIT (dent->mask, hit->suffix->flagbit)) ++ return False; ++ return True; /* Yes, these affixes are legal */ ++} ++#endif ++ ++/* ++ * Print a word and its flag, making sure the case of the output matches ++ * the case of the original found in "orig_word". ++ */ ++Public void ++flagpr (register ichar_t *word, /* (Modified) word to print */ ++ int preflag, /* Prefix flag (if any) */ ++ int prestrip, /* Lth of pfx stripped off orig_word */ ++ int preadd, /* Length of prefix added to w */ ++ int sufflag, /* Suffix flag (if any) */ ++ int sufadd) /* Length of suffix added to w */ ++{ ++ register ichar_t * origp; /* Pointer into orig_word */ ++ int orig_len; /* Length of orig_word */ ++ ++ orig_len = icharlen (orig_word); ++ /* ++ * We refuse to print if the cases outside the modification ++ * points don't match those just inside. This prevents things ++ * like "OEM's" from being turned into "OEM/S" which expands ++ * only to "OEM'S". ++ */ ++ if (preflag > 0) ++ { ++ origp = orig_word + preadd; ++ if (myupper (*origp)) ++ { ++ for (origp = orig_word; origp < orig_word + preadd; origp++) ++ { ++ if (mylower (*origp)) ++ return; ++ } ++ } ++ else ++ { ++ for (origp = orig_word; origp < orig_word + preadd; origp++) ++ { ++ if (myupper (*origp)) ++ return; ++ } ++ } ++ } ++ if (sufflag > 0) ++ { ++ origp = orig_word + orig_len - sufadd; ++ if (myupper (origp[-1])) ++ { ++ for ( ; *origp != 0; origp++) ++ { ++ if (mylower (*origp)) ++ return; ++ } ++ } ++ else ++ { ++ origp = orig_word + orig_len - sufadd; ++ for ( ; *origp != 0; origp++) ++ { ++ if (myupper (*origp)) ++ return; ++ } ++ } ++ } ++ /* ++ * The cases are ok. Put out the word, being careful that the ++ * prefix/suffix cases match those in the original, and that the ++ * unchanged characters from the original actually match it. ++ */ ++ (void) putchar (' '); ++ origp = orig_word + preadd; ++ if (myupper (*origp)) ++ { ++ while (--prestrip >= 0) ++ (void) fputs (printichar ((int) *word++), stdout); ++ } ++ else ++ { ++ while (--prestrip >= 0) ++ (void) fputs (printichar ((int) mytolower (*word++)), stdout); ++ } ++ for (prestrip = orig_len - preadd - sufadd; --prestrip >= 0; word++) ++ (void) fputs (printichar ((int) *origp++), stdout); ++ if (origp > orig_word) ++ origp--; ++ if (myupper (*origp)) ++ (void) fputs (ichartosstr (word, 0), stdout); ++ else ++ { ++ while (*word) ++ { ++ (void) fputs (printichar ((int) mytolower (*word++)), stdout); ++ } ++ } ++ /* ++ * Now put out the flags ++ */ ++ (void) putchar (hashheader.flagmarker); ++ if (preflag > 0) ++ (void) putchar (preflag); ++ if (sufflag > 0) ++ (void) putchar (sufflag); ++} +diff -Nur vim60am.old/src/spell/hash.c vim60am/src/spell/hash.c +--- vim60am.old/src/spell/hash.c Thu Jan 1 01:00:00 1970 ++++ vim60am/src/spell/hash.c Wed Jun 27 19:16:51 2001 +@@ -0,0 +1,91 @@ ++/* ++ * hash.c - a simple hash function for ispell ++ * ++ * Pace Willisson, 1983 ++ * ++ * Copyright 1992, 1993, Geoff Kuenning, Granada Hills, CA ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All modifications to the source code must be clearly marked as ++ * such. Binary redistributions based on modified source code ++ * must be clearly marked as modified versions in the documentation ++ * and/or other materials provided with the distribution. ++ * 4. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgment: ++ * This product includes software developed by Geoff Kuenning and ++ * other unpaid contributors. ++ * 5. The name of Geoff Kuenning may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY GEOFF KUENNING AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL GEOFF KUENNING OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++/* ++ * $Log$ ++ * Revision 1.20 1994/01/25 07:11:34 geoff ++ * Get rid of all old RCS log lines in preparation for the 3.1 release. ++ * ++ */ ++ ++#include "ispell.h" ++ ++/* ++ * The following hash algorithm is due to Ian Dall, with slight modifications ++ * by Geoff Kuenning to reflect the results of testing with the English ++ * dictionaries actually distributed with ispell. ++ */ ++#define HASHSHIFT 5 ++ ++#ifdef NO_CAPITALIZATION_SUPPORT ++#define HASHUPPER(c) c ++#else /* NO_CAPITALIZATION_SUPPORT */ ++#define HASHUPPER(c) mytoupper(c) ++#endif /* NO_CAPITALIZATION_SUPPORT */ ++ ++Public int ++hash ( ++ register ichar_t * s, ++ register int hashtblsize) ++{ ++ register long h = 0; ++ register int i; ++ ++#ifdef ICHAR_IS_CHAR ++ for (i = 4; i-- && *s != 0; ) ++ h = (h << 8) | HASHUPPER (*s++); ++#else /* ICHAR_IS_CHAR */ ++ for (i = 2; i-- && *s != 0; ) ++ h = (h << 16) | HASHUPPER (*s++); ++#endif /* ICHAR_IS_CHAR */ ++ while (*s != 0) ++ { ++ /* ++ * We have to do circular shifts the hard way, since C doesn't ++ * have them even though the hardware probably does. Oh, well. ++ */ ++ h = (h << HASHSHIFT) | ++ ((h >> (32 - HASHSHIFT)) & ((1 << HASHSHIFT) - 1)); ++ h ^= HASHUPPER (*s++); ++ } ++ return (unsigned long) h % hashtblsize; ++} +diff -Nur vim60am.old/src/spell/i_proto.h vim60am/src/spell/i_proto.h +--- vim60am.old/src/spell/i_proto.h Thu Jan 1 01:00:00 1970 ++++ vim60am/src/spell/i_proto.h Wed Jun 27 19:16:51 2001 +@@ -0,0 +1,112 @@ ++Global int addvheader (struct dent * ent); ++Global void askmode (void); ++Global void backup (void); ++#ifndef NO_CAPITALIZATION_SUPPORT ++Global Logical cap_ok (ichar_t * word, struct success * hit, int len); ++#endif /* NO_CAPITALIZATION_SUPPORT */ ++Global void chupcase (char * s); ++Global void checkfile (void); ++Global void checkline (FILE * ofile); ++Global void chk_aff (ichar_t * word, ichar_t * ucword, int len, ++ int ignoreflagbits, int allhits, int pfxopts, int sfxopts); ++Global int combinecaps (struct dent * hdr, struct dent * newent); ++Global int compoundgood (ichar_t * word, int pfxopts); ++Global void copyout (char ** cc, int cnt); ++Global void correct (char * ctok, int ctokl, ichar_t * itok, int itokl, ++ char ** curchar); ++Global char * do_regex_lookup (char * expr, int whence); ++Global SIGNAL_TYPE done (int); ++Global void dumpmode (void); ++Global void erase (void); ++Global int expand_pre (char * croot, ichar_t * rootword, ++ MASKTYPE mask[], int option, char *extra); ++Global int expand_suf (char * croot, ichar_t * rootword, ++ MASKTYPE mask[], int crossonly, int option, char * extra); ++Global int findfiletype (char * name, int searchnames, ++ int * deformatter); ++Global void flagpr (ichar_t * word, int preflag, int prestrip, ++ int preadd, int sufflag, int sufadd); ++Global void givehelp (int interactive); ++Global int good (ichar_t * word, int ignoreflagbits, int allhits, ++ int pfxopts, int sfxopts); ++Global int hash (ichar_t * word, int hashtablesize); ++#ifndef ICHAR_IS_CHAR ++Global int icharcmp (ichar_t * s1, ichar_t * s2); ++Global ichar_t * icharcpy (ichar_t * out, ichar_t * in); ++Global int icharlen (ichar_t * str); ++Global int icharncmp (ichar_t * s1, ichar_t * s2, int n); ++#endif /* ICHAR_IS_CHAR */ ++Global int ichartostr (char * out, ichar_t * in, int outlen, ++ int canonical); ++Global char * ichartosstr (ichar_t * in, int canonical); ++Global void inverse (void); ++Global struct dent * lookup (ichar_t * word, int dotree); ++Global void lowcase (ichar_t * string); ++Global int makedent (char * lbuf, int lbuflen, struct dent * d); ++Global void makepossibilities (ichar_t * word); ++Global void move (int row, int col); ++Global void normal (void); ++Global char * printichar (int in); ++#ifdef USESH ++Global int shellescape (char * buf); ++Global void shescape (char * buf); ++#else /* USESH */ ++#ifndef REGEX_LOOKUP ++Global int shellescape (char * buf); ++#endif /* REGEX_LOOKUP */ ++#endif /* USESH */ ++Global char * skipoverword (char * bufp); ++Global void stop (void); ++Global int stringcharlen (char * bufp, int canonical); ++Global int strtoichar (ichar_t * out, char * in, int outlen, ++ int canonical); ++Global ichar_t * strtosichar (char * in, int canonical); ++Global void terminit (void); ++Global void toutent (FILE * outfile, struct dent * hent, int onlykeep); ++Global void treeinit (char * persdict, char * LibDict); ++Global void treeinsert (char * word, int wordlen, int keep); ++Global struct dent * treelookup (ichar_t * word); ++Global void treeoutput (void); ++Global void upcase (ichar_t * string); ++#ifndef NO_CAPITALIZATION_SUPPORT ++Global long whatcap (ichar_t * word); ++#endif ++Global char * xgets (char * string, int size, FILE * stream); ++Global void yyinit (void); ++Global Logical yyopen (char * file); ++Global int yyparse (void); ++ ++#include ++ ++#ifdef REGEX_LOOKUP ++# ifdef USG ++Global char * regcmp (const char * expr, const char * terminator, ...); ++Global char * regex (const char * pat, const char * subject, ...); ++# else ++Global char * re_comp (const char * expr); ++Global int * re_exec (const char * pat); ++# endif ++#endif ++/* WM ++Global int tgetent (char * buf, const char * termname); ++Global int tgetnum (const char * id); ++Global char * tgetstr (const char * id, char ** area); ++Global char * tgoto (const char * cm, int col, int row); ++Global char * tputs (const char * str, int pad, int (*func) (int ch); ++*/ ++ ++Global char * mypath_rindex(char const *str, char c); ++Global void save_root_cap (ichar_t * word, ichar_t * pattern, ++ int prestrip, int preadd, int sufstrip, int sufadd, ++ struct dent * firstdent, struct flagent * pfxent, ++ struct flagent * sufent, ++ ichar_t savearea[MAX_CAPS][INPUTWORDLEN + MAXAFFIXLEN], ++ int * nsaved); ++Global int casecmp (char * a, char * b, int canonical); ++Global int ins_root_cap (ichar_t * word, ichar_t * pattern, ++ int prestrip, int preadd, int sufstrip, int sufadd, ++ struct dent * firstdent, struct flagent * pfxent, ++ struct flagent * sufent); ++Global int insert(register ichar_t * word); ++Global char * linit (char *); ++Global char * last_slash (char *file); +diff -Nur vim60am.old/src/spell/ispell.h vim60am/src/spell/ispell.h +--- vim60am.old/src/spell/ispell.h Thu Jan 1 01:00:00 1970 ++++ vim60am/src/spell/ispell.h Wed Jun 27 19:16:51 2001 +@@ -0,0 +1,619 @@ ++/* ++ * $Id$ ++ */ ++ ++/* ++ * Copyright 1992, 1993, Geoff Kuenning, Granada Hills, CA ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All modifications to the source code must be clearly marked as ++ * such. Binary redistributions based on modified source code ++ * must be clearly marked as modified versions in the documentation ++ * and/or other materials provided with the distribution. ++ * 4. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgment: ++ * This product includes software developed by Geoff Kuenning and ++ * other unpaid contributors. ++ * 5. The name of Geoff Kuenning may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY GEOFF KUENNING AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL GEOFF KUENNING OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++/* ++ * $Log$ ++ * Revision 1.68 1995/03/06 02:42:41 geoff ++ * Be vastly more paranoid about parenthesizing macro arguments. This ++ * fixes a bug in defmt.c where a complex argument was passed to ++ * isstringch. ++ * ++ * Revision 1.67 1995/01/03 19:24:12 geoff ++ * Get rid of a non-global declaration. ++ * ++ * Revision 1.66 1994/12/27 23:08:49 geoff ++ * Fix a lot of subtly bad assumptions about the widths of ints and longs ++ * which only show up on 64-bit machines like the Cray and the DEC Alpha. ++ * ++ * Revision 1.65 1994/11/02 06:56:10 geoff ++ * Remove the anyword feature, which I've decided is a bad idea. ++ * ++ * Revision 1.64 1994/10/25 05:46:18 geoff ++ * Add the FF_ANYWORD flag for defining an affix that will apply to any ++ * word, even if not explicitly specified. (Good for French.) ++ * ++ * Revision 1.63 1994/09/16 04:48:28 geoff ++ * Make stringdups and laststringch unsigned ints, and dupnos a plain ++ * int, so that we can handle more than 128 stringchars and stringchar ++ * types. ++ * ++ * Revision 1.62 1994/09/01 06:06:39 geoff ++ * Change erasechar/killchar to uerasechar/ukillchar to avoid ++ * shared-library problems on HP systems. ++ * ++ * Revision 1.61 1994/08/31 05:58:35 geoff ++ * Add contextoffset, used in -a mode to handle extremely long lines. ++ * ++ * Revision 1.60 1994/05/17 06:44:15 geoff ++ * Add support for controlled compound formation and the COMPOUNDONLY ++ * option to affix flags. ++ * ++ * Revision 1.59 1994/03/15 06:25:16 geoff ++ * Change deftflag's initialization so we can tell if -t/-n appeared. ++ * ++ * Revision 1.58 1994/02/07 05:53:28 geoff ++ * Add typecasts to the the 7-bit versions of ichar* routines ++ * ++ * Revision 1.57 1994/01/25 07:11:48 geoff ++ * Get rid of all old RCS log lines in preparation for the 3.1 release. ++ * ++ */ ++ ++#include ++#include "config.h" ++ ++#ifdef NO8BIT ++#define SET_SIZE 128 ++#else ++#define SET_SIZE 256 ++#endif ++ ++#define MASKSIZE (MASKBITS / MASKTYPE_WIDTH) ++ ++/* The following is really testing for MASKSIZE <= 1, but cpp can't do that */ ++#if MASKBITS <= MASKTYPE_WIDTH ++#define SETMASKBIT(mask, bit) ((mask)[0] |= (MASKTYPE) 1 << (bit)) ++#define CLRMASKBIT(mask, bit) ((mask)[0] &= (MASKTYPE) ~(1 << (bit))) ++#define TSTMASKBIT(mask, bit) ((mask)[0] & ((MASKTYPE) 1 << (bit))) ++#else ++#define SETMASKBIT(mask, bit) \ ++ ((mask)[(bit) / MASKTYPE_WIDTH] |= \ ++ (MASKTYPE) 1 << ((bit) & (MASKTYPE_WIDTH - 1))) ++#define CLRMASKBIT(mask, bit) \ ++ ((mask)[(bit) / MASKTYPE_WIDTH] &= \ ++ ~((MASKTYPE) 1 << ((bit) & (MASKTYPE_WIDTH - 1)))) ++#define TSTMASKBIT(mask, bit) \ ++ ((mask)[(bit) / MASKTYPE_WIDTH] & \ ++ ((MASKTYPE) 1 << ((bit) & (MASKTYPE_WIDTH - 1)))) ++#endif ++ ++#if MASKBITS > 64 ++#define FULLMASKSET ++#endif ++ ++#if MASKBITS <= 32 ++# ifndef lint ++#define BITTOCHAR(bit) ((bit) + 'A') ++#define CHARTOBIT(ch) ((ch) - 'A') ++# endif /* lint */ ++#define LARGESTFLAG 26 /* 5 are needed for flagfield below */ ++#define FLAGBASE ((MASKTYPE_WIDTH) - 6) ++#else ++# if MASKBITS <= 64 ++# ifndef lint ++#define BITTOCHAR(bit) ((bit) + 'A') ++#define CHARTOBIT(ch) ((ch) - 'A') ++# endif /* lint */ ++#define LARGESTFLAG (64 - 6) /* 5 are needed for flagfield below */ ++#define FLAGBASE ((MASKTYPE_WIDTH) - 6) ++# else ++# ifndef lint ++#define BITTOCHAR(bit) (bit) ++#define CHARTOBIT(ch) (ch) ++# endif /* lint */ ++#define LARGESTFLAG MASKBITS /* flagfield is a separate field */ ++#define FLAGBASE 0 ++# endif ++#endif ++ ++/* ++** Data type for internal word storage. If necessary, we use shorts rather ++** than chars so that string characters can be encoded as a single unit. ++*/ ++#if (SET_SIZE + MAXSTRINGCHARS) <= 256 ++#ifndef lint ++#define ICHAR_IS_CHAR ++#endif /* lint */ ++#endif ++ ++#ifdef ICHAR_IS_CHAR ++typedef unsigned char ichar_t; /* Internal character */ ++#define icharlen(s) strlen ((char *) (s)) ++#define icharcpy(a, b) strcpy ((char *) (a), (char *) (b)) ++#define icharcmp(a, b) strcmp ((char *) (a), (char *) (b)) ++#define icharncmp(a, b, n) strncmp ((char *) (a), (char *) (b), (n)) ++#define chartoichar(x) ((ichar_t) (x)) ++#else ++typedef unsigned short ichar_t; /* Internal character */ ++#define chartoichar(x) ((ichar_t) (unsigned char) (x)) ++#endif ++ ++struct dent ++ { ++ struct dent * next; ++ char * word; ++ MASKTYPE mask[MASKSIZE]; ++#ifdef FULLMASKSET ++ char flags; ++#endif ++ }; ++ ++/* ++** Flags in the directory entry. If FULLMASKSET is undefined, these are ++** stored in the highest bits of the last longword of the mask field. If ++** FULLMASKSET is defined, they are stored in the extra "flags" field. ++#ifndef NO_CAPITALIZATION_SUPPORT ++** ++** If a word has only one capitalization form, and that form is not ++** FOLLOWCASE, it will have exactly one entry in the dictionary. The ++** legal capitalizations will be indicated by the 2-bit capitalization ++** field, as follows: ++** ++** ALLCAPS The word must appear in all capitals. ++** CAPITALIZED The word must be capitalized (e.g., London). ++** It will also be accepted in all capitals. ++** ANYCASE The word may appear in lowercase, capitalized, ++** or all-capitals. ++** ++** Regardless of the capitalization flags, the "word" field of the entry ++** will point to an all-uppercase copy of the word. This is to simplify ++** the large portion of the code that doesn't care about capitalization. ++** Ispell will generate the correct version when needed. ++** ++** If a word has more than one capitalization, there will be multiple ++** entries for it, linked together by the "next" field. The initial ++** entry for such words will be a dummy entry, primarily for use by code ++** that ignores capitalization. The "word" field of this entry will ++** again point to an all-uppercase copy of the word. The "mask" field ++** will contain the logical OR of the mask fields of all variants. ++** A header entry is indicated by a capitalization type of ALLCAPS, ++** with the MOREVARIANTS bit set. ++** ++** The following entries will define the individual variants. Each ++** entry except the last has the MOREVARIANTS flag set, and each ++** contains one of the following capitalization options: ++** ++** ALLCAPS The word must appear in all capitals. ++** CAPITALIZED The word must be capitalized (e.g., London). ++** It will also be accepted in all capitals. ++** FOLLOWCASE The word must be capitalized exactly like the ++** sample in the entry. Prefix (suffix) characters ++** must be rendered in the case of the first (last) ++** "alphabetic" character. It will also be accepted ++** in all capitals. ("Alphabetic" means "mentioned ++** in a 'casechars' statement".) ++** ANYCASE The word may appear in lowercase, capitalized, ++** or all-capitals. ++** ++** The "mask" field for the entry contains only the affix flag bits that ++** are legal for that capitalization. The "word" field will be null ++** except for FOLLOWCASE entries, where it will point to the ++** correctly-capitalized spelling of the root word. ++** ++** It is worth discussing why the ALLCAPS option is used in ++** the header entry. The header entry accepts an all-capitals ++** version of the root plus every affix (this is always legal, since ++** words get capitalized in headers and so forth). Further, all of ++** the following variant entries will reject any all-capitals form ++** that is illegal due to an affix. ++** ++** Finally, note that variations in the KEEP flag can cause a multiple-variant ++** entry as well. For example, if the personal dictionary contains "ALPHA", ++** (KEEP flag set) and the user adds "alpha" with the KEEP flag clear, a ++** multiple-variant entry will be created so that "alpha" will be accepted ++** but only "ALPHA" will actually be kept. ++#endif ++*/ ++#ifdef FULLMASKSET ++#define flagfield flags ++#else ++#define flagfield mask[MASKSIZE - 1] ++#endif ++#define USED ((MASKTYPE) 1 << (FLAGBASE + 0)) ++#define KEEP ((MASKTYPE) 1 << (FLAGBASE + 1)) ++#ifdef NO_CAPITALIZATION_SUPPORT ++#define ALLFLAGS (USED | KEEP) ++#else /* NO_CAPITALIZATION_SUPPORT */ ++#define ANYCASE ((MASKTYPE) 0 << (FLAGBASE + 2)) ++#define ALLCAPS ((MASKTYPE) 1 << (FLAGBASE + 2)) ++#define CAPITALIZED ((MASKTYPE) 2 << (FLAGBASE + 2)) ++#define FOLLOWCASE ((MASKTYPE) 3 << (FLAGBASE + 2)) ++#define CAPTYPEMASK ((MASKTYPE) 3 << (FLAGBASE + 2)) ++#define MOREVARIANTS ((MASKTYPE) 1 << (FLAGBASE + 4)) ++#define ALLFLAGS (USED | KEEP | CAPTYPEMASK | MOREVARIANTS) ++#define captype(x) ((x) & CAPTYPEMASK) ++#endif /* NO_CAPITALIZATION_SUPPORT */ ++ ++/* ++ * Language tables used to encode prefix and suffix information. ++ */ ++struct flagent ++ { ++ ichar_t * strip; /* String to strip off */ ++ ichar_t * affix; /* Affix to append */ ++ short flagbit; /* Flag bit this ent matches */ ++ short stripl; /* Length of strip */ ++ short affl; /* Length of affix */ ++ short numconds; /* Number of char conditions */ ++ short flagflags; /* Modifiers on this flag */ ++ char conds[SET_SIZE + MAXSTRINGCHARS]; /* Adj. char conds */ ++ }; ++ ++/* ++ * Bits in flagflags ++ */ ++#define FF_CROSSPRODUCT (1 << 0) /* Affix does cross-products */ ++#define FF_COMPOUNDONLY (1 << 1) /* Afx works in compounds */ ++ ++union ptr_union /* Aid for building flg ptrs */ ++ { ++ struct flagptr * fp; /* Pointer to more indexing */ ++ struct flagent * ent; /* First of a list of ents */ ++ }; ++ ++struct flagptr ++ { ++ union ptr_union pu; /* Ent list or more indexes */ ++ int numents; /* If zero, pu.fp is valid */ ++ }; ++ ++/* ++ * Description of a single string character type. ++ */ ++struct strchartype ++ { ++ char * name; /* Name of the type */ ++ char * deformatter; /* Deformatter to use */ ++ char * suffixes; /* File suffixes, null seps */ ++ }; ++ ++/* ++ * Header placed at the beginning of the hash file. ++ */ ++struct hashheader ++ { ++ unsigned short magic; /* Magic number for ID */ ++ unsigned short compileoptions; /* How we were compiled */ ++ short maxstringchars; /* Max # strchrs we support */ ++ short maxstringcharlen; /* Max strchr len supported */ ++ short compoundmin; /* Min lth of compound parts */ ++ short compoundbit; /* Flag 4 compounding roots */ ++ unsigned int stringsize; /* Size of string table */ ++ int lstringsize; /* Size of lang. str tbl */ ++ unsigned int tblsize; /* No. entries in hash tbl */ ++ int stblsize; /* No. entries in sfx tbl */ ++ int ptblsize; /* No. entries in pfx tbl */ ++ int sortval; /* Largest sort ID assigned */ ++ int nstrchars; /* No. strchars defined */ ++ int nstrchartype; /* No. strchar types */ ++ int strtypestart; /* Start of strtype table */ ++ char nrchars[5]; /* Nroff special characters */ ++ char texchars[13]; /* TeX special characters */ ++#define TeXleftparen texchars[0] ++#define TeXrightparen texchars[1] ++#define TeXleftsquare texchars[2] ++#define TeXrightsquare texchars[3] ++#define TeXleftcurly texchars[4] ++#define TeXrightcurly texchars[5] ++#define TeXlefttangle texchars[6] ++#define TeXrighttangle texchars[7] ++#define TeXbackslash texchars[8] ++#define TeXdollar texchars[9] ++#define TeXstar texchars[10] ++#define TeXdot texchars[11] ++#define TeXpercent texchars[12] ++ char compoundflag; /* Compund-word handling */ ++ char defhardflag; /* Default tryveryhard flag */ ++ char flagmarker; /* "Start-of-flags" char */ ++ unsigned short sortorder[SET_SIZE + MAXSTRINGCHARS]; /* Sort ordering */ ++ ichar_t lowerconv[SET_SIZE + MAXSTRINGCHARS]; /* Lower-conversion table */ ++ ichar_t upperconv[SET_SIZE + MAXSTRINGCHARS]; /* Upper-conversion table */ ++ char wordchars[SET_SIZE + MAXSTRINGCHARS]; /* NZ for chars found in wrds */ ++ char upperchars[SET_SIZE + MAXSTRINGCHARS]; /* NZ for uppercase chars */ ++ char lowerchars[SET_SIZE + MAXSTRINGCHARS]; /* NZ for lowercase chars */ ++ char boundarychars[SET_SIZE + MAXSTRINGCHARS]; /* NZ for boundary chars */ ++ char stringstarts[SET_SIZE]; /* NZ if char can start str */ ++ char stringchars[MAXSTRINGCHARS][MAXSTRINGCHARLEN + 1]; /* String chars */ ++ unsigned int stringdups[MAXSTRINGCHARS]; /* No. of "base" char */ ++ int dupnos[MAXSTRINGCHARS]; /* Dup char ID # */ ++ unsigned short magic2; /* Second magic for dbl chk */ ++ }; ++ ++/* hash table magic number */ ++#define SPELL_MAGIC 0x9602 ++ ++/* compile options, put in the hash header for consistency checking */ ++#ifdef NO8BIT ++# define MAGIC8BIT 0x01 ++#else ++# define MAGIC8BIT 0x00 ++#endif ++#ifdef NO_CAPITALIZATION_SUPPORT ++# define MAGICCAPITALIZATION 0x00 ++#else ++# define MAGICCAPITALIZATION 0x02 ++#endif ++#if MASKBITS <= 32 ++# define MAGICMASKSET 0x00 ++#else ++# if MASKBITS <= 64 ++# define MAGICMASKSET 0x04 ++# else ++# if MASKBITS <= 128 ++# define MAGICMASKSET 0x08 ++# else ++# define MAGICMASKSET 0x0C ++# endif ++# endif ++#endif ++ ++#define COMPILEOPTIONS (MAGIC8BIT | MAGICCAPITALIZATION | MAGICMASKSET) ++ ++/* ++ * Structure used to record data about successful lookups; these values ++ * are used in the ins_root_cap routine to produce correct capitalizations. ++ */ ++struct success ++ { ++ struct dent * dictent; /* Header of dict entry chain for wd */ ++ struct flagent * prefix; /* Prefix flag used, or NULL */ ++ struct flagent * suffix; /* Suffix flag used, or NULL */ ++ }; ++ ++/* ++** Offsets into the nroff special-character array ++*/ ++#define NRLEFTPAREN hashheader.nrchars[0] ++#define NRRIGHTPAREN hashheader.nrchars[1] ++#define NRDOT hashheader.nrchars[2] ++#define NRBACKSLASH hashheader.nrchars[3] ++#define NRSTAR hashheader.nrchars[4] ++ ++/* ++** Values for compoundflag ++*/ ++#define COMPOUND_NEVER 0 /* Compound words are never good */ ++#define COMPOUND_ANYTIME 1 /* Accept run-together words */ ++#define COMPOUND_CONTROLLED 2 /* Compounds controlled by afx flags */ ++ ++/* ++** The isXXXX macros normally only check ASCII range, and don't support ++** the character sets of other languages. These private versions handle ++** whatever character sets have been defined in the affix files. ++*/ ++#define myupper(X) (hashheader.upperchars[(X)]) ++#define mylower(X) (hashheader.lowerchars[(X)]) ++#define myspace(X) (((X) > 0) && ((X) < 0x80) \ ++ && isspace((unsigned char) (X))) ++#define iswordch(X) (hashheader.wordchars[(X)]) ++#define isboundarych(X) (hashheader.boundarychars[(X)]) ++#define isstringstart(X) (hashheader.stringstarts[(unsigned char) (X)]) ++#define mytolower(X) (hashheader.lowerconv[(X)]) ++#define mytoupper(X) (hashheader.upperconv[(X)]) ++ ++/* ++** These macros are similar to the ones above, but they take into account ++** the possibility of string characters. Note well that they take a POINTER, ++** not a character. ++** ++** The "l_" versions set "len" to the length of the string character as a ++** handy side effect. (Note that the global "laststringch" is also set, ++** and sometimes used, by these macros.) ++** ++** The "l1_" versions go one step further and guarantee that the "len" ++** field is valid for *all* characters, being set to 1 even if the macro ++** returns false. This macro is a great example of how NOT to write ++** readable C. ++*/ ++#define isstringch(ptr, canon) (isstringstart (*(ptr)) \ ++ && stringcharlen ((ptr), (canon)) > 0) ++#define l_isstringch(ptr, len, canon) \ ++ (isstringstart (*(ptr)) \ ++ && (len = stringcharlen ((ptr), (canon))) \ ++ > 0) ++#define l1_isstringch(ptr, len, canon) \ ++ (len = 1, \ ++ isstringstart (*(ptr)) \ ++ && ((len = \ ++ stringcharlen ((ptr), (canon))) \ ++ > 0 \ ++ ? 1 : (len = 1, 0))) ++ ++/* ++ * Sizes of buffers returned by ichartosstr/strtosichar. ++ */ ++#define ICHARTOSSTR_SIZE (INPUTWORDLEN + 4 * MAXAFFIXLEN + 4) ++#define STRTOSICHAR_SIZE ((INPUTWORDLEN + 4 * MAXAFFIXLEN + 4) \ ++ * sizeof (ichar_t)) ++ ++/* ++ * termcap variables ++ */ ++#ifdef MAIN ++# define S_EXTERN /* nothing */ ++#define Global ++#else ++#define Global extern ++# define S_EXTERN extern ++#endif ++ ++#include "wm.h" ++ ++ ++S_EXTERN char * BC; /* backspace if not ^H */ ++S_EXTERN char * cd; /* clear to end of display */ ++S_EXTERN char * cl; /* clear display */ ++S_EXTERN char * cm; /* cursor movement */ ++S_EXTERN char * ho; /* home */ ++S_EXTERN char * nd; /* non-destructive space */ ++S_EXTERN char * so; /* standout */ ++S_EXTERN char * se; /* standout end */ ++S_EXTERN int sg; /* space taken by so/se */ ++S_EXTERN char * ti; /* terminal initialization sequence */ ++S_EXTERN char * te; /* terminal termination sequence */ ++S_EXTERN int li; /* lines */ ++S_EXTERN int co; /* columns */ ++ ++S_EXTERN int contextsize; /* number of lines of context to show */ ++S_EXTERN char contextbufs[MAXCONTEXT][BUFSIZ]; /* Context of current line */ ++S_EXTERN int contextoffset; /* Offset of line start in contextbufs[0] */ ++S_EXTERN char * currentchar; /* Location in contextbufs */ ++S_EXTERN char ctoken[INPUTWORDLEN + MAXAFFIXLEN]; /* Current token as char */ ++S_EXTERN ichar_t itoken[INPUTWORDLEN + MAXAFFIXLEN]; /* Ctoken as ichar_t str */ ++ ++S_EXTERN char termcap[2048]; /* termcap entry */ ++S_EXTERN char termstr[2048]; /* for string values */ ++S_EXTERN char * termptr; /* pointer into termcap, used by tgetstr */ ++ ++S_EXTERN int numhits; /* number of hits in dictionary lookups */ ++S_EXTERN struct success ++ hits[MAX_HITS]; /* table of hits gotten in lookup */ ++ ++S_EXTERN char * hashstrings; /* Strings in hash table */ ++S_EXTERN struct hashheader ++ hashheader; /* Header of hash table */ ++S_EXTERN struct dent * ++ hashtbl; /* Main hash table, for dictionary */ ++S_EXTERN int hashsize; /* Size of main hash table */ ++ ++ ++S_EXTERN int aflag; /* NZ if -a or -A option specified */ ++S_EXTERN int cflag; /* NZ if -c (crunch) option */ ++S_EXTERN int lflag; /* NZ if -l (list) option */ ++S_EXTERN int incfileflag; /* whether xgets() acts exactly like gets() */ ++Global Logical nodictflag; /* NZ if dictionary not needed */ ++ ++S_EXTERN int uerasechar; /* User's erase character, from stty */ ++S_EXTERN int ukillchar; /* User's kill character */ ++ ++S_EXTERN unsigned int laststringch; /* Number of last string character */ ++S_EXTERN int defdupchar; /* Default duplicate string type */ ++ ++S_EXTERN unsigned int numpflags; /* Number of prefix flags in table */ ++S_EXTERN unsigned int numsflags; /* Number of suffix flags in table */ ++S_EXTERN struct flagptr *pflagindex; ++ /* Fast index to pflaglist */ ++S_EXTERN struct flagent *pflaglist; /* Prefix flag control list */ ++S_EXTERN struct flagptr *sflagindex; ++ /* Fast index to sflaglist */ ++S_EXTERN struct flagent *sflaglist; /* Suffix flag control list */ ++ ++S_EXTERN struct strchartype * /* String character type collection */ ++ chartypes; ++ ++S_EXTERN FILE * infile; /* File being corrected */ ++S_EXTERN FILE * outfile; /* Corrected copy of infile */ ++ ++S_EXTERN char * askfilename; /* File specified in -f option */ ++ ++S_EXTERN int changes; /* NZ if changes made to cur. file */ ++S_EXTERN int readonly; /* NZ if current file is readonly */ ++S_EXTERN int quit; /* NZ if we're done with this file */ ++ ++#define MAXPOSSIBLE 100 /* Max no. of possibilities to generate */ ++ ++S_EXTERN char possibilities[MAXPOSSIBLE][INPUTWORDLEN + MAXAFFIXLEN]; ++ /* Table of possible corrections */ ++S_EXTERN int pcount; /* Count of possibilities generated */ ++S_EXTERN int maxposslen; /* Length of longest possibility */ ++S_EXTERN int easypossibilities; /* Number of "easy" corrections found */ ++ /* ..(defined as those using legal affixes) */ ++ ++Global Logical inited; ++/* ++ * The following array contains a list of characters that should be tried ++ * in "missingletter." Note that lowercase characters are omitted. ++ */ ++S_EXTERN int Trynum; /* Size of "Try" array */ ++S_EXTERN ichar_t Try[SET_SIZE + MAXSTRINGCHARS]; ++ ++/* ++ * Initialized variables. These are generated using macros so that they ++ * may be consistently declared in all programs. Numerous examples of ++ * usage are given below. ++ */ ++#ifdef MAIN ++#define S_INIT(decl, init) decl = init ++#else ++#define S_INIT(decl, init) extern decl ++#endif ++ ++#ifdef MINIMENU ++S_INIT (int minimenusize, 2); /* MUST be either 2 or zero */ ++#else /* MINIMENU */ ++S_INIT (int minimenusize, 0); /* MUST be either 2 or zero */ ++#endif /* MINIMENU */ ++ ++S_INIT (int eflag, 0); /* NZ for expand mode */ ++S_INIT (int dumpflag, 0); /* NZ to do dump mode */ ++S_INIT (int fflag, 0); /* NZ if -f specified */ ++#ifndef USG ++S_INIT (int sflag, 0); /* NZ to stop self after EOF */ ++#endif ++S_INIT (int vflag, 0); /* NZ to display characters as M-xxx */ ++S_INIT (int xflag, DEFNOBACKUPFLAG); /* NZ to suppress backups */ ++S_INIT (int deftflag, -1); /* NZ for TeX mode by default */ ++S_INIT (int tflag, DEFTEXFLAG); /* NZ for TeX mode in current file */ ++S_INIT (int prefstringchar, -1); /* Preferred string character type */ ++ ++S_INIT (int terse, 0); /* NZ for "terse" mode */ ++ ++S_INIT (char tempfile[MAXPATHLEN], ""); /* Name of file we're spelling into */ ++ ++S_INIT (int minword, MINWORD); /* Longest always-legal word */ ++S_INIT (int sortit, 1); /* Sort suggestions alphabetically */ ++S_INIT (int compoundflag, -1); /* How to treat compounds: see above */ ++S_INIT (int tryhardflag, -1); /* Always call tryveryhard */ ++ ++S_INIT (char * currentfile, NULL); /* Name of current input file */ ++ ++/* Odd numbers for math mode in LaTeX; even for LR or paragraph mode */ ++S_INIT (int math_mode, 0); ++/* P -- paragraph or LR mode ++ * b -- parsing a \begin statement ++ * e -- parsing an \end statement ++ * r -- parsing a \ref type of argument. ++ * m -- looking for a \begin{minipage} argument. ++ */ ++S_INIT (char LaTeX_Mode, 'P'); ++ ++#include "i_proto.h" +diff -Nur vim60am.old/src/spell/local.h vim60am/src/spell/local.h +--- vim60am.old/src/spell/local.h Thu Jan 1 01:00:00 1970 ++++ vim60am/src/spell/local.h Wed Jun 27 19:16:51 2001 +@@ -0,0 +1,338 @@ ++/* ++ * Written by Eli Zaretskii ++ * ++ * This is local.h file suitable for compiling Ispell on MS-DOS systems ++ * with version 2.x of DJGPP port of GNU C/C++ compiler. ++ * ++ * $Id$ ++ * ++ * $Log$ ++ */ ++ ++/* ++ * WARNING WARNING WARNING ++ * ++ * This file is *NOT* a normal C header file! Although it uses C ++ * syntax and is included in C programs, it is also processed by shell ++ * scripts that are very stupid about format. ++ * ++ * Do not try to use #if constructs to configure this file for more ++ * than one configuration. Do not place whitespace after the "#" in ++ * "#define". Do not attempt to disable lines by commenting them out. ++ * Do not use backslashes to reduce the length of long lines. ++ * None of these things will work the way you expect them to. ++ * ++ * WARNING WARNING WARNING ++ */ ++ ++/* ++** Things that normally go in a Makefile. Define these just like you ++** might in the Makefile, except you should use #define instead of ++** make's assignment syntax. Everything must be double-quoted, and ++** (unlike make) you can't use any sort of $-syntax to pick up the ++** values of other definitions. ++*/ ++ ++#define CC "gcc" ++#define CFLAGS "-O2 -g" ++#define YACC "bison -y" ++ ++/* ++** TERMLIB - DJGPP doesn't have one, it uses direct screen writes. ++*/ ++#define TERMLIB "" ++ ++/* ++** Where to install various components of ispell. BINDIR contains ++** binaries. LIBDIR contains hash tables and affix files. ELISPDIR ++** contains emacs lisp files (if any) and TEXINFODIR contains emacs ++** TeXinfo files. MAN1DIR and MAN1EXT will hold the chapter-1 and ++** chapter-4 manual pages, respectively. ++** ++** If you intend to use multiple dictionary files, I would suggest ++** LIBDIR be a directory which will contain nothing else, so sensible ++** names can be constructed for the -d option without conflict. ++*/ ++#define BINDIR "/usr/bin" ++#define LIBDIR "/usr/lib/ispell" ++#define ELISPDIR "/usr/lib/emacs/site-lisp" ++#define TEXINFODIR "/usr/share/info" ++#define MAN1DIR "/usr/share/man/man1" ++#define MAN4DIR "/usr/share/man/man4" ++ ++/* ++** List of all hash files (languages) which will be supported by ispell. ++** ++** This variable has a complex format so that many options can be ++** specified. The format is as follows: ++** ++** [,...] [ [, ...] ...] ++** ++** where ++** ++** language is the name of a subdirectory of the ++** "languages" directory ++** make-options are options that are to be passed to "make" in ++** the specified directory. The make-options ++** should not, in general, specify a target, as ++** this will be provided by the make process. ++** ++** For example, if LANGUAGES is: ++** ++** "{american,EXTRADICT=/usr/dict/words /usr/dict/web2} {deutsch}", ++** ++** then the American-English and Deutsch (German) languages will be supported, ++** and when the English dictionary is built, the variable ++** 'EXTRADICT=/usr/dict/words /usr/dict/web2' will be passed to the makefile. ++** ++** Notes on the syntax: The makefile is not very robust. If you have ++** make problems, or if make seems to in the language-subdirs ++** dependency, check your syntax. The makefile adds single quotes to ++** the individual variables in the LANGUAGES specification, so don't ++** use quotes of any kind. ++** ++** In the future, the first language listed in this variable will ++** become the default, and the DEFHASH, DEFLANG, and DEFPAFF, ++** variables will all become obsolete. So be sure to put your default ++** language first, to make later conversion easier! ++** ++** Notes on options for the various languages will be found in the ++** Makefiles for those languages. Some of those languages may require ++** you to also change various limits limits like MASKBITS or the ++** length parameters. ++** ++** A special note on the English language: because the British and ++** American dialects use different spelling, you should usually select ++** one or the other of these. If you select both, the setting of ++** MASTERHASH will determine which becomes the language linked to ++** DEFHASH (which will usually be named english.hash). ++** ++** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ++** !!! Note the pathname for the `words' file: it might be different !!! ++** !!! If you don't have this file, make EXTRADICT empty !!! ++** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ++*/ ++#define LANGUAGES "{american,MASTERDICTS=americax.med,HASHFILES=amermedx.hash,EXTRADICT=/usr/lib/ispell/words}" ++ ++/* ++** Master hash file for DEFHASH. This is the name of a hash file ++** built by a language Makefile. It should be the most-popular hash ++** file on your system, because it is the one that will be used by ++** default. It must be listed in LANGUAGES, above. ++*/ ++#define MASTERHASH "polish.hash" ++ ++/* ++** Default native-language hash file. This is the name given to the ++** hash table that will be used if no language is specified to ++** ispell. It is a link to MASTERHASH, above. ++*/ ++#define DEFHASH "polish.hash" ++ ++/* ++** If your sort command accepts the -T switch to set temp file ++** locations (try it out; on some systems it exists but is ++** undocumented), make the following variable the null string. ++** Otherwise leave it as the sed script. ++** ++** With DJGPP, you will probably use GNU Sort which accepts -T, so: ++*/ ++#define SORTTMP "" ++ ++/* ++** If your system has the rename(2) system call, define HAS_RENAME and ++** ispell will use that call to rename backup files. Otherwise, it ++** will use link/unlink. There is no harm in this except on MS-DOS, ++** which might not support link/unlink (DJGPP does, but also has rename). ++*/ ++#define HAS_RENAME 1 ++ ++/* environment variable for user's word list */ ++#ifndef PDICTVAR ++#define PDICTVAR "WORDLIST" ++#endif ++ ++/* ++** Prefix part of default private dictionary. Under MS-DOS 8.3 ++** filename limitation, we are in trouble... ++*/ ++#define DEFPDICT ".isp." ++ ++/* old place to look for default word list */ ++#define OLDPDICT ".isp." ++ ++/* ++** mktemp template for temporary file - MUST contain 6 consecutive X's. ++** On MSDOS the directory part of TEMPNAME is only used if neither $TMP ++** nor $TEMP nor $TMPDIR (in that order) are defined. If any of these ++** variables is defined, the filename part of TEMPNAME is appended to ++** their value. ++*/ ++#define TEMPNAME "/tmp/isXXXXXX" ++ ++/* ++** If REGEX_LOOKUP is NOT defined, the lookup command (L) will use the look(1) ++** command (if available) or the egrep command. If REGEX_LOOKUP is defined, ++** the lookup command will use the internal dictionary and the ++** regular-expression library (which you must supply separately. ++** DJGPP v2 has POSIX regexp functions. ++*/ ++#ifndef FEAT_SPELL_HL ++#define REGEX_LOOKUP 1 ++#endif ++ ++/* ++** Choose the proper type of regular-expression routines here. BSD ++** and public-domain systems have routines called re_comp and re_exec; ++** System V uses regcmp and regex. ++*/ ++#include ++#include ++#define REGCTYPE regex_t * ++#define REGCMP(re,str) (regcomp (re, str, 0), re) ++#define REGEX(re, str, dummy) \ ++ (re != 0 && regexec (re, str, 0, 0, 0) == 0 ? (char *)1 : NULL) ++#define REGFREE(re) \ ++ do { \ ++ if (re == 0) \ ++ re = (regex_t *)calloc (1, sizeof (regex_t)); \ ++ else \ ++ regfree(re); \ ++ } while (0) ++ ++/* ++** ++** The 2 following definitions are only meaningfull if you don't use ++** any regex library. ++*/ ++/* path to egrep (use speeded up version if available); ++ defined without explicit path, since there are no ++ standard places for programs on MS-DOS. */ ++#define EGREPCMD "egrep -i" ++ ++/* path to wordlist for Lookup command (typically /usr/dict/{words|web2}) */ ++/* note that /usr/dict/web2 is usually a bad idea due to obscure words */ ++#undef WORDS ++ ++/* ++** FIXME: The filename truncation below is not flexible enough for DJGPP ++** which can support long filenames on some platforms, since we ++** will only know if the support is available at runtime. ++*/ ++ ++/* max file name length (will truncate to fit BAKEXT) if not in sys/param.h */ ++#ifdef NAME_MAX ++#define MAXNAMLEN NAME_MAX ++#else ++#define MAXNAMLEN 12 ++#endif ++ ++#define MAXEXTLEN 4 /* max. extension length including '.' */ ++#define MAXBASENAMELEN 8 /* max. base filename length without ext */ ++ ++/* define if you want .bak file names truncated to MAXNAMLEN characters */ ++/* On MS-DOS, we really have no choice... */ ++#define TRUNCATEBAK 1 ++ ++/* ++** This is the extension that will be added to backup files. ++** On MS-DOS, it makes sense to use the shortest possible extension. ++*/ ++#define BAKEXT "~" ++ ++/* ++** Define the following to suppress the 8-bit character feature. ++** FIXME: does this defeat support of foreign languages? ++*/ ++/*#define NO8BIT 1 */ ++#ifdef NO8BIT ++#undef NO8BIT ++#endif ++ ++/* ++** Define this if you want to use the shell for interpretation of commands ++** issued via the "L" command, "^Z" under System V, and "!". If this is ++** not defined then a direct spawnvp() will be used in place of the ++** normal system(). This may speed up these operations if the SHELL ++** environment variable points to a Unix-like shell (such as `sh' or `bash'). ++** ++** However, if you undefine USESH, commands which use pipes, redirection ++** and shell wildcards won't work, and you will need support for the SIGTSTP ++** signal, for the above commands to work at all. ++*/ ++ ++#define USESH 1 ++ ++/* ++** Define this if you want to be able to type any command at a "type space ++** to continue" prompt. ++*/ ++#define COMMANDFORSPACE 1 ++ ++/* ++** The next three variables are used to provide a variable-size context ++** display at the bottom of the screen. Normally, the user will see ++** a number of lines equal to CONTEXTPCT of his screen, rounded down ++** (thus, with CONTEXTPCT == 10, a 24-line screen will produce two lines ++** of context). The context will never be greater than MAXCONTEXT or ++** less than MINCONTEXT. To disable this feature entirely, set MAXCONTEXT ++** and MINCONTEXT to the same value. To round context percentages up, ++** define CONTEXTROUNDUP. ++** ++** Warning: don't set MAXCONTEXT ridiculously large. There is a ++** static buffer of size MAXCONTEXT*BUFSIZ; since BUFSIZ is frequently ++** 1K or larger, this can create a remarkably large executable. ++*/ ++#define CONTEXTPCT 20 /* Use 20% of the screen for context */ ++#define MINCONTEXT 2 /* Always show at least 2 lines of context */ ++#define MAXCONTEXT 10 /* Never show more than 10 lines of context */ ++#define CONTEXTROUNDUP 1 /* Round context up */ ++ ++/* ++** Define this if you want the "mini-menu," which gives the most important ++** options at the bottom of the screen, to be the default (in any case, it ++** can be controlled with the "-M" switch). ++*/ ++#define MINIMENU ++ ++/* ++** Redefine GETKEYSTROKE() to whatever appropriate on some MS-DOS systems ++** where getchar() doesn't operate properly in raw mode. ++*/ ++#ifdef __DJGPP__ ++#include ++#include ++#define GETKEYSTROKE() getxkey() ++#else ++#define GETKEYSTROKE() getchar() ++#endif ++ ++/* ++** We include to have the definition of O_BINARY. The ++** configuration script will notice this and define MSDOS_BINARY_OPEN. ++*/ ++#include ++ ++/* ++** Environment variable to use to locate the home directory. On DOS ++** systems we set this to ISPELL_HOME to avoid conflicts with ++** other programs that look for a HOME environment variable. ++*/ ++#define HOME "ISPELL_HOME" ++#define PDICTHOME "." ++#define OPTIONVAR "ISPELL_OPTIONS" ++#define LIBRARYVAR "ISPELL_DICTDIR" ++ ++/* ++** On MS-DOS systems, we define the following variables so that ++** ispell's files have legal suffixes. Note that these suffixes ++** must agree with the way you've defined dictionary files which ++** incorporate these suffixes. ++** ++** Actually, it is not recommended at all to change the suffixes, ++** since they are hardwired in the Makefile's under languages/ ++** subdirectory, and MS-DOS will silently truncate excess letters anyway. ++*/ ++#define HASHSUFFIX ".hash" ++#define STATSUFFIX ".sta" ++#define COUNTSUFFIX ".cnt" +diff -Nur vim60am.old/src/spell/lookup.c vim60am/src/spell/lookup.c +--- vim60am.old/src/spell/lookup.c Thu Jan 1 01:00:00 1970 ++++ vim60am/src/spell/lookup.c Wed Jun 27 19:16:52 2001 +@@ -0,0 +1,534 @@ ++#ifndef lint ++static char Rcs_Id[] = ++ "$Id$"; ++#endif ++ ++/* ++ * lookup.c - see if a word appears in the dictionary ++ * ++ * Pace Willisson, 1983 ++ * ++ * Copyright 1987, 1988, 1989, 1992, 1993, Geoff Kuenning, Granada Hills, CA ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All modifications to the source code must be clearly marked as ++ * such. Binary redistributions based on modified source code ++ * must be clearly marked as modified versions in the documentation ++ * and/or other materials provided with the distribution. ++ * 4. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgment: ++ * This product includes software developed by Geoff Kuenning and ++ * other unpaid contributors. ++ * 5. The name of Geoff Kuenning may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY GEOFF KUENNING AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL GEOFF KUENNING OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++/* ++ * $Log$ ++ * Revision 1.42 1995/01/08 23:23:42 geoff ++ * Support MSDOS_BINARY_OPEN when opening the hash file to read it in. ++ * ++ * Revision 1.41 1994/01/25 07:11:51 geoff ++ * Get rid of all old RCS log lines in preparation for the 3.1 release. ++ * ++ */ ++ ++#include "ispell.h" ++#include "msgs.h" ++#include ++#include ++#ifdef WIN32 ++#include ++#endif ++ ++#ifdef INDEXDUMP ++Local void dumpindex (struct flagptr * indexp, int depth); ++#endif /* INDEXDUMP */ ++ ++Public Logical inited = False; ++ ++char err_buf[256]; ++ ++Public char * ++linit (char * hashname) ++{ ++ int hashfd; ++ register int i; ++ register struct dent * dp; ++ struct flagent * entry; ++ struct flagptr * ind; ++ int nextchar; ++ int viazero; ++ register ichar_t * cp; ++ ++ if (inited) ++ return(NULL); ++ ++ if(hashtbl != NULL) ++ free(hashtbl); ++ numpflags = 0; ++ numsflags = 0; ++ if(pflagindex != NULL) ++ free(pflagindex); ++ pflagindex = NULL; ++ if(sflagindex != NULL) ++ free(sflagindex); ++ sflagindex = NULL; ++ if((pflagindex = (struct flagptr *)calloc(SET_SIZE + MAXSTRINGCHARS, ++ sizeof(struct flagptr))) == NULL) ++ { ++ (void) sprintf(err_buf, LOOKUP_C_NO_HASH_SPACE); ++ return(err_buf); ++ } ++ if((sflagindex = (struct flagptr *)calloc(SET_SIZE + MAXSTRINGCHARS, ++ sizeof(struct flagptr))) == NULL) ++ { ++ (void) sprintf(err_buf, LOOKUP_C_NO_HASH_SPACE); ++ return(err_buf); ++ } ++ hashtbl = NULL; ++ if ((hashfd = open (hashname, 0 | MSDOS_BINARY_OPEN)) < 0) ++ { ++ (void) sprintf(err_buf, CANT_OPEN, hashname); ++ return(err_buf); ++ } ++ ++ hashsize = read (hashfd, (char *) &hashheader, sizeof hashheader); ++ if (hashsize < sizeof hashheader) ++ { ++ if (hashsize < 0) ++ (void) sprintf(err_buf, LOOKUP_C_CANT_READ, hashname); ++ else if (hashsize == 0) ++ (void) sprintf(err_buf, LOOKUP_C_NULL_HASH, hashname); ++ else ++ (void) sprintf(err_buf, LOOKUP_C_SHORT_HASH (hashname, hashsize, ++ (int) sizeof hashheader)); ++ (void) close (hashfd); ++ return(err_buf); ++ } ++ else if (hashheader.magic != SPELL_MAGIC) ++ { ++ (void) sprintf(err_buf, ++ LOOKUP_C_BAD_MAGIC (hashname, (unsigned int) SPELL_MAGIC, ++ (unsigned int) hashheader.magic)); ++ (void) close (hashfd); ++ return(err_buf); ++ } ++ else if (hashheader.magic2 != SPELL_MAGIC) ++ { ++ (void) sprintf(err_buf, ++ LOOKUP_C_BAD_MAGIC2 (hashname, (unsigned int) SPELL_MAGIC, ++ (unsigned int) hashheader.magic2)); ++ (void) close (hashfd); ++ return(err_buf); ++ } ++ else if (hashheader.compileoptions != COMPILEOPTIONS ++ || hashheader.maxstringchars != MAXSTRINGCHARS ++ || hashheader.maxstringcharlen != MAXSTRINGCHARLEN) ++ { ++ (void) sprintf(err_buf, ++ LOOKUP_C_BAD_OPTIONS ((unsigned int) hashheader.compileoptions, ++ hashheader.maxstringchars, hashheader.maxstringcharlen, ++ (unsigned int) COMPILEOPTIONS, MAXSTRINGCHARS, MAXSTRINGCHARLEN)); ++ (void) close (hashfd); ++ return(err_buf); ++ } ++ if (nodictflag) ++ { ++ /* ++ * Dictionary is not needed - create an empty dummy table. We ++ * actually have to have one entry since the hash ++ * algorithm involves a divide by the table size ++ * (actually modulo, but zero is still unacceptable). ++ * So we create an empty entry. ++ */ ++ hashsize = 1; /* This prevents divides by zero */ ++ hashtbl = (struct dent *) calloc (1, sizeof (struct dent)); ++ if (hashtbl == NULL) ++ { ++ (void) sprintf(err_buf, LOOKUP_C_NO_HASH_SPACE); ++ (void) close (hashfd); ++ return(err_buf); ++ } ++ hashtbl[0].word = NULL; ++ hashtbl[0].next = NULL; ++ hashtbl[0].flagfield &= ~(USED | KEEP); ++ /* The flag bits don't matter, but calloc cleared them. */ ++ if(hashstrings != NULL) ++ free(hashstrings); ++ if((hashstrings = (char *) calloc (1, (unsigned) hashheader.lstringsize)) ++ == NULL) ++ { ++ (void) sprintf(err_buf, LOOKUP_C_NO_HASH_SPACE); ++ (void) close (hashfd); ++ return(err_buf); ++ } ++ } ++ else ++ { ++ if(hashtbl != NULL) ++ free(hashtbl); ++ if((hashtbl = (struct dent *) ++ malloc ((unsigned) hashheader.tblsize * sizeof (struct dent))) == NULL) ++ { ++ (void) sprintf(err_buf, LOOKUP_C_NO_HASH_SPACE); ++ (void) close (hashfd); ++ return(err_buf); ++ } ++ hashsize = hashheader.tblsize; ++ if(hashstrings != NULL) ++ free(hashstrings); ++ if((hashstrings = (char *) malloc ((unsigned) hashheader.stringsize)) == NULL) ++ { ++ (void) sprintf(err_buf, LOOKUP_C_NO_HASH_SPACE); ++ (void) close (hashfd); ++ return(err_buf); ++ } ++ } ++ numsflags = hashheader.stblsize; ++ numpflags = hashheader.ptblsize; ++ if(sflaglist != NULL) ++ free(sflaglist); ++ if((sflaglist = (struct flagent *) ++ malloc ((numsflags + numpflags) * sizeof (struct flagent))) == NULL) ++ { ++ (void) sprintf(err_buf, LOOKUP_C_NO_HASH_SPACE); ++ (void) close (hashfd); ++ return(err_buf); ++ } ++ pflaglist = sflaglist + numsflags; ++ ++ if (nodictflag) ++ { ++ /* ++ * Read just the strings for the language table, and ++ * skip over the rest of the strings and all of the ++ * hash table. ++ */ ++ if (read (hashfd, hashstrings, (unsigned) hashheader.lstringsize) ++ != hashheader.lstringsize) ++ { ++ (void) sprintf(err_buf, LOOKUP_C_BAD_FORMAT); ++ (void) close (hashfd); ++ return(err_buf); ++ } ++ (void) lseek (hashfd, ++ (long) hashheader.stringsize - (long) hashheader.lstringsize ++ + (long) hashheader.tblsize * (long) sizeof (struct dent), 1); ++ } ++ else ++ { ++ if ((unsigned int)read (hashfd, hashstrings, ++ (unsigned int) hashheader.stringsize) != hashheader.stringsize ++ || (unsigned int)read (hashfd, (char *) hashtbl, (unsigned) ++ hashheader.tblsize * sizeof (struct dent)) ++ != (unsigned int) hashheader.tblsize * sizeof (struct dent)) ++ { ++ (void) sprintf(err_buf, LOOKUP_C_BAD_FORMAT); ++ (void) close (hashfd); ++ return(err_buf); ++ } ++ } ++ if ((unsigned int)read (hashfd, (char *) sflaglist, ++ (unsigned int) (numsflags + numpflags) * sizeof (struct flagent)) ++ != (unsigned int)(numsflags + numpflags) * sizeof (struct flagent)) ++ { ++ (void) sprintf(err_buf, LOOKUP_C_BAD_FORMAT); ++ (void) close (hashfd); ++ return(err_buf); ++ } ++ (void) close (hashfd); ++ ++ if (!nodictflag) ++ { ++ for (i = hashsize, dp = hashtbl; --i >= 0; dp++) ++ { ++ if (dp->word == (char *) -1) ++ dp->word = NULL; ++ else ++ dp->word = &hashstrings [ (int)(dp->word) ]; ++ if (dp->next == (struct dent *) -1) ++ dp->next = NULL; ++ else ++ dp->next = &hashtbl [ (int)(dp->next) ]; ++ } ++ } ++ ++ for (i = numsflags + numpflags, entry = sflaglist; --i >= 0; entry++) ++ { ++ if (entry->stripl) ++ entry->strip = (ichar_t *) &hashstrings[(int) entry->strip]; ++ else ++ entry->strip = NULL; ++ if (entry->affl) ++ entry->affix = (ichar_t *) &hashstrings[(int) entry->affix]; ++ else ++ entry->affix = NULL; ++ } ++ /* ++ ** Warning - 'entry' and 'i' are reset in the body of the loop ++ ** below. Don't try to optimize it by (e.g.) moving the decrement ++ ** of i into the loop condition. ++ */ ++ for (i = numsflags, entry = sflaglist; i > 0; i--, entry++) ++ { ++ if (entry->affl == 0) ++ { ++ cp = NULL; ++ ind = &sflagindex[0]; ++ viazero = 1; ++ } ++ else ++ { ++ cp = entry->affix + entry->affl - 1; ++ ind = &sflagindex[*cp]; ++ viazero = 0; ++ while (ind->numents == 0 && ind->pu.fp != NULL) ++ { ++ if (cp == entry->affix) ++ { ++ ind = &ind->pu.fp[0]; ++ viazero = 1; ++ } ++ else ++ { ++ ind = &ind->pu.fp[*--cp]; ++ viazero = 0; ++ } ++ } ++ } ++ if (ind->numents == 0) ++ ind->pu.ent = entry; ++ ind->numents++; ++ /* ++ ** If this index entry has more than MAXSEARCH flags in ++ ** it, we will split it into subentries to reduce the ++ ** searching. However, the split doesn't make sense in ++ ** two cases: (a) if we are already at the end of the ++ ** current affix, or (b) if all the entries in the list ++ ** have identical affixes. Since the list is sorted, (b) ++ ** is true if the first and last affixes in the list ++ ** are identical. ++ */ ++ if (!viazero && ind->numents >= MAXSEARCH && ++ icharcmp (entry->affix, ind->pu.ent->affix) != 0) ++ { ++ /* Sneaky trick: back up and reprocess */ ++ entry = ind->pu.ent - 1; /* -1 is for entry++ in loop */ ++ i = numsflags - (entry - sflaglist); ++ if((ind->pu.fp = (struct flagptr *) ++ calloc ((unsigned) (SET_SIZE + hashheader.nstrchars), ++ sizeof (struct flagptr))) == NULL) ++ { ++ (void) sprintf(err_buf, LOOKUP_C_NO_LANG_SPACE); ++ return(err_buf); ++ } ++ ind->numents = 0; ++ } ++ } ++ /* ++ ** Warning - 'entry' and 'i' are reset in the body of the loop ++ ** below. Don't try to optimize it by (e.g.) moving the decrement ++ ** of i into the loop condition. ++ */ ++ for (i = numpflags, entry = pflaglist; i > 0; i--, entry++) ++ { ++ if (entry->affl == 0) ++ { ++ cp = NULL; ++ ind = &pflagindex[0]; ++ viazero = 1; ++ } ++ else ++ { ++ cp = entry->affix; ++ ind = &pflagindex[*cp++]; ++ viazero = 0; ++ while (ind->numents == 0 && ind->pu.fp != NULL) ++ { ++ if (*cp == 0) ++ { ++ ind = &ind->pu.fp[0]; ++ viazero = 1; ++ } ++ else ++ { ++ ind = &ind->pu.fp[*cp++]; ++ viazero = 0; ++ } ++ } ++ } ++ if (ind->numents == 0) ++ ind->pu.ent = entry; ++ ind->numents++; ++ /* ++ ** If this index entry has more than MAXSEARCH flags in ++ ** it, we will split it into subentries to reduce the ++ ** searching. However, the split doesn't make sense in ++ ** two cases: (a) if we are already at the end of the ++ ** current affix, or (b) if all the entries in the list ++ ** have identical affixes. Since the list is sorted, (b) ++ ** is true if the first and last affixes in the list ++ ** are identical. ++ */ ++ if (!viazero && ind->numents >= MAXSEARCH ++ && icharcmp (entry->affix, ind->pu.ent->affix) != 0) ++ { ++ /* Sneaky trick: back up and reprocess */ ++ entry = ind->pu.ent - 1; /* -1 is for entry++ in loop */ ++ i = numpflags - (entry - pflaglist); ++ ind->pu.fp = ++ (struct flagptr *) calloc (SET_SIZE + hashheader.nstrchars, ++ sizeof (struct flagptr)); ++ if (ind->pu.fp == NULL) ++ { ++ (void) sprintf(err_buf, LOOKUP_C_NO_LANG_SPACE); ++ return(err_buf); ++ } ++ ind->numents = 0; ++ } ++ } ++#ifdef INDEXDUMP ++ (void) sprintf(err_buf, "Prefix index table:"); ++ dumpindex (pflagindex, 0); ++ (void) sprintf(err_buf, "Suffix index table:"); ++ dumpindex (sflagindex, 0); ++#endif ++ if (hashheader.nstrchartype == 0) ++ chartypes = NULL; ++ else ++ { ++ chartypes = (struct strchartype *) ++ calloc (1, hashheader.nstrchartype * sizeof (struct strchartype)); ++ if (chartypes == NULL) ++ { ++ (void) sprintf(err_buf, LOOKUP_C_NO_LANG_SPACE); ++ return(err_buf); ++ } ++ for (i = 0, nextchar = hashheader.strtypestart; ++ i < hashheader.nstrchartype; i++) ++ { ++ chartypes[i].name = &hashstrings[nextchar]; ++ nextchar += strlen (chartypes[i].name) + 1; ++ chartypes[i].deformatter = &hashstrings[nextchar]; ++ nextchar += strlen (chartypes[i].deformatter) + 1; ++ chartypes[i].suffixes = &hashstrings[nextchar]; ++ while (hashstrings[nextchar] != '\0') ++ nextchar += strlen (&hashstrings[nextchar]) + 1; ++ nextchar++; ++ } ++ } ++ inited = True; ++ return (NULL); ++} ++ ++#ifdef INDEXDUMP ++Local void ++dumpindex ( ++ register struct flagptr * indexp, ++ register int depth) ++{ ++ register int i; ++ int j; ++ int k; ++ char stripbuf[INPUTWORDLEN + 4 * MAXAFFIXLEN + 4]; ++ ++ for (i = 0; i < SET_SIZE + hashheader.nstrchars; i++, indexp++) ++ { ++ if (indexp->numents == 0 && indexp->pu.fp != NULL) ++ { ++ for (j = depth; --j >= 0; ) ++ (void) putc (' ', stderr); ++ if (i >= ' ' && i <= '~') ++ (void) putc (i, stderr); ++ else ++ (void) fprintf (stderr, "0x%x", i); ++ (void) putc ('\n', stderr); ++ dumpindex (indexp->pu.fp, depth + 1); ++ } ++ else if (indexp->numents) ++ { ++ for (j = depth; --j >= 0; ) ++ (void) putc (' ', stderr); ++ if (i >= ' ' && i <= '~') ++ (void) putc (i, stderr); ++ else ++ (void) fprintf (stderr, "0x%x", i); ++ (void) fprintf (stderr, " -> %d entries\n", indexp->numents); ++ for (k = 0; k < indexp->numents; k++) ++ { ++ for (j = depth; --j >= 0; ) ++ (void) putc (' ', stderr); ++ if (indexp->pu.ent[k].stripl) ++ { ++ (void) ichartostr (stripbuf, indexp->pu.ent[k].strip, ++ sizeof stripbuf, 1); ++ (void) fprintf (stderr, " entry %d (-%s,%s)\n", ++ &indexp->pu.ent[k] - sflaglist, ++ stripbuf, ++ indexp->pu.ent[k].affl ++ ? ichartosstr (indexp->pu.ent[k].affix, 1) : "-"); ++ } ++ else ++ (void) fprintf (stderr, " entry %d (%s)\n", ++ &indexp->pu.ent[k] - sflaglist, ++ ichartosstr (indexp->pu.ent[k].affix, 1)); ++ } ++ } ++ } ++} ++#endif ++ ++/* n is length of s */ ++Public struct dent * ++lookup (register ichar_t *s, int dotree) ++ ++{ ++ register struct dent * dp; ++ register char * s1; ++ char schar[INPUTWORDLEN + MAXAFFIXLEN]; ++ ++ dp = &hashtbl[hash (s, hashsize)]; ++ if (ichartostr (schar, s, sizeof schar, 1)) ++ (void) fprintf (stderr, WORD_TOO_LONG (schar)); ++ for ( ; dp != NULL; dp = dp->next) ++ { ++ /* quick strcmp, but only for equality */ ++ s1 = dp->word; ++ if (s1 && s1[0] == schar[0] && strcmp (s1 + 1, schar + 1) == 0) ++ return dp; ++#ifndef NO_CAPITALIZATION_SUPPORT ++ while (dp->flagfield & MOREVARIANTS) /* Skip variations */ ++ dp = dp->next; ++#endif ++ } ++ if (dotree) ++ { ++ dp = treelookup (s); ++ return dp; ++ } ++ else ++ return NULL; ++} +diff -Nur vim60am.old/src/spell/makedent.c vim60am/src/spell/makedent.c +--- vim60am.old/src/spell/makedent.c Thu Jan 1 01:00:00 1970 ++++ vim60am/src/spell/makedent.c Wed Jun 27 19:16:52 2001 +@@ -0,0 +1,1107 @@ ++/* ++ * Copyright 1988, 1989, 1992, 1993, Geoff Kuenning, Granada Hills, CA ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All modifications to the source code must be clearly marked as ++ * such. Binary redistributions based on modified source code ++ * must be clearly marked as modified versions in the documentation ++ * and/or other materials provided with the distribution. ++ * 4. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgment: ++ * This product includes software developed by Geoff Kuenning and ++ * other unpaid contributors. ++ * 5. The name of Geoff Kuenning may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY GEOFF KUENNING AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL GEOFF KUENNING OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++/* ++ * $Log$ ++ * Revision 1.45 1994/12/27 23:08:52 geoff ++ * Add code to makedent to reject words that contain non-word characters. ++ * This helps protect people who use ISO 8-bit characters when ispell ++ * isn't configured for that option. ++ * ++ * Revision 1.44 1994/10/25 05:46:20 geoff ++ * Fix some incorrect declarations in the lint versions of some routines. ++ * ++ * Revision 1.43 1994/09/16 03:32:34 geoff ++ * Issue an error message for bad affix flags ++ * ++ * Revision 1.42 1994/02/07 04:23:43 geoff ++ * Correctly identify the deformatter when changing file types ++ * ++ * Revision 1.41 1994/01/25 07:11:55 geoff ++ * Get rid of all old RCS log lines in preparation for the 3.1 release. ++ * ++ */ ++ ++#include "ispell.h" ++#include ++#include "msgs.h" ++ ++Global int makedent(char * lbuf, int lbuflen, struct dent * ent); ++#ifndef NO_CAPITALIZATION_SUPPORT ++Global long whatcap(ichar_t * word); ++#endif ++Global int addvheader(struct dent * ent); ++Global int combinecaps(struct dent * hdr, struct dent * newent); ++#ifndef NO_CAPITALIZATION_SUPPORT ++Local void forcevheader(struct dent * hdrp, struct dent * oldp, ++ struct dent * newp); ++#endif /* NO_CAPITALIZATION_SUPPORT */ ++Local int combine_two_entries(struct dent * hdrp, ++ struct dent * oldp, struct dent * newp); ++Local int acoversb(struct dent * enta, struct dent * entb); ++Global void upcase(ichar_t * string); ++Global void lowcase(ichar_t * string); ++Global void chupcase(char * s); ++Local int issubset(struct dent * ent1, struct dent * ent2); ++Local void combineaffixes(struct dent * ent1, struct dent * ent2); ++Global void toutent(FILE * outfile, struct dent * hent, int onlykeep); ++Local void toutword(FILE * outfile, char * word, struct dent * cent); ++Local void flagout(FILE * outfile, int flag); ++Global int stringcharlen(char * bufp, int canonical); ++Global int strtoichar(ichar_t * out, char * in, int outlen, ++ int canonical); ++Global int ichartostr(char * out, ichar_t * in, int outlen, ++ int canonical); ++Global ichar_t * strtosichar(char * in, int canonical); ++Global char * ichartosstr(ichar_t * in, int canonical); ++Global char * printichar(int in); ++#ifndef ICHAR_IS_CHAR ++Global ichar_t * icharcpy(ichar_t * out, ichar_t * in); ++Global int icharlen(ichar_t * str); ++Global int icharcmp(ichar_t * s1, ichar_t * s2); ++Global int icharncmp(ichar_t * s1, ichar_t * s2, int n); ++#endif /* ICHAR_IS_CHAR */ ++Global int findfiletype(char * name, int searchnames, ++ int * deformatter); ++ ++Local Logical has_marker; ++ ++/* ++ * Fill in a directory entry, including setting the capitalization flags, and ++ * allocate and initialize memory for the d->word field. Returns -1 ++ * if there was trouble. The input word must be in canonical form. ++ */ ++ ++Public int ++makedent( ++ char * lbuf, ++ int lbuflen, ++ struct dent * d) ++{ ++ ichar_t ibuf[INPUTWORDLEN + MAXAFFIXLEN]; ++ ichar_t * ip; ++ char * p; ++ int bit; ++ int len; ++ ++ /* Strip off any trailing newline */ ++ len = strlen(lbuf) - 1; ++ if(lbuf[len] == '\n') ++ lbuf[len] = '\0'; ++ ++ d->next = NULL; ++ /* WARNING: flagfield might be the same as mask! See ispell.h. */ ++ d->flagfield = 0; ++ (void) bzero ((char *) d->mask, sizeof (d->mask)); ++ d->flagfield |= USED; ++ d->flagfield &= ~KEEP; ++ ++ p = index(lbuf, hashheader.flagmarker); ++ if(p != NULL) ++ *p = 0; ++ ++ /* ++ ** Convert the word to an ichar_t and back; this makes sure that ++ ** it is in canonical form and thus that the length is correct. ++ */ ++ if(strtoichar(ibuf, lbuf, INPUTWORDLEN * sizeof (ichar_t), 1) ++ || ichartostr(lbuf, ibuf, lbuflen, 1)) ++ { ++ (void) fprintf(stderr, WORD_TOO_LONG (lbuf)); ++ return(-1); ++ } ++ /* ++ ** Make sure the word is well-formed(contains only legal characters). ++ */ ++ for(ip = ibuf; *ip != 0; ip++) ++ { ++ if(!iswordch(*ip)) ++ { ++ /* Boundary characters are legal as long as they're not at edges */ ++ if(!isboundarych(*ip) || ip == ibuf || ip[1] == 0) ++ { ++ (void) fprintf(stderr, MAKEDENT_C_BAD_WORD_CHAR, lbuf); ++ return -1; ++ } ++ } ++ } ++ len = strlen(lbuf); ++#ifndef NO_CAPITALIZATION_SUPPORT ++ /* ++ ** Figure out the capitalization rules from the capitalization of ++ ** the sample entry. ++ */ ++ d->flagfield |= whatcap(ibuf); ++#endif ++ ++ if(len > INPUTWORDLEN - 1) ++ { ++ (void) fprintf(stderr, WORD_TOO_LONG (lbuf)); ++ return(-1); ++ } ++ ++ d->word = malloc((unsigned) len + 1); ++ if(d->word == NULL) ++ { ++ (void) fprintf(stderr, MAKEDENT_C_NO_WORD_SPACE, lbuf); ++ return -1; ++ } ++ ++ (void) strcpy (d->word, lbuf); ++#ifdef NO_CAPITALIZATION_SUPPORT ++ chupcase(d->word); ++#else /* NO_CAPITALIZATION_SUPPORT */ ++ if(captype(d->flagfield) != FOLLOWCASE) ++ chupcase(d->word); ++#endif /* NO_CAPITALIZATION_SUPPORT */ ++ if(p == NULL) ++ return(0); ++ ++ p++; ++ while(*p != '\0' && *p != '\n') ++ { ++ bit = CHARTOBIT((unsigned char) *p); ++ if(bit >= 0 && bit <= LARGESTFLAG) ++ SETMASKBIT(d->mask, bit); ++ else ++ (void) fprintf (stderr, BAD_FLAG, (unsigned char) *p); ++ p++; ++ if(*p == hashheader.flagmarker) ++ p++; /* Handle old-format dictionaries too */ ++ } ++ return(0); ++} ++ ++#ifndef NO_CAPITALIZATION_SUPPORT ++/* ++** Classify the capitalization of a sample entry. Returns one of the ++** four capitalization codes ANYCASE, ALLCAPS, CAPITALIZED, or FOLLOWCASE. ++*/ ++ ++Public long ++whatcap(register ichar_t * word) ++{ ++ register ichar_t * p; ++ ++ for(p = word; *p; p++) ++ { ++ if(mylower(*p)) ++ break; ++ } ++ if(*p == '\0') ++ return ALLCAPS; ++ else ++ { ++ for(; *p; p++) ++ if(myupper(*p)) ++ break; ++ if(*p == '\0') ++ { ++ /* ++ ** No uppercase letters follow the lowercase ones. ++ ** If there is more than one uppercase letter, it's ++ ** "followcase". If only the first one is capitalized, ++ ** it's "capitalize". If there are no capitals ++ ** at all, it's ANYCASE. ++ */ ++ if(myupper(word[0])) ++ { ++ for(p = word + 1; *p != '\0'; p++) ++ if(myupper(*p)) ++ return FOLLOWCASE; ++ return CAPITALIZED; ++ } ++ else ++ return ANYCASE; ++ } ++ else ++ return FOLLOWCASE; /* .../lower/upper */ ++ } ++} ++ ++/* ++** Add a variant-capitalization header to a word. This routine may be ++** called even for a followcase word that doesn't yet have a header. ++** ++** Returns 0 if all was ok, -1 if allocation error. ++*/ ++Public int ++addvheader(register struct dent *dp) /* Entry to update */ ++{ ++ register struct dent * tdent; /* Copy of entry */ ++ ++ /* ++ ** Add a second entry with the correct capitalization, and then make ++ ** dp into a special dummy entry. ++ */ ++ tdent = (struct dent *) malloc (sizeof (struct dent)); ++ if(tdent == NULL) ++ { ++ (void) fprintf(stderr, MAKEDENT_C_NO_WORD_SPACE, dp->word); ++ return -1; ++ } ++ *tdent = *dp; ++ if(captype(tdent->flagfield) != FOLLOWCASE) ++ tdent->word = NULL; ++ else ++ { ++ /* Followcase words need a copy of the capitalization */ ++ tdent->word = malloc((unsigned int) strlen (tdent->word) + 1); ++ if(tdent->word == NULL) ++ { ++ (void) fprintf (stderr, MAKEDENT_C_NO_WORD_SPACE, dp->word); ++ free((char *) tdent); ++ return -1; ++ } ++ (void) strcpy(tdent->word, dp->word); ++ } ++ chupcase(dp->word); ++ dp->next = tdent; ++ dp->flagfield &= ~CAPTYPEMASK; ++ dp->flagfield |= (ALLCAPS | MOREVARIANTS); ++ return 0; ++} ++#endif /* NO_CAPITALIZATION_SUPPORT */ ++ ++/* ++** Combine and resolve the entries describing two capitalizations of the same ++** word. This may require allocating yet more entries. ++** ++** Hdrp is a pointer into a hash table. If the word covered by hdrp has ++** variations, hdrp must point to the header. Newp is a pointer to temporary ++** storage, and space is malloc'ed if newp is to be kept. The newp->word ++** field must have been allocated with mymalloc, so that this routine may free ++** the space if it keeps newp but not the word. ++** ++** Return value: 0 if the word was added, 1 if the word was combined ++** with an existing entry, and -1 if trouble occurred(e.g., malloc). ++** If 1 is returned, newp->word may have been be freed using myfree. ++** ++** Life is made much more difficult by the KEEP flag's possibilities. We ++** must ensure that a !KEEP word doesn't find its way into the personal ++** dictionary as a result of this routine's actions. However, a !KEEP ++** word that has affixes must have come from the main dictionary, so it ++** is acceptable to combine entries in that case(got that?). ++** ++** The net result of all this is a set of rules that is a bloody pain ++** to figure out. Basically, we want to choose one of the following actions: ++** ++** (1) Add newp's affixes and KEEP flag to oldp, and discard newp. ++** (2) Add oldp's affixes and KEEP flag to newp, replace oldp with ++** newp, and discard newp. ++#ifndef NO_CAPITALIZATION_SUPPORT ++** (3) Insert newp as a new entry in the variants list. If there is ++** currently no variant header, this requires adding one. Adding a ++** header splits into two sub-cases: ++** ++** (3a) If oldp is ALLCAPS and the KEEP flags match, just turn it ++** into the header. ++** (3b) Otherwise, add a new entry to serve as the header. ++** To ease list linking, this is done by copying oldp into ++** the new entry, and then performing(3a). ++** ++** After newp has been added as a variant, its affixes and KEEP ++** flag are OR-ed into the variant header. ++#endif ++** ++** So how to choose which? The default is always case(3), which adds newp ++** as a new entry in the variants list. Cases(1) and (2) are symmetrical ++** except for which entry is discarded. We can use case(1) or (2) whenever ++** one entry "covers" the other. "Covering" is defined as follows: ++** ++** (4) For entries with matching capitalization types, A covers B ++** if: ++** ++** (4a) B's affix flags are a subset of A's, or the KEEP flags ++** match, and ++** (4b) either the KEEP flags match, or A's KEEP flag is set. ++** (Since A has more suffixes, combining B with it won't ++** cause any extra suffixes to be added to the dictionary.) ++** (4c) If the words are FOLLOWCASE, the capitalizations match ++** exactly. ++** ++#ifndef NO_CAPITALIZATION_SUPPORT ++** (5) For entries with mismatched capitalization types, A covers B ++** if(4a) and(4b) are true, and: ++** ++** (5a) B is ALLCAPS, or ++** (5b) A is ANYCASE, and B is CAPITALIZED. ++#endif ++** ++** For any "hdrp" without variants, oldp is the same as hdrp. Otherwise, ++** the above tests are applied using each variant in turn for oldp. ++*/ ++Public int ++combinecaps( ++ struct dent * hdrp, /* Header of entry currently in dictionary */ ++ register struct dent * newp) /* Entry to add */ ++{ ++ register struct dent * ++ oldp; /* Current "oldp" entry */ ++#ifndef NO_CAPITALIZATION_SUPPORT ++ register struct dent * ++ tdent; /* Entry we'll add to the dictionary */ ++#endif /* NO_CAPITALIZATION_SUPPORT */ ++ register int retval = 0; /* Return value from combine_two_entries */ ++ ++ /* ++ ** First, see if we can combine the two entries(cases 1 and 2). If ++ ** combine_two_entries does so, it will return 1. If it has trouble, ++ ** it will return zero. ++ */ ++ oldp = hdrp; ++#ifdef NO_CAPITALIZATION_SUPPORT ++ retval = combine_two_entries(hdrp, oldp, newp); ++#else /* NO_CAPITALIZATION_SUPPORT */ ++ if((oldp->flagfield &(CAPTYPEMASK | MOREVARIANTS)) ++ == (ALLCAPS | MOREVARIANTS)) ++ { ++ while(oldp->flagfield & MOREVARIANTS) ++ { ++ oldp = oldp->next; ++ retval = combine_two_entries(hdrp, oldp, newp); ++ if(retval != 0) /* Did we combine them? */ ++ break; ++ } ++ } ++ else ++ retval = combine_two_entries(hdrp, oldp, newp); ++ if(retval == 0) ++ { ++ /* ++ ** Couldn't combine the two entries. Add a new variant. For ++ ** ease, we'll stick it right behind the header, rather than ++ ** at the end of the list. ++ */ ++ forcevheader(hdrp, oldp, newp); ++ tdent = (struct dent *) malloc (sizeof (struct dent)); ++ if(tdent == NULL) ++ { ++ (void) fprintf (stderr, MAKEDENT_C_NO_WORD_SPACE, newp->word); ++ return -1; ++ } ++ *tdent = *newp; ++ tdent->next = hdrp->next; ++ hdrp->next = tdent; ++ tdent->flagfield |= (hdrp->flagfield & MOREVARIANTS); ++ hdrp->flagfield |= MOREVARIANTS; ++ combineaffixes(hdrp, newp); ++ hdrp->flagfield |= (newp->flagfield & KEEP); ++ if(captype(newp->flagfield) == FOLLOWCASE) ++ tdent->word = newp->word; ++ else ++ { ++ tdent->word = NULL; ++ free(newp->word); /* newp->word isn't needed */ ++ } ++ } ++#endif /* NO_CAPITALIZATION_SUPPORT */ ++ return retval; ++} ++ ++#ifndef NO_CAPITALIZATION_SUPPORT ++/* ++** The following routine implements steps 3a and 3b in the commentary ++** for "combinecaps". ++*/ ++Local void ++forcevheader( ++ register struct dent * hdrp, ++ struct dent * oldp, ++ struct dent * newp) ++{ ++ ++ if((hdrp->flagfield &(CAPTYPEMASK | MOREVARIANTS)) == ALLCAPS ++ && ((oldp->flagfield ^ newp->flagfield) & KEEP) == 0) ++ return; /* Caller will set MOREVARIANTS */ ++ else if((hdrp->flagfield &(CAPTYPEMASK | MOREVARIANTS)) ++ != (ALLCAPS | MOREVARIANTS)) ++ (void) addvheader(hdrp); ++} ++#endif /* NO_CAPITALIZATION_SUPPORT */ ++ ++/* ++** This routine implements steps 4 and 5 of the commentary for "combinecaps". ++** ++** Returns 1 if newp can be discarded, 0 if nothing done. ++*/ ++Local int ++combine_two_entries( ++ struct dent *hdrp, /*(Possible) header of variant chain */ ++ register struct dent *oldp, /* Pre-existing dictionary entry */ ++ register struct dent *newp) /* Entry to possibly combine */ ++{ ++ ++ if(acoversb(oldp, newp)) ++ { ++ /* newp is superfluous. Drop it, preserving affixes and keep flag */ ++ combineaffixes(oldp, newp); ++ oldp->flagfield |= (newp->flagfield & KEEP); ++ hdrp->flagfield |= (newp->flagfield & KEEP); ++ free(newp->word); ++ return 1; ++ } ++ else if(acoversb(newp, oldp)) ++ { ++ /* ++ ** oldp is superfluous. Replace it with newp, preserving affixes and ++ ** the keep flag. ++ */ ++ combineaffixes(newp, oldp); ++#ifdef NO_CAPITALIZATION_SUPPORT ++ newp->flagfield |= (oldp->flagfield & KEEP); ++#else /* NO_CAPITALIZATION_SUPPORT */ ++ newp->flagfield |= (oldp->flagfield & (KEEP | MOREVARIANTS)); ++#endif /* NO_CAPITALIZATION_SUPPORT */ ++ hdrp->flagfield |= (newp->flagfield & KEEP); ++ newp->next = oldp->next; ++ /* ++ ** We really want to free oldp->word, but that might be part of ++ ** "hashstrings". So we'll futz around to arrange things so we can ++ ** free newp->word instead. This depends very much on the fact ++ ** that both words are the same length. ++ */ ++ if(oldp->word != NULL) ++ (void) strcpy (oldp->word, newp->word); ++ free(newp->word); /* No longer needed */ ++ newp->word = oldp->word; ++ *oldp = *newp; ++#ifndef NO_CAPITALIZATION_SUPPORT ++ /* We may need to add a header if newp is followcase */ ++ if(captype(newp->flagfield) == FOLLOWCASE ++ && (hdrp->flagfield & (CAPTYPEMASK | MOREVARIANTS)) ++ != (ALLCAPS | MOREVARIANTS)) ++ (void) addvheader (hdrp); ++#endif /* NO_CAPITALIZATION_SUPPORT */ ++ return 1; ++ } ++ else ++ return 0; ++} ++ ++/* ++** Determine if enta covers entb, according to the rules in steps 4 and 5 ++** of the commentary for "combinecaps". ++*/ ++Local int ++acoversb( ++ register struct dent * enta, /* "A" in the rules */ ++ register struct dent * entb) /* "B" in the rules */ ++{ ++ int subset; /* NZ if entb is a subset of enta */ ++ ++ if((subset = issubset(entb, enta)) != 0) ++ { ++ /* entb is a subset of enta; thus enta might cover entb */ ++ if(((enta->flagfield ^ entb->flagfield) & KEEP) != 0 ++ && (enta->flagfield & KEEP) == 0) /* Inverse of condition (4b) */ ++ return 0; ++ } ++ else ++ { ++ /* not a subset; KEEP flags must match exactly(both (4a) and (4b)) */ ++ if(((enta->flagfield ^ entb->flagfield) & KEEP) != 0) ++ return 0; ++ } ++ ++ /* Rules(4a) and (4b) are satisfied; check for capitalization match */ ++#ifdef NO_CAPITALIZATION_SUPPORT ++#ifdef lint ++ return subset; /* Just so it gets used */ ++#else /* lint */ ++ return 1; /* All words match */ ++#endif /* lint */ ++#else /* NO_CAPITALIZATION_SUPPORT */ ++ if(((enta->flagfield ^ entb->flagfield) & CAPTYPEMASK) == 0) ++ { ++ if(captype(enta->flagfield) != FOLLOWCASE /* Condition (4c) */ ++ || strcmp(enta->word, entb->word) == 0) ++ return 1; /* Perfect match */ ++ else ++ return 0; ++ } ++ else if(subset == 0) /* No flag subset, refuse */ ++ return 0; /* ..near matches */ ++ else if(captype(entb->flagfield) == ALLCAPS) ++ return 1; ++ else if(captype(enta->flagfield) == ANYCASE ++ && captype(entb->flagfield) == CAPITALIZED) ++ return 1; ++ else ++ return 0; ++#endif /* NO_CAPITALIZATION_SUPPORT */ ++} ++ ++Public void ++upcase(register ichar_t * s) ++{ ++ ++ while(*s) ++ { ++ *s = mytoupper(*s); ++ s++; ++ } ++} ++ ++Public void ++lowcase(register ichar_t * s) ++{ ++ ++ while(*s) ++ { ++ *s = mytolower(*s); ++ s++; ++ } ++} ++ ++/* ++ * Upcase variant that works on normal strings. Note that it is a lot ++ * slower than the normal upcase. The input must be in canonical form. ++ */ ++Public void ++chupcase(char * s) ++{ ++ ichar_t * is; ++ ++ is = strtosichar(s, 1); ++ upcase(is); ++ (void) ichartostr (s, is, strlen (s) + 1, 1); ++} ++ ++/* ++** See if one affix field is a subset of another. Returns NZ if ent1 ++** is a subset of ent2. The KEEP flag is not taken into consideration. ++*/ ++Local int ++issubset( ++ register struct dent * ent1, ++ register struct dent * ent2) ++{ ++/* The following is really testing for MASKSIZE > 1, but cpp can't do that */ ++#if MASKBITS > 32 ++ register int flagword; ++ ++#ifdef FULLMASKSET ++#define MASKMAX MASKSIZE ++#else ++#define MASKMAX MASKSIZE - 1 ++#endif /* FULLMASKSET */ ++ for(flagword = MASKMAX; --flagword >= 0; ) ++ { ++ if((ent1->mask[flagword] & ent2->mask[flagword]) ++ != ent1->mask[flagword]) ++ return 0; ++ } ++#endif /* MASKBITS > 32 */ ++#ifdef FULLMASKSET ++ return((ent1->mask[MASKSIZE - 1] & ent2->mask[MASKSIZE - 1]) ++ == ent1->mask[MASKSIZE - 1]); ++#else ++ if(((ent1->mask[MASKSIZE - 1] & ent2->mask[MASKSIZE - 1]) ++ ^ ent1->mask[MASKSIZE - 1]) & ~ALLFLAGS) ++ return 0; ++ else ++ return 1; ++#endif /* FULLMASKSET */ ++} ++ ++/* ++** Add ent2's affix flags to ent1. ++*/ ++Local void ++combineaffixes( ++ register struct dent * ent1, ++ register struct dent * ent2) ++{ ++/* The following is really testing for MASKSIZE > 1, but cpp can't do that */ ++#if MASKBITS > 32 ++ register int flagword; ++ ++ if(ent1 == ent2) ++ return; ++ /* MASKMAX is defined in issubset, just above */ ++ for(flagword = MASKMAX; --flagword >= 0; ) ++ ent1->mask[flagword] |= ent2->mask[flagword]; ++#endif /* MASKBITS > 32 */ ++#ifndef FULLMASKSET ++ ent1->mask[MASKSIZE - 1] |= ent2->mask[MASKSIZE - 1] & ~ALLFLAGS; ++#endif ++} ++ ++/* ++** Write out a dictionary entry, including capitalization variants. ++** If onlykeep is true, only those variants with KEEP set will be ++** written. ++*/ ++Public void ++toutent( ++ register FILE * toutfile, ++ struct dent * hent, ++ register int onlykeep) ++{ ++#ifdef NO_CAPITALIZATION_SUPPORT ++ if(!onlykeep || (hent->flagfield & KEEP)) ++ toutword(toutfile, hent->word, hent); ++#else ++ register struct dent * cent; ++ ichar_t wbuf[INPUTWORDLEN + MAXAFFIXLEN]; ++ ++ cent = hent; ++ if(strtoichar(wbuf, cent->word, INPUTWORDLEN, 1)) ++ (void) fprintf(stderr, WORD_TOO_LONG (cent->word)); ++ for( ; ; ) ++ { ++ if(!onlykeep || (cent->flagfield & KEEP)) ++ { ++ switch(captype (cent->flagfield)) ++ { ++ case ANYCASE: ++ lowcase(wbuf); ++ toutword(toutfile, ichartosstr (wbuf, 1), cent); ++ break; ++ case ALLCAPS: ++ if((cent->flagfield & MOREVARIANTS) == 0 || cent != hent) ++ { ++ upcase(wbuf); ++ toutword(toutfile, ichartosstr (wbuf, 1), cent); ++ } ++ break; ++ case CAPITALIZED: ++ lowcase(wbuf); ++ wbuf[0] = mytoupper(wbuf[0]); ++ toutword(toutfile, ichartosstr (wbuf, 1), cent); ++ break; ++ case FOLLOWCASE: ++ toutword(toutfile, cent->word, cent); ++ break; ++ } ++ } ++ if(cent->flagfield & MOREVARIANTS) ++ cent = cent->next; ++ else ++ break; ++ } ++#endif ++} ++ ++Local void ++toutword( ++ register FILE * toutfile, ++ char * word, ++ register struct dent * cent) ++{ ++ register int bit; ++ ++ has_marker = False; ++ (void) fprintf (toutfile, "%s", word); ++ for(bit = 0; bit < LARGESTFLAG; bit++) ++ { ++ if(TSTMASKBIT(cent->mask, bit)) ++ flagout(toutfile, BITTOCHAR (bit)); ++ } ++ (void) fprintf (toutfile, "\n"); ++} ++ ++Local void ++flagout( ++ register FILE * toutfile, ++ int flag) ++{ ++ if(!has_marker) ++ (void) putc(hashheader.flagmarker, toutfile); ++ has_marker = True; ++ (void) putc (flag, toutfile); ++} ++ ++/* ++ * If the string under the given pointer begins with a string character, ++ * return the length of that "character". If not, return 0. ++ * May be called any time, but it's best if "isstrstart" is first ++ * used to filter out unnecessary calls. ++ * ++ * As a side effect, "laststringch" is set to the number of the string ++ * found, or to -1 if none was found. This can be useful for such things ++ * as case conversion. ++ */ ++Public int ++stringcharlen( ++ char * bufp, ++ int canonical) /* NZ if input is in canonical form */ ++{ ++#ifdef SLOWMULTIPLY ++ static char * sp[MAXSTRINGCHARS]; ++ static int m_inited = 0; ++#endif /* SLOWMULTIPLY */ ++ register char * bufcur; ++ register char * stringcur; ++ register int stringno; ++ register int lowstringno; ++ register int highstringno; ++ int dupwanted; ++ ++#ifdef SLOWMULTIPLY ++ if(!m_inited) ++ { ++ m_inited = 1; ++ for(stringno = 0; stringno < MAXSTRINGCHARS; stringno++) ++ sp[stringno] = &hashheader.stringchars[stringno][0]; ++ } ++#endif /* SLOWMULTIPLY */ ++ lowstringno = 0; ++ highstringno = hashheader.nstrchars - 1; ++ dupwanted = canonical ? 0 : defdupchar; ++ while(lowstringno <= highstringno) ++ { ++ stringno = (lowstringno + highstringno) >> 1; ++#ifdef SLOWMULTIPLY ++ stringcur = sp[stringno]; ++#else /* SLOWMULTIPLY */ ++ stringcur = &hashheader.stringchars[stringno][0]; ++#endif /* SLOWMULTIPLY */ ++ bufcur = bufp; ++ while(*stringcur) ++ { ++#ifdef NO8BIT ++ if(((*bufcur++ ^ *stringcur) & 0x7F) != 0) ++#else /* NO8BIT */ ++ if(*bufcur++ != *stringcur) ++#endif /* NO8BIT */ ++ break; ++ /* ++ ** We can't use autoincrement above because of the ++ ** test below. ++ */ ++ stringcur++; ++ } ++ if(*stringcur == '\0') ++ { ++ if(hashheader.dupnos[stringno] == dupwanted) ++ { ++ /* We have a match */ ++ laststringch = hashheader.stringdups[stringno]; ++#ifdef SLOWMULTIPLY ++ return stringcur - sp[stringno]; ++#else /* SLOWMULTIPLY */ ++ return stringcur - &hashheader.stringchars[stringno][0]; ++#endif /* SLOWMULTIPLY */ ++ } ++ else ++ --stringcur; ++ } ++ /* No match - choose which side to search on */ ++#ifdef NO8BIT ++ if((*--bufcur & 0x7F) <(*stringcur & 0x7F)) ++ highstringno = stringno - 1; ++ else if((*bufcur & 0x7F) >(*stringcur & 0x7F)) ++ lowstringno = stringno + 1; ++#else /* NO8BIT */ ++ if(*--bufcur < *stringcur) ++ highstringno = stringno - 1; ++ else if(*bufcur > *stringcur) ++ lowstringno = stringno + 1; ++#endif /* NO8BIT */ ++ else if(dupwanted < hashheader.dupnos[stringno]) ++ highstringno = stringno - 1; ++ else ++ lowstringno = stringno + 1; ++ } ++ laststringch = -1; ++ return 0; /* Not a string character */ ++} ++ ++/* ++ * Convert an external string to an ichar_t string. If necessary, the parity ++ * bit is stripped off as part of the process. ++ * ++ * Returns NZ if the output string overflowed. ++ */ ++Public int ++strtoichar( ++ register ichar_t * out, /* Where to put result */ ++ register char * in, /* String to convert */ ++ int outlen, /* Size of output buffer, *BYTES* */ ++ int canonical) /* NZ if input is in canonical form */ ++{ ++ register int len; /* Length of next character */ ++ ++ outlen /= sizeof(ichar_t); /* Convert to an ichar_t count */ ++ for( ; --outlen > 0 && *in != '\0'; in += len) ++ { ++ if(l1_isstringch(in, len, canonical)) ++ *out++ = SET_SIZE + laststringch; ++ else ++ *out++ = *in & S_NOPARITY; ++ } ++ *out = 0; ++ return outlen <= 0; ++} ++ ++/* ++ * Convert an ichar_t string to an external string. ++ * ++ * WARNING: the resulting string may wind up being longer than the ++ * original. In fact, even the sequence strtoichar->ichartostr may ++ * produce a result longer than the original, because the output form ++ * may use a different string type set than the original input form. ++ * ++ * Returns NZ if the output string overflowed. ++ */ ++Public int ++ichartostr( ++ register char * out, /* Where to put result */ ++ register ichar_t * in, /* String to convert */ ++ int outlen, /* Size of output buffer, bytes */ ++ int canonical) /* NZ for canonical form */ ++{ ++ register unsigned int ch; /* Next character to store */ ++ register unsigned int i; /* Index into duplicates list */ ++ register char * scharp; /* Pointer into a string char */ ++ ++ while(--outlen > 0 && (ch = *in++) != 0) ++ { ++ if(ch < SET_SIZE) ++ *out++ = (char) ch; ++ else ++ { ++ ch -= SET_SIZE; ++ if(!canonical) ++ { ++ for(i = hashheader.nstrchars; --i >= 0; ) ++ { ++ if(hashheader.dupnos[i] == defdupchar ++ && hashheader.stringdups[i] == ch) ++ { ++ ch = i; ++ break; ++ } ++ } ++ } ++ scharp = hashheader.stringchars[(unsigned) ch]; ++ while((*out++ = *scharp++) != '\0') ++ ; ++ out--; ++ } ++ } ++ *out = '\0'; ++ return outlen <= 0; ++} ++ ++/* ++ * Convert a string to an ichar_t, storing the result in a static area. ++ */ ++Public ichar_t * ++strtosichar( ++ char * in, /* String to convert */ ++ int canonical) /* NZ if input is in canonical form */ ++{ ++ static ichar_t out[STRTOSICHAR_SIZE / sizeof(ichar_t)]; ++ ++ if(strtoichar(out, in, sizeof out, canonical)) ++ (void) fprintf(stderr, WORD_TOO_LONG (in)); ++ return out; ++} ++ ++/* ++ * Convert an ichar_t to a string, storing the result in a static area. ++ */ ++Public char * ++ichartosstr( ++ ichar_t * in, /* Internal string to convert */ ++ int canonical) /* NZ for canonical conversion */ ++{ ++ static char out[ICHARTOSSTR_SIZE]; ++ ++ if(ichartostr(out, in, sizeof out, canonical)) ++ (void) fprintf(stderr, WORD_TOO_LONG (out)); ++ return out; ++} ++ ++/* ++ * Convert a single ichar to a printable string, storing the result in ++ * a static area. ++ */ ++Public char * ++printichar(int in) ++{ ++ static char out[MAXSTRINGCHARLEN + 1]; ++ ++ if(in < SET_SIZE) ++ { ++ out[0] = (char) in; ++ out[1] = '\0'; ++ } ++ else ++ (void) strcpy(out, hashheader.stringchars[(unsigned) in - SET_SIZE]); ++ return out; ++} ++ ++#ifndef ICHAR_IS_CHAR ++/* ++ * Copy an ichar_t. ++ */ ++Public ichar_t * ++icharcpy( ++ register ichar_t * out, /* Destination */ ++ register ichar_t * in) /* Source */ ++{ ++ ichar_t * origout; /* Copy of destination for return */ ++ ++ origout = out; ++ while((*out++ = *in++) != 0) ++ ; ++ return origout; ++} ++ ++/* ++ * Return the length of an ichar_t. ++ */ ++Public int ++icharlen(register ichar_t * in) /* String to count */ ++{ ++ register int len; /* Length so far */ ++ ++ for(len = 0; *in++ != 0; len++) ++ ; ++ return len; ++} ++ ++/* ++ * Compare two ichar_t's. ++ */ ++Public int ++icharcmp( ++ register ichar_t * s1, ++ register ichar_t * s2) ++{ ++ ++ while(*s1 != 0) ++ { ++ if(*s1++ != *s2++) ++ return *--s1 - *--s2; ++ } ++ return *s1 - *s2; ++} ++ ++/* ++ * Strncmp for two ichar_t's. ++ */ ++Public int ++icharncmp( ++ register ichar_t * s1, ++ register ichar_t * s2, ++ register int n) ++{ ++ ++ while(--n >= 0 && *s1 != 0) ++ { ++ if(*s1++ != *s2++) ++ return *--s1 - *--s2; ++ } ++ if(n < 0) ++ return 0; ++ else ++ return *s1 - *s2; ++} ++ ++#endif /* ICHAR_IS_CHAR */ ++ ++Public int ++findfiletype( ++ char * name, /* Name to look up in suffix table */ ++ int searchnames, /* NZ to search name field of table */ ++ int * deformatter) /* Where to set deformatter type */ ++{ ++ char * cp; /* Pointer into suffix list */ ++ int cplen; /* Length of current suffix */ ++ register int i; /* Index into type table */ ++ int len; /* Length of the name */ ++ ++ /* ++ * Note: for now, the deformatter is set to 1 for tex, 0 for nroff. ++ * Further, we assume that it's one or the other, so that a test ++ * for tex is sufficient. This needs to be generalized. ++ */ ++ len = strlen(name); ++ if(searchnames) ++ { ++ for(i = 0; i < hashheader.nstrchartype; i++) ++ { ++ if(strcmp(name, chartypes[i].name) == 0) ++ { ++ if(deformatter != NULL) ++ *deformatter = ++ (strcmp (chartypes[i].deformatter, "tex") == 0); ++ return i; ++ } ++ } ++ } ++ for(i = 0; i < hashheader.nstrchartype; i++) ++ { ++ for(cp = chartypes[i].suffixes; *cp != '\0'; cp += cplen + 1) ++ { ++ cplen = strlen(cp); ++ if(len >= cplen && strcmp(&name[len - cplen], cp) == 0) ++ { ++ if(deformatter != NULL) ++ *deformatter = ++ (strcmp (chartypes[i].deformatter, "tex") == 0); ++ return i; ++ } ++ } ++ } ++ return -1; ++} ++ ++Public char * ++mypath_rindex(char const *str, char c) ++{ ++ register char *x; ++ ++ x = (char *)str + strlen(str); ++ ++ while(x >= str) ++ { ++ if(*x == '\\' || *x == '/' || *x == ':') ++ return(NULL); ++ else if(*x == c) ++ return(x); ++ else ++ x--; ++ } ++ return(NULL); ++} +diff -Nur vim60am.old/src/spell/msgs.h vim60am/src/spell/msgs.h +--- vim60am.old/src/spell/msgs.h Thu Jan 1 01:00:00 1970 ++++ vim60am/src/spell/msgs.h Wed Jun 27 19:16:52 2001 +@@ -0,0 +1,278 @@ ++/* ++ * $Id$ ++ * ++ * Copyright 1992, 1993, Geoff Kuenning, Granada Hills, CA ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All modifications to the source code must be clearly marked as ++ * such. Binary redistributions based on modified source code ++ * must be clearly marked as modified versions in the documentation ++ * and/or other materials provided with the distribution. ++ * 4. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgment: ++ * This product includes software developed by Geoff Kuenning and ++ * other unpaid contributors. ++ * 5. The name of Geoff Kuenning may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY GEOFF KUENNING AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL GEOFF KUENNING OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++ ++/* ++ * Messages header file. ++ * ++ * This file contains all text strings that are written by any of the ++ * C programs in the ispell package. The strings are collected here so that ++ * you can have the option of translating them into your local language for ++ * the benefit of your users. ++ * ++ * Anyone who goes to the effort of making a translation may wish to return ++ * the translated strings to me, geoff@ITcorp.com, so that I can include ++ * them in a later distribution under #ifdef control. ++ * ++ * Besides the strings in this header file, you may also want to translate ++ * the strings in version.h, which give the version and copyright information. ++ * However, any translation of these strings MUST accurately preserve the ++ * legal rights under international law; you may wish to consult a lawyer ++ * about this since you will be responsible for the results of any ++ * incorrect translation. ++ * ++ * Most of the strings below are simple printf format strings. If the printf ++ * takes more than one parameter, the string is given as a parameterized ++ * macro in case your local language needs a different word order. ++ */ ++ ++/* ++ * $Log$ ++ * Revision 1.31 1994/12/27 23:08:57 geoff ++ * Add a message to be issued if a word contains illegal characters. ++ * ++ * Revision 1.30 1994/10/25 05:46:40 geoff ++ * Improve a couple of error messages relating to affix flags. ++ * ++ * Revision 1.29 1994/10/04 03:46:23 geoff ++ * Add a missing carriage return in the help message ++ * ++ * Revision 1.28 1994/09/16 05:07:00 geoff ++ * Add the BAD_FLAG message, and start a sentence in another message with ++ * an uppercase letter. ++ * ++ * Revision 1.27 1994/07/28 05:11:38 geoff ++ * Log message for previous revision: add BHASH_C_ZERO_COUNT. ++ * ++ * Revision 1.26 1994/07/28 04:53:49 geoff ++ * ++ * Revision 1.25 1994/05/24 04:54:36 geoff ++ * Add error messages for affix-flag checking. ++ * ++ * Revision 1.24 1994/01/25 07:12:42 geoff ++ * Get rid of all old RCS log lines in preparation for the 3.1 release. ++ * ++ */ ++ ++/* ++ * The following strings are used in numerous places: ++ */ ++#define BAD_FLAG "\nIllegal affix flag character '%c'\n" ++#define CANT_OPEN "Can't open %s" ++#define CANT_CREATE "Can't create %s\n" ++#define WORD_TOO_LONG(w) "\nWord '%s' too long at line %d of %s, truncated\n", \ ++ w, __LINE__, __FILE__ ++ ++/* ++ * The following strings are used in buildhash.c: ++ */ ++#define BHASH_C_NO_DICT "No dictionary (%s)\n" ++#define BHASH_C_NO_COUNT "No count file\n" ++#define BHASH_C_BAD_COUNT "Bad count file\n" ++#define BHASH_C_ZERO_COUNT "No words in dictionary\n" ++ /* I think this message looks better when it's nearly 80 characters wide, ++ * thus the ugly formatting in the next two defines. GK 9-87 */ ++#define BHASH_C_BAFF_1(max, excess) \ ++ " Warning: this language table may exceed the maximum total affix length\nof %d by up to %d bytes. You should either increase MAXAFFIXLEN in config.X\nor shorten your largest affix/strip string difference. (This is the\n", \ ++ max, excess ++#define BHASH_C_BAFF_2 \ ++ "difference between the affix length and the strip length in a given\nreplacement rule, or the affix length if there is no strip string\nin that rule.)\n" ++#define BHASH_C_OVERFLOW "Hash table overflowed by %d words\n" ++#define BHASH_C_CANT_OPEN_DICT "Can't open dictionary\n" ++#define BHASH_C_NO_SPACE "Couldn't allocate hash table\n" ++#define BHASH_C_COLLISION_SPACE "\ncouldn't allocate space for collision\n" ++#define BHASH_C_COUNTING "Counting words in dictionary ...\n" ++#define BHASH_C_WORD_COUNT "\n%d words\n" ++#define BHASH_C_USAGE "Usage: buildhash [-s] dict-file aff-file hash-file\n\tbuildhash -c count aff-file\n" ++ ++/* ++ * The following strings are used in correct.c: ++ */ ++#define CORR_C_HELP_1 "Whenever a word is found that is not in the dictionary,\n" ++#define CORR_C_HELP_2 "it is printed on the first line of the screen. If the dictionary\n" ++#define CORR_C_HELP_3 "contains any similar words, they are listed with a number\n" ++#define CORR_C_HELP_4 "next to each one. You have the option of replacing the word\n" ++#define CORR_C_HELP_5 "completely, or choosing one of the suggested words.\n" ++ /* You may add HELP_6 through HELP_9 if your language needs more lines */ ++#define CORR_C_HELP_6 "" ++#define CORR_C_HELP_7 "" ++#define CORR_C_HELP_8 "" ++#define CORR_C_HELP_9 "" ++#define CORR_C_HELP_COMMANDS "\nCommands are:\n\n" ++#define CORR_C_HELP_R_CMD "R Replace the misspelled word completely.\n" ++#define CORR_C_HELP_BLANK "Space Accept the word this time only.\n" ++#define CORR_C_HELP_A_CMD "A Accept the word for the rest of this session.\n" ++#define CORR_C_HELP_I_CMD "I Accept the word, and put it in your private dictionary.\n" ++#define CORR_C_HELP_U_CMD "U Accept and add lowercase version to private dictionary.\n" ++#define CORR_C_HELP_0_CMD "0-n Replace with one of the suggested words.\n" ++#define CORR_C_HELP_L_CMD "L Look up words in system dictionary.\n" ++#define CORR_C_HELP_X_CMD "X Write the rest of this file, ignoring misspellings,\n and start next file.\n" ++#define CORR_C_HELP_Q_CMD "Q Quit immediately. Asks for confirmation.\n Leaves file unchanged.\n" ++#define CORR_C_HELP_BANG "! Shell escape.\n" ++#define CORR_C_HELP_REDRAW "^L Redraw screen.\n" ++#define CORR_C_HELP_SUSPEND "^Z Suspend program.\n" ++#define CORR_C_HELP_HELP "? Show this help screen.\n" ++#define CORR_C_HELP_TYPE_SPACE "-- Type space to continue --" ++ ++#define CORR_C_FILE_LABEL " File: %s" ++#define CORR_C_READONLY "[READONLY]" ++#define CORR_C_MINI_MENU "[SP] R)epl A)ccept I)nsert L)ookup U)ncap Q)uit e(X)it or ? for help\n" ++#define CORR_C_CONFIRM_QUIT "Are you sure you want to throw away your changes? " ++#define CORR_C_REPLACE_WITH "Replace with: " ++#define CORR_C_LOOKUP_PROMPT "Lookup string ('*' is wildcard): " ++#define CORR_C_MORE_PROMPT "-- more --" ++#define CORR_C_BLANK_MORE " " ++#define CORR_C_END_LOOK "--end--" ++ ++/* ++ * The following strings are used in defmt.c: ++ */ ++#define DEFMT_C_TEX_MATH_ERROR "****ERROR in parsing TeX math mode!\n" ++#define DEFMT_C_LR_MATH_ERROR "***ERROR in LR to math-mode switch.\n" ++ ++/* ++ * The following strings are used in icombine.c: ++ */ ++#define ICOMBINE_C_BAD_TYPE "icombine: unrecognized formatter type '%s'\n" ++#define ICOMBINE_C_USAGE "Usage: icombine [-T suffix] [aff-file] < wordlist\n" ++ ++/* ++ * The following strings are used in ispell.c: ++ */ ++#define ISPELL_C_USAGE1 "Usage: %s [-dfile | -pfile | -wchars | -Wn | -t | -n | -x | -b | -S | -B | -C | -P | -m | -Lcontext | -M | -N | -Ttype | -V] file .....\n" ++#define ISPELL_C_USAGE2 " %s [-dfile | -pfile | -wchars | -Wn | -t | -n | -Ttype] -l\n" ++#ifndef USG ++#define ISPELL_C_USAGE3 " %s [-dfile | -pfile | -ffile | -Wn | -t | -n | -s | -B | -C | -P | -m | -Ttype] {-a | -A}\n" ++#else ++#define ISPELL_C_USAGE3 " %s [-dfile | -pfile | -ffile | -Wn | -t | -n | -B | -C | -P | -m | -Ttype] {-a | -A}\n" ++#endif ++#define ISPELL_C_USAGE4 " %s [-dfile] [-wchars | -Wn] -c\n" ++#define ISPELL_C_USAGE5 " %s [-dfile] [-wchars] -e[1-4]\n" ++#define ISPELL_C_USAGE6 " %s [-dfile] [-wchars] -D\n" ++#define ISPELL_C_USAGE7 " %s -v\n" ++#define ISPELL_C_TEMP_DISAPPEARED "temporary file disappeared (%s)\n" ++#define ISPELL_C_BAD_TYPE "ispell: unrecognized formatter type '%s'\n" ++#define ISPELL_C_NO_FILE "ispell: specified file does not exist\n" ++#define ISPELL_C_NO_FILES "ispell: specified files do not exist\n" ++#define ISPELL_C_CANT_WRITE "Warning: Can't write to %s\n" ++#define ISPELL_C_OPTIONS_ARE "Compiled-in options:\n" ++#ifdef MSDOS ++#define ISPELL_C_NO_OPTIONS_SPACE "ispell: no memory to read default options\n" ++#endif ++ ++/* ++ * The following strings are used in lookup.c: ++ */ ++#define LOOKUP_C_CANT_READ "Trouble reading hash table %s" ++#define LOOKUP_C_NULL_HASH "Null hash table %s" ++#define LOOKUP_C_SHORT_HASH(name, gotten, wanted) \ ++ "Truncated hash table %s: got %d bytes, expected %d", \ ++ name, gotten, wanted ++#define LOOKUP_C_BAD_MAGIC(name, wanted, gotten) \ ++ "Illegal format hash table %s - expected magic 0x%x, got 0x%x", \ ++ name, wanted, gotten ++#define LOOKUP_C_BAD_MAGIC2(name, wanted, gotten) \ ++ "Illegal format hash table %s - \nexpected magic2 0x%x, got 0x%x", \ ++ name, wanted, gotten ++#define LOOKUP_C_BAD_OPTIONS(gotopts, gotchars, gotlen, wantedopts, wantedchars, wantedlen) \ ++ "Hash table options don't agree with buildhash - 0x%x/%d/%d vs. 0x%x/%d/%d", \ ++ gotopts, gotchars, gotlen, \ ++ wantedopts, wantedchars, wantedlen ++#define LOOKUP_C_NO_HASH_SPACE "Couldn't allocate space for hash table" ++#define LOOKUP_C_BAD_FORMAT "Illegal format hash table" ++#define LOOKUP_C_NO_LANG_SPACE "Couldn't allocate space for language tables" ++ ++/* ++ * The following strings are used in makedent.c: ++ */ ++#define MAKEDENT_C_NO_WORD_SPACE "\nCouldn't allocate space for word '%s'\n" ++#define MAKEDENT_C_BAD_WORD_CHAR "\nWord '%s' contains illegal characters\n" ++ ++/* ++ * The following strings are used in parse.y: ++ */ ++#define PARSE_Y_8_BIT "Eighth bit ignored (recompile ispell without NO8BIT)" ++#define PARSE_Y_NO_WORD_STRINGS "wordchars statement may not specify string characters" ++#define PARSE_Y_UNMATCHED "Unmatched charset lengths" ++#define PARSE_Y_NO_BOUNDARY_STRINGS "boundarychars statement may not specify string characters" ++#define PARSE_Y_LONG_STRING "String character is too long" ++#define PARSE_Y_NULL_STRING "String character must have nonzero length" ++#define PARSE_Y_MANY_STRINGS "Too many string characters" ++#define PARSE_Y_NO_SUCH_STRING "No such string character" ++#define PARSE_Y_MULTIPLE_STRINGS "Alternate string character was already defined" ++#define PARSE_Y_LENGTH_MISMATCH "Upper and lower versions of string character must be same length" ++#define PARSE_Y_WRONG_NROFF "Incorrect character count in nroffchars statement" ++#define PARSE_Y_WRONG_TEX "Incorrect character count in TeXchars statement" ++#define PARSE_Y_DOUBLE_COMPOUND "Compoundwords option may only appear once" ++#define PARSE_Y_LONG_FLAG "Flag must be single character" ++#define PARSE_Y_BAD_FLAG "Flag must be alphabetic" ++#define PARSE_Y_DUP_FLAG "Duplicate flag" ++#define PARSE_Y_NO_SPACE "Out of memory" ++#define PARSE_Y_NEED_BLANK "Single characters must be separated by a blank" ++#define PARSE_Y_MANY_CONDS "Too many conditions; 8 maximum" ++#define PARSE_Y_EOF "Unexpected EOF in quoted string" ++#define PARSE_Y_LONG_QUOTE "Quoted string too long, max 256 characters" ++#define PARSE_Y_ERROR_FORMAT(file, lineno, error) \ ++ "%s line %d: %s\n", file, lineno, error ++#define PARSE_Y_MALLOC_TROUBLE "yyopen: trouble allocating memory\n" ++#define PARSE_Y_UNGRAB_PROBLEM "Internal error: ungrab buffer overflow" ++#define PARSE_Y_BAD_DEFORMATTER "Deformatter must be either 'nroff' or 'tex'" ++#define PARSE_Y_BAD_NUMBER "Illegal digit in number" ++ ++/* ++ * The following strings are used in term.c: ++ */ ++#define TERM_C_SMALL_SCREEN "Screen too small: need at least %d lines\n" ++#define TERM_C_NO_BATCH "Can't deal with non-interactive use yet.\n" ++#define TERM_C_CANT_FORK "Couldn't fork, try later.\n" ++#define TERM_C_TYPE_SPACE "\n-- Type space to continue --" ++ ++/* ++ * The following strings are used in tree.c: ++ */ ++#define TREE_C_CANT_UPDATE "Warning: Cannot update personal dictionary (%s)\n" ++#define TREE_C_NO_SPACE "Ran out of space for personal dictionary\n" ++#define TREE_C_TRY_ANYWAY "Continuing anyway (with reduced performance).\n" ++ ++/* ++ * The following strings are used in unsq.c: ++ */ ++#define UNSQ_C_BAD_COUNT "Illegal count character 0x%x\n" ++#define UNSQ_C_SURPRISE_EOF "Unexpected EOF\n" +diff -Nur vim60am.old/src/spell/tgood.c vim60am/src/spell/tgood.c +--- vim60am.old/src/spell/tgood.c Thu Jan 1 01:00:00 1970 ++++ vim60am/src/spell/tgood.c Wed Jun 27 19:16:55 2001 +@@ -0,0 +1,654 @@ ++/* ++ * Copyright 1987, 1988, 1989, 1992, 1993, Geoff Kuenning, Granada Hills, CA ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All modifications to the source code must be clearly marked as ++ * such. Binary redistributions based on modified source code ++ * must be clearly marked as modified versions in the documentation ++ * and/or other materials provided with the distribution. ++ * 4. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgment: ++ * This product includes software developed by Geoff Kuenning and ++ * other unpaid contributors. ++ * 5. The name of Geoff Kuenning may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY GEOFF KUENNING AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL GEOFF KUENNING OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++/* ++ * Table-driven version of good.c. ++ * ++ * Geoff Kuenning, July 1987 ++ */ ++ ++/* ++ * $Log$ ++ * Revision 1.32 1994/11/02 06:56:16 geoff ++ * Remove the anyword feature, which I've decided is a bad idea. ++ * ++ * Revision 1.31 1994/10/25 05:46:25 geoff ++ * Add support for the FF_ANYWORD (affix applies to all words, even if ++ * flag bit isn't set) flag option. ++ * ++ * Revision 1.30 1994/05/24 06:23:08 geoff ++ * Don't create a hit if "allhits" is clear and capitalization ++ * mismatches. This cures a bug where a word could be in the dictionary ++ * and yet not found. ++ * ++ * Revision 1.29 1994/05/17 06:44:21 geoff ++ * Add support for controlled compound formation and the COMPOUNDONLY ++ * option to affix flags. ++ * ++ * Revision 1.28 1994/01/25 07:12:13 geoff ++ * Get rid of all old RCS log lines in preparation for the 3.1 release. ++ * ++ */ ++ ++#include ++#include "ispell.h" ++ ++Global void chk_aff (ichar_t * word, ichar_t * ucword, int len, ++ int ignoreflagbits, int allhits, int pfxopts, int sfxopts); ++Local void pfx_list_chk (ichar_t * word, ichar_t * ucword, ++ int len, int optflags, int sfxopts, struct flagptr * ind, ++ int ignoreflagbits, int allhits); ++Local void chk_suf (ichar_t * word, ichar_t * ucword, int len, ++ int optflags, struct flagent * pfxent, int ignoreflagbits, ++ int allhits); ++Local void suf_list_chk (ichar_t * word, ichar_t * ucword, int len, ++ struct flagptr * ind, int optflags, struct flagent * pfxent, ++ int ignoreflagbits, int allhits); ++Global int expand_pre (char * croot, ichar_t * rootword, ++ MASKTYPE mask[], int option, char * extra); ++Local int pr_pre_expansion (char * croot, ichar_t * rootword, ++ struct flagent * flent, MASKTYPE mask[], int option, ++ char * extra); ++Global int expand_suf (char * croot, ichar_t * rootword, ++ MASKTYPE mask[], int optflags, int option, char * extra); ++Local int pr_suf_expansion (char * croot, ichar_t * rootword, ++ struct flagent * flent, int option, char * extra); ++Local void forcelc (ichar_t * dst, int len); ++ ++/* Check possible affixes */ ++Public void ++chk_aff ( ++ ichar_t * word, /* Word to be checked */ ++ ichar_t * ucword, /* Upper-case-only copy of word */ ++ int len, /* The length of word/ucword */ ++ int ignoreflagbits, /* Ignore whether affix is legal */ ++ int allhits, /* Keep going after first hit */ ++ int pfxopts, /* Options to apply to prefixes */ ++ int sfxopts) /* Options to apply to suffixes */ ++ { ++ register ichar_t * cp; /* Pointer to char to index on */ ++ struct flagptr * ind; /* Flag index table to test */ ++ ++ pfx_list_chk (word, ucword, len, pfxopts, sfxopts, &pflagindex[0], ++ ignoreflagbits, allhits); ++ cp = ucword; ++ ind = &pflagindex[*cp++]; ++ while (ind->numents == 0 && ind->pu.fp != NULL) ++ { ++ if (*cp == 0) ++ return; ++ if (ind->pu.fp[0].numents) ++ { ++ pfx_list_chk (word, ucword, len, pfxopts, sfxopts, &ind->pu.fp[0], ++ ignoreflagbits, allhits); ++ if (numhits && !allhits && !cflag && !ignoreflagbits) ++ return; ++ } ++ ind = &ind->pu.fp[*cp++]; ++ } ++ pfx_list_chk (word, ucword, len, pfxopts, sfxopts, ind, ignoreflagbits, ++ allhits); ++ if (numhits && !allhits && !cflag && !ignoreflagbits) ++ return; ++ chk_suf (word, ucword, len, sfxopts, (struct flagent *) NULL, ++ ignoreflagbits, allhits); ++ } ++ ++/* Check some prefix flags */ ++Local void ++pfx_list_chk( ++ ichar_t * word, /* Word to be checked */ ++ ichar_t * ucword, /* Upper-case-only word */ ++ int len, /* The length of ucword */ ++ int optflags, /* Options to apply */ ++ int sfxopts, /* Options to apply to suffixes */ ++ struct flagptr * ind, /* Flag index table */ ++ int ignoreflagbits, /* Ignore whether affix is legal */ ++ int allhits) /* Keep going after first hit */ ++ { ++ int cond; /* Condition number */ ++ register ichar_t * cp; /* Pointer into end of ucword */ ++ struct dent * dent; /* Dictionary entry we found */ ++ int entcount; /* Number of entries to process */ ++ register struct flagent * ++ flent; /* Current table entry */ ++ int preadd; /* Length added to tword2 as prefix */ ++ register int tlen; /* Length of tword */ ++ ichar_t tword[INPUTWORDLEN + 4 * MAXAFFIXLEN + 4]; /* Tmp cpy */ ++ ichar_t tword2[sizeof tword]; /* 2nd copy for ins_root_cap */ ++ ++ for (flent = ind->pu.ent, entcount = ind->numents; ++ entcount > 0; flent++, entcount--) ++ { ++ /* ++ * If this is a compound-only affix, ignore it unless we're ++ * looking for that specific thing. ++ */ ++ if ((flent->flagflags & FF_COMPOUNDONLY) != 0 ++ && (optflags & FF_COMPOUNDONLY) == 0) ++ continue; ++ /* ++ * In COMPOUND_CONTROLLED mode, the FF_COMPOUNDONLY bit must ++ * match exactly. ++ */ ++ if (compoundflag == COMPOUND_CONTROLLED ++ && ((flent->flagflags ^ optflags) & FF_COMPOUNDONLY) != 0) ++ continue; ++ /* ++ * See if the prefix matches. ++ */ ++ tlen = len - flent->affl; ++ if (tlen > 0 && (flent->affl == 0 || ++ icharncmp (flent->affix, ucword, flent->affl) == 0) && ++ tlen + flent->stripl >= flent->numconds) ++ { ++ /* ++ * The prefix matches. Remove it, replace it by the "strip" ++ * string (if any), and check the original conditions. ++ */ ++ if (flent->stripl) ++ (void) icharcpy (tword, flent->strip); ++ (void) icharcpy (tword + flent->stripl, ucword + flent->affl); ++ cp = tword; ++ for (cond = 0; cond < flent->numconds; cond++) ++ { ++ if ((flent->conds[*cp++] & (1 << cond)) == 0) ++ break; ++ } ++ if (cond >= flent->numconds) ++ { ++ /* ++ * The conditions match. See if the word is in the ++ * dictionary. ++ */ ++ tlen += flent->stripl; ++ if (cflag) ++ flagpr (tword, BITTOCHAR (flent->flagbit), flent->stripl, ++ flent->affl, -1, 0); ++ else if (ignoreflagbits) ++ { ++ if ((dent = lookup (tword, 1)) != NULL) ++ { ++ cp = tword2; ++ if (flent->affl) ++ { ++ (void) icharcpy (cp, flent->affix); ++ cp += flent->affl; ++ *cp++ = '+'; ++ } ++ preadd = cp - tword2; ++ (void) icharcpy (cp, tword); ++ cp += tlen; ++ if (flent->stripl) ++ { ++ *cp++ = '-'; ++ (void) icharcpy (cp, flent->strip); ++ } ++ (void) ins_root_cap (tword2, word, ++ flent->stripl, preadd, ++ 0, (cp - tword2) - tlen - preadd, ++ dent, flent, (struct flagent *) NULL); ++ } ++ } ++ else if ((dent = lookup (tword, 1)) != NULL ++ && TSTMASKBIT (dent->mask, flent->flagbit)) ++ { ++ if (numhits < MAX_HITS) ++ { ++ hits[numhits].dictent = dent; ++ hits[numhits].prefix = flent; ++ hits[numhits].suffix = NULL; ++ numhits++; ++ } ++ if (!allhits) ++ { ++#ifndef NO_CAPITALIZATION_SUPPORT ++ if (cap_ok (word, &hits[0], len)) ++ return; ++ numhits = 0; ++#else /* NO_CAPITALIZATION_SUPPORT */ ++ return; ++#endif /* NO_CAPITALIZATION_SUPPORT */ ++ } ++ } ++ /* ++ * Handle cross-products. ++ */ ++ if (flent->flagflags & FF_CROSSPRODUCT) ++ chk_suf (word, tword, tlen, sfxopts | FF_CROSSPRODUCT, ++ flent, ignoreflagbits, allhits); ++ } ++ } ++ } ++ } ++ ++/* Check possible suffixes */ ++Local void ++chk_suf( ++ ichar_t * word, /* Word to be checked */ ++ ichar_t * ucword, /* Upper-case-only word */ ++ int len, /* The length of ucword */ ++ int optflags, /* Affix option flags */ ++ struct flagent * pfxent, /* Prefix flag entry if cross-prod */ ++ int ignoreflagbits, /* Ignore whether affix is legal */ ++ int allhits) /* Keep going after first hit */ ++ { ++ register ichar_t * cp; /* Pointer to char to index on */ ++ struct flagptr * ind; /* Flag index table to test */ ++ ++ suf_list_chk (word, ucword, len, &sflagindex[0], optflags, pfxent, ++ ignoreflagbits, allhits); ++ cp = ucword + len - 1; ++ ind = &sflagindex[*cp]; ++ while (ind->numents == 0 && ind->pu.fp != NULL) ++ { ++ if (cp == ucword) ++ return; ++ if (ind->pu.fp[0].numents) ++ { ++ suf_list_chk (word, ucword, len, &ind->pu.fp[0], ++ optflags, pfxent, ignoreflagbits, allhits); ++ if (numhits != 0 && !allhits && !cflag && !ignoreflagbits) ++ return; ++ } ++ ind = &ind->pu.fp[*--cp]; ++ } ++ suf_list_chk (word, ucword, len, ind, optflags, pfxent, ++ ignoreflagbits, allhits); ++ } ++ ++Local void ++suf_list_chk ( ++ ichar_t * word, /* Word to be checked */ ++ ichar_t * ucword, /* Upper-case-only word */ ++ int len, /* The length of ucword */ ++ struct flagptr * ind, /* Flag index table */ ++ int optflags, /* Affix option flags */ ++ struct flagent * pfxent, /* Prefix flag entry if crossonly */ ++ int ignoreflagbits, /* Ignore whether affix is legal */ ++ int allhits) /* Keep going after first hit */ ++{ ++ register ichar_t * cp; /* Pointer into end of ucword */ ++ int cond; /* Condition number */ ++ struct dent * dent; /* Dictionary entry we found */ ++ int entcount; /* Number of entries to process */ ++ register struct flagent * ++ flent; /* Current table entry */ ++ int preadd; /* Length added to tword2 as prefix */ ++ register int tlen; /* Length of tword */ ++ ichar_t tword[INPUTWORDLEN + 4 * MAXAFFIXLEN + 4]; /* Tmp cpy */ ++ ichar_t tword2[sizeof tword]; /* 2nd copy for ins_root_cap */ ++ ++ (void) icharcpy (tword, ucword); ++ for (flent = ind->pu.ent, entcount = ind->numents; ++ entcount > 0; ++ flent++, entcount--) ++ { ++ if ((optflags & FF_CROSSPRODUCT) != 0 ++ && (flent->flagflags & FF_CROSSPRODUCT) == 0) ++ continue; ++ /* ++ * If this is a compound-only affix, ignore it unless we're ++ * looking for that specific thing. ++ */ ++ if ((flent->flagflags & FF_COMPOUNDONLY) != 0 ++ && (optflags & FF_COMPOUNDONLY) == 0) ++ continue; ++ /* ++ * In COMPOUND_CONTROLLED mode, the FF_COMPOUNDONLY bit must ++ * match exactly. ++ */ ++ if (compoundflag == COMPOUND_CONTROLLED ++ && ((flent->flagflags ^ optflags) & FF_COMPOUNDONLY) != 0) ++ continue; ++ /* ++ * See if the suffix matches. ++ */ ++ tlen = len - flent->affl; ++ if (tlen > 0 ++ && (flent->affl == 0 ++ || icharcmp (flent->affix, ucword + tlen) == 0) ++ && tlen + flent->stripl >= flent->numconds) ++ { ++ /* ++ * The suffix matches. Remove it, replace it by the "strip" ++ * string (if any), and check the original conditions. ++ */ ++ (void) icharcpy (tword, ucword); ++ cp = tword + tlen; ++ if (flent->stripl) ++ { ++ (void) icharcpy (cp, flent->strip); ++ tlen += flent->stripl; ++ cp = tword + tlen; ++ } ++ else ++ *cp = '\0'; ++ for (cond = flent->numconds; --cond >= 0; ) ++ { ++ if ((flent->conds[*--cp] & (1 << cond)) == 0) ++ break; ++ } ++ if (cond < 0) ++ { ++ /* ++ * The conditions match. See if the word is in the ++ * dictionary. ++ */ ++ if (cflag) ++ { ++ if (optflags & FF_CROSSPRODUCT) ++ flagpr (tword, BITTOCHAR (pfxent->flagbit), ++ pfxent->stripl, pfxent->affl, ++ BITTOCHAR (flent->flagbit), flent->affl); ++ else ++ flagpr (tword, -1, 0, 0, ++ BITTOCHAR (flent->flagbit), flent->affl); ++ } ++ else if (ignoreflagbits) ++ { ++ if ((dent = lookup (tword, 1)) != NULL) ++ { ++ cp = tword2; ++ if ((optflags & FF_CROSSPRODUCT) ++ && pfxent->affl != 0) ++ { ++ (void) icharcpy (cp, pfxent->affix); ++ cp += pfxent->affl; ++ *cp++ = '+'; ++ } ++ preadd = cp - tword2; ++ (void) icharcpy (cp, tword); ++ cp += tlen; ++ if ((optflags & FF_CROSSPRODUCT) ++ && pfxent->stripl != 0) ++ { ++ *cp++ = '-'; ++ (void) icharcpy (cp, pfxent->strip); ++ cp += pfxent->stripl; ++ } ++ if (flent->stripl) ++ { ++ *cp++ = '-'; ++ (void) icharcpy (cp, flent->strip); ++ cp += flent->stripl; ++ } ++ if (flent->affl) ++ { ++ *cp++ = '+'; ++ (void) icharcpy (cp, flent->affix); ++ cp += flent->affl; ++ } ++ (void) ins_root_cap (tword2, word, ++ (optflags & FF_CROSSPRODUCT) ? pfxent->stripl : 0, ++ preadd, ++ flent->stripl, (cp - tword2) - tlen - preadd, ++ dent, pfxent, flent); ++ } ++ } ++ else if ((dent = lookup (tword, 1)) != NULL ++ && TSTMASKBIT (dent->mask, flent->flagbit) ++ && ((optflags & FF_CROSSPRODUCT) == 0 ++ || TSTMASKBIT (dent->mask, pfxent->flagbit))) ++ { ++ if (numhits < MAX_HITS) ++ { ++ hits[numhits].dictent = dent; ++ hits[numhits].prefix = pfxent; ++ hits[numhits].suffix = flent; ++ numhits++; ++ } ++ if (!allhits) ++ { ++#ifndef NO_CAPITALIZATION_SUPPORT ++ if (cap_ok (word, &hits[0], len)) ++ return; ++ numhits = 0; ++#else /* NO_CAPITALIZATION_SUPPORT */ ++ return; ++#endif /* NO_CAPITALIZATION_SUPPORT */ ++ } ++ } ++ } ++ } ++ } ++} ++ ++/* ++ * Expand a dictionary prefix entry ++ */ ++Public int ++expand_pre( ++ char * croot, /* Char version of rootword */ ++ ichar_t * rootword, /* Root word to expand */ ++ register MASKTYPE mask[], /* Mask bits to expand on */ ++ int option, /* Option, see expandmode */ ++ char * extra) /* Extra info to add to line */ ++{ ++ int entcount; /* No. of entries to process */ ++ int explength; /* Length of expansions */ ++ register struct flagent * ++ flent; /* Current table entry */ ++ ++ for (flent = pflaglist, entcount = numpflags, explength = 0; ++ entcount > 0; flent++, entcount--) ++ { ++ if (TSTMASKBIT (mask, flent->flagbit)) ++ explength += ++ pr_pre_expansion (croot, rootword, flent, mask, option, extra); ++ } ++ return explength; ++} ++ ++/* Print a prefix expansion */ ++Local int ++pr_pre_expansion( ++ char * croot, /* Char version of rootword */ ++ register ichar_t * rootword, /* Root word to expand */ ++ register struct flagent * flent, /* Current table entry */ ++ MASKTYPE mask[], /* Mask bits to expand on */ ++ int option, /* Option, see expandmode */ ++ char * extra) /* Extra info to add to line */ ++{ ++ int cond; /* Current condition number */ ++ register ichar_t * nextc; /* Next case choice */ ++ int tlen; /* Length of tword */ ++ ichar_t tword[INPUTWORDLEN + MAXAFFIXLEN]; /* Temp */ ++ ++ tlen = icharlen (rootword); ++ if (flent->numconds > tlen) ++ return 0; ++ tlen -= flent->stripl; ++ if (tlen <= 0) ++ return 0; ++ tlen += flent->affl; ++ for (cond = 0, nextc = rootword; cond < flent->numconds; cond++) ++ { ++ if ((flent->conds[mytoupper (*nextc++)] & (1 << cond)) == 0) ++ return 0; ++ } ++ /* ++ * The conditions are satisfied. Copy the word, add the prefix, ++ * and make it the proper case. This code is carefully written ++ * to match that ins_cap and cap_ok. Note that the affix, as ++ * inserted, is uppercase. ++ * ++ * There is a tricky bit here: if the root is capitalized, we ++ * want a capitalized result. If the root is followcase, however, ++ * we want to duplicate the case of the first remaining letter ++ * of the root. In other words, "Loved/U" should generate "Unloved", ++ * but "LOved/U" should generate "UNLOved" and "lOved/U" should ++ * produce "unlOved". ++ */ ++ if (flent->affl) ++ { ++ (void) icharcpy (tword, flent->affix); ++ nextc = tword + flent->affl; ++ } ++ (void) icharcpy (nextc, rootword + flent->stripl); ++ if (myupper (rootword[0])) ++ { ++ /* We must distinguish followcase from capitalized and all-upper */ ++ for (nextc = rootword + 1; *nextc; nextc++) ++ { ++ if (!myupper (*nextc)) ++ break; ++ } ++ if (*nextc) ++ { ++ /* It's a followcase or capitalized word. Figure out which. */ ++ for ( ; *nextc; nextc++) ++ { ++ if (myupper (*nextc)) ++ break; ++ } ++ if (*nextc) ++ { ++ /* It's followcase. */ ++ if (!myupper (tword[flent->affl])) ++ forcelc (tword, flent->affl); ++ } ++ else ++ { ++ /* It's capitalized */ ++ forcelc (tword + 1, tlen - 1); ++ } ++ } ++ } ++ else ++ { ++ /* Followcase or all-lower, we don't care which */ ++ if (!myupper (*nextc)) ++ forcelc (tword, flent->affl); ++ } ++ if (option == 3) ++ (void) printf ("\n%s", croot); ++ if (option != 4) ++ (void) printf (" %s%s", ichartosstr (tword, 1), extra); ++ if (flent->flagflags & FF_CROSSPRODUCT) ++ return tlen ++ + expand_suf (croot, tword, mask, FF_CROSSPRODUCT, option, extra); ++ else ++ return tlen; ++} ++ ++/* ++ * Expand a dictionary suffix entry ++ */ ++int expand_suf (croot, rootword, mask, optflags, option, extra) ++ char * croot; /* Char version of rootword */ ++ ichar_t * rootword; /* Root word to expand */ ++ register MASKTYPE mask[]; /* Mask bits to expand on */ ++ int optflags; /* Affix option flags */ ++ int option; /* Option, see expandmode */ ++ char * extra; /* Extra info to add to line */ ++ { ++ int entcount; /* No. of entries to process */ ++ int explength; /* Length of expansions */ ++ register struct flagent * ++ flent; /* Current table entry */ ++ ++ for (flent = sflaglist, entcount = numsflags, explength = 0; ++ entcount > 0; ++ flent++, entcount--) ++ { ++ if (TSTMASKBIT (mask, flent->flagbit)) ++ { ++ if ((optflags & FF_CROSSPRODUCT) == 0 ++ || (flent->flagflags & FF_CROSSPRODUCT)) ++ explength += ++ pr_suf_expansion (croot, rootword, flent, option, extra); ++ } ++ } ++ return explength; ++ } ++ ++/* Print a suffix expansion */ ++static int pr_suf_expansion (croot, rootword, flent, option, extra) ++ char * croot; /* Char version of rootword */ ++ register ichar_t * rootword; /* Root word to expand */ ++ register struct flagent * flent; /* Current table entry */ ++ int option; /* Option, see expandmode */ ++ char * extra; /* Extra info to add to line */ ++ { ++ int cond; /* Current condition number */ ++ register ichar_t * nextc; /* Next case choice */ ++ int tlen; /* Length of tword */ ++ ichar_t tword[INPUTWORDLEN + MAXAFFIXLEN]; /* Temp */ ++ ++ tlen = icharlen (rootword); ++ cond = flent->numconds; ++ if (cond > tlen) ++ return 0; ++ if (tlen - flent->stripl <= 0) ++ return 0; ++ for (nextc = rootword + tlen; --cond >= 0; ) ++ { ++ if ((flent->conds[mytoupper (*--nextc)] & (1 << cond)) == 0) ++ return 0; ++ } ++ /* ++ * The conditions are satisfied. Copy the word, add the suffix, ++ * and make it match the case of the last remaining character of the ++ * root. Again, this code carefully matches ins_cap and cap_ok. ++ */ ++ (void) icharcpy (tword, rootword); ++ nextc = tword + tlen - flent->stripl; ++ if (flent->affl) ++ { ++ (void) icharcpy (nextc, flent->affix); ++ if (!myupper (nextc[-1])) ++ forcelc (nextc, flent->affl); ++ } ++ else ++ *nextc = 0; ++ if (option == 3) ++ (void) printf ("\n%s", croot); ++ if (option != 4) ++ (void) printf (" %s%s", ichartosstr (tword, 1), extra); ++ return tlen + flent->affl - flent->stripl; ++ } ++ ++static void forcelc (dst, len) /* Force to lowercase */ ++ register ichar_t * dst; /* Destination to modify */ ++ register int len; /* Length to copy */ ++ { ++ ++ for ( ; --len >= 0; dst++) ++ *dst = mytolower (*dst); ++ } +diff -Nur vim60am.old/src/spell/tree.c vim60am/src/spell/tree.c +--- vim60am.old/src/spell/tree.c Thu Jan 1 01:00:00 1970 ++++ vim60am/src/spell/tree.c Wed Jun 27 19:16:55 2001 +@@ -0,0 +1,748 @@ ++/* ++ * tree.c - a hash style dictionary for user's personal words ++ * ++ * Pace Willisson, 1983 ++ * Hash support added by Geoff Kuenning, 1987 ++ * ++ * Copyright 1987, 1988, 1989, 1992, 1993, Geoff Kuenning, Granada Hills, CA ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All modifications to the source code must be clearly marked as ++ * such. Binary redistributions based on modified source code ++ * must be clearly marked as modified versions in the documentation ++ * and/or other materials provided with the distribution. ++ * 4. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgment: ++ * This product includes software developed by Geoff Kuenning and ++ * other unpaid contributors. ++ * 5. The name of Geoff Kuenning may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY GEOFF KUENNING AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL GEOFF KUENNING OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++/* ++ * $Log$ ++ * Revision 1.56 1995/01/08 23:23:49 geoff ++ * Support PDICTHOME for DOS purposes. ++ * ++ * Revision 1.55 1994/10/25 05:46:27 geoff ++ * Fix a comment that looked to some compilers like it might be nested. ++ * ++ * Revision 1.54 1994/01/25 07:12:15 geoff ++ * Get rid of all old RCS log lines in preparation for the 3.1 release. ++ * ++ */ ++ ++#include ++#include ++#include ++#include "ispell.h" ++#include "msgs.h" ++ ++Local FILE * trydict (char * dictname, char * home, ++ char * prefix, char * suffix); ++Local void treeload (FILE * dictf); ++Local struct dent * tinsert (struct dent * proto); ++#if SORTPERSONAL != 0 ++Local int pdictcmp (struct dent ** enta, struct dent **entb); ++#endif /* SORTPERSONAL != 0 */ ++#ifdef REGEX_LOOKUP ++#endif /* REGEX_LOOKUP */ ++ ++Local int cantexpand = 0; /* NZ if an expansion fails */ ++Local struct dent * pershtab; /* Aux hash table for personal dict */ ++Local int pershsize = 0; /* Space available in aux hash table */ ++Local int hcount = 0; /* Number of items in hash table */ ++ ++/* ++ * Hash table sizes. Prime is probably a good idea, though in truth I ++ * whipped the algorithm up on the spot rather than looking it up, so ++ * who knows what's really best? If we overflow the table, we just ++ * use a double-and-add-1 algorithm. ++ */ ++static int goodsizes[] = ++ { ++ 53, 223, 907, 3631 ++ }; ++ ++Local char personaldict[MAXPATHLEN]; ++Local FILE * dictf; ++Local newwords = 0; ++ ++Public void ++treeinit ( ++ char * p, /* Value specified in -p switch */ ++ char * LibDict) /* Root of default dict name */ ++{ ++ int abspath; /* NZ if p is abs path name */ ++ char * h; /* Home directory name */ ++ char seconddict[MAXPATHLEN]; /* Name of secondary dict */ ++ FILE * secondf; /* Access to second dict file */ ++ ++ /* ++ ** If -p was not specified, try to get a default name from the ++ ** environment. After this point, if p is null, the the value in ++ ** personaldict is the only possible name for the personal dictionary. ++ ** If p is non-null, then there is a possibility that we should ++ ** prepend HOME to get the correct dictionary name. ++ */ ++ if (p == NULL) ++ p = getenv (PDICTVAR); ++ /* ++ ** if p exists and begins with '/' we don't really need HOME, ++ ** but it's not very likely that HOME isn't set anyway (on non-DOS ++ ** systems). ++ */ ++ { ++ int i; ++ struct dent *x; ++ ++ for(i = 0; i < pershsize; i++) ++ { ++ x = &pershtab[i]; ++ if(x->word != NULL) ++ free(x->word); ++ for(x = x->next; x != NULL;) ++ { ++ struct dent *y; ++ ++ if(x->word != NULL) ++ free(x->word); ++ y = x; ++ x = x->next; ++ free(y); ++ } ++ } ++ if(pershtab != NULL) ++ free(pershtab); ++ pershtab = NULL; ++ pershsize = 0; ++ hcount = 0; ++ } ++ if ((h = getenv (HOME)) == NULL) ++ { ++#ifdef PDICTHOME ++ h = PDICTHOME; ++#else /* PDICTHOME */ ++ return; ++#endif /* PDICTHOME */ ++ } ++ ++ if (p == NULL) ++ { ++ /* ++ * No -p and no PDICTVAR. We will use LibDict and DEFPAFF to ++ * figure out the name of the personal dictionary and where it ++ * is. The rules are as follows: ++ * ++ * (1) If there is a local dictionary and a HOME dictionary, ++ * both are loaded, but changes are saved in the local one. ++ * The dictionary to save changes in is named "personaldict". ++ * (2) Dictionaries named after the affix file take precedence ++ * over dictionaries with the default suffix (DEFPAFF). ++ * (3) Dictionaries named with the new default names ++ * (DEFPDICT/DEFPAFF) take precedence over the old ones ++ * (OLDPDICT/OLDPAFF). ++ * (4) Dictionaries aren't combined unless they follow the same ++ * naming scheme. ++ * (5) If no dictionary can be found, a new one is created in ++ * the home directory, named after DEFPDICT and the affix ++ * file. ++ */ ++ dictf = trydict (personaldict, (char *) NULL, DEFPDICT, LibDict); ++ secondf = trydict (seconddict, h, DEFPDICT, LibDict); ++ if (dictf == NULL && secondf == NULL) ++ { ++ dictf = trydict (personaldict, (char *) NULL, DEFPDICT, DEFPAFF); ++ secondf = trydict (seconddict, h, DEFPDICT, DEFPAFF); ++ } ++ if (dictf == NULL && secondf == NULL) ++ { ++ dictf = trydict (personaldict, (char *) NULL, OLDPDICT, LibDict); ++ secondf = trydict (seconddict, h, OLDPDICT, LibDict); ++ } ++ if (dictf == NULL && secondf == NULL) ++ { ++ dictf = trydict (personaldict, (char *) NULL, OLDPDICT, OLDPAFF); ++ secondf = trydict (seconddict, h, OLDPDICT, OLDPAFF); ++ } ++ if (personaldict[0] == '\0') ++ { ++ if (seconddict[0] != '\0') ++ (void) strcpy (personaldict, seconddict); ++ else ++ (void) sprintf (personaldict, "%s/%s%s", h, DEFPDICT, LibDict); ++ } ++ if (dictf != NULL) ++ { ++ treeload (dictf); ++ (void) fclose (dictf); ++ } ++ if (secondf != NULL) ++ { ++ treeload (secondf); ++ (void) fclose (secondf); ++ } ++ } ++ else ++ { ++ /* ++ ** Figure out if p is an absolute path name. Note that beginning ++ ** with "./" and "../" is considered an absolute path, since this ++ ** still means we can't prepend HOME. ++ */ ++ abspath = (*p == '/' || strncmp (p, "./", 2) == 0 ++ || strncmp (p, "../", 3) == 0); ++#ifdef MSDOS ++ if (!abspath) ++ abspath = (*p == '\\' || strncmp (p, ".\\", 2) == 0 ++ || strncmp (p, "..\\", 3) == 0 ++ || (p[0] && p[1] == ':')); ++#endif ++ if (abspath) ++ { ++ (void) strcpy (personaldict, p); ++ if ((dictf = fopen (personaldict, "r")) != NULL) ++ { ++ treeload (dictf); ++ (void) fclose (dictf); ++ } ++ } ++ else ++ { ++ /* ++ ** The user gave us a relative pathname. We will try it ++ ** locally, and if that doesn't work, we'll try the home ++ ** directory. If neither exists, it will be created in ++ ** the home directory if words are added. ++ */ ++ (void) strcpy (personaldict, p); ++ if ((dictf = fopen (personaldict, "r")) != NULL) ++ { ++ treeload (dictf); ++ (void) fclose (dictf); ++ } ++ else if (!abspath) ++ { ++ /* Try the home */ ++ (void) sprintf (personaldict, "%s/%s", h, p); ++ if ((dictf = fopen (personaldict, "r")) != NULL) ++ { ++ treeload (dictf); ++ (void) fclose (dictf); ++ } ++ } ++ /* ++ * If dictf is null, we couldn't open the dictionary ++ * specified in the -p switch. Complain. ++ */ ++ if (dictf == NULL) ++ { ++ (void) fprintf (stderr, CANT_OPEN, p); ++ perror (""); ++ return; ++ } ++ } ++ } ++ ++#ifndef FEAT_SPELL_HL ++ if (!lflag && !aflag ++ && access (personaldict, 2) < 0 && errno != ENOENT) ++ { ++ (void) fprintf (stderr, TREE_C_CANT_UPDATE, personaldict); ++ (void) sleep ((unsigned) 2); ++ } ++#endif ++} ++ ++/* ++ * Try to open a dictionary. As a side effect, leaves the dictionary ++ * name in "filename" if one is found, and leaves a null string there ++ * otherwise. ++ */ ++Local FILE * ++trydict ( ++ char * filename, /* Where to store the file name */ ++ char * home, /* Home directory */ ++ char * prefix, /* Prefix for dictionary */ ++ char * suffix) /* Suffix for dictionary */ ++{ ++ FILE * dictf; /* Access to dictionary file */ ++ ++ if (home == NULL) ++ (void) sprintf (filename, "%s%s", prefix, suffix); ++ else ++ (void) sprintf (filename, "%s/%s%s", home, prefix, suffix); ++ dictf = fopen (filename, "r"); ++ if (dictf == NULL) ++ filename[0] = '\0'; ++ return dictf; ++} ++ ++Local void ++treeload ( ++ register FILE * loadfile) /* File to load words from */ ++{ ++ char buf[BUFSIZ]; /* Buffer for reading pers dict */ ++ ++ while (fgets (buf, sizeof buf, loadfile) != NULL) ++ treeinsert (buf, sizeof(buf), 1); ++ newwords = 0; ++} ++ ++Public void ++treeinsert ( ++ char * word, /* Word to insert - must be canonical */ ++ int wordlen, /* Length of the word buffer */ ++ int keep) ++{ ++ register int i, len; ++ struct dent wordent; ++ register struct dent * dp; ++ struct dent * olddp; ++#ifndef NO_CAPITALIZATION_SUPPORT ++ struct dent * newdp; ++#endif ++ struct dent * oldhtab; ++ int oldhsize; ++ ichar_t nword[INPUTWORDLEN + MAXAFFIXLEN]; ++#ifndef NO_CAPITALIZATION_SUPPORT ++ int isvariant; ++#endif ++ ++ len = strlen(word); ++ if((word[len - 1] == '\n') || (word[len - 1] == '\r')) ++ word[len - 1] = '\0', len--; ++ if((word[len - 1] == '\n') || (word[len - 1] == '\r')) ++ word[len - 1] = '\0'; ++ /* ++ * Expand hash table when it is MAXPCT % full. ++ */ ++ if (!cantexpand && (hcount * 100) / MAXPCT >= pershsize) ++ { ++ oldhsize = pershsize; ++ oldhtab = pershtab; ++ for (i = 0; i < sizeof goodsizes / sizeof (goodsizes[0]); i++) ++ if (goodsizes[i] > pershsize) ++ break; ++ if (i >= sizeof goodsizes / sizeof goodsizes[0]) ++ pershsize += pershsize + 1; ++ else ++ pershsize = goodsizes[i]; ++ pershtab = ++ (struct dent *) calloc ((unsigned) pershsize, sizeof (struct dent)); ++ if (pershtab == NULL) ++ { ++ (void) fprintf (stderr, TREE_C_NO_SPACE); ++ /* ++ * Try to continue anyway, since our overflow ++ * algorithm can handle an overfull (100%+) table, ++ * and the malloc very likely failed because we ++ * already have such a huge table, so small mallocs ++ * for overflow entries will still work. ++ */ ++ if (oldhtab == NULL) ++ exit (1); /* No old table, can't go on */ ++ (void) fprintf (stderr, TREE_C_TRY_ANYWAY); ++ cantexpand = 1; /* Suppress further messages */ ++ pershsize = oldhsize; /* Put things back */ ++ pershtab = oldhtab; /* ... */ ++ newwords = 1; /* And pretend it worked */ ++ } ++ else ++ { ++ /* ++ * Re-insert old entries into new table ++ */ ++ for (i = 0; i < oldhsize; i++) ++ { ++ dp = &oldhtab[i]; ++ if (dp->flagfield & USED) ++ { ++#ifdef NO_CAPITALIZATION_SUPPORT ++ (void) tinsert (dp); ++#else ++ newdp = tinsert (dp); ++ isvariant = (dp->flagfield & MOREVARIANTS); ++#endif ++ dp = dp->next; ++#ifdef NO_CAPITALIZATION_SUPPORT ++ while (dp != NULL) ++ { ++ (void) tinsert (dp); ++ olddp = dp; ++ dp = dp->next; ++ free ((char *) olddp); ++ } ++#else ++ while (dp != NULL) ++ { ++ if (isvariant) ++ { ++ isvariant = dp->flagfield & MOREVARIANTS; ++ olddp = newdp->next; ++ newdp->next = dp; ++ newdp = dp; ++ dp = dp->next; ++ newdp->next = olddp; ++ } ++ else ++ { ++ isvariant = dp->flagfield & MOREVARIANTS; ++ newdp = tinsert (dp); ++ olddp = dp; ++ dp = dp->next; ++ free ((char *) olddp); ++ } ++ } ++#endif ++ } ++ } ++ if (oldhtab != NULL) ++ free ((char *) oldhtab); ++ } ++ } ++ ++ /* ++ ** We're ready to do the insertion. Start by creating a sample ++ ** entry for the word. ++ */ ++ if (makedent (word, wordlen, &wordent) < 0) ++ return; /* Word must be too big or something */ ++ if (keep) ++ wordent.flagfield |= KEEP; ++ /* ++ ** Now see if word or a variant is already in the table. We use the ++ ** capitalized version so we'll find the header, if any. ++ **/ ++ (void) strtoichar (nword, word, sizeof nword, 1); ++ upcase (nword); ++ if ((dp = lookup (nword, 1)) != NULL) ++ { ++ /* It exists. Combine caps and set the keep flag. */ ++ if (combinecaps (dp, &wordent) < 0) ++ { ++ free (wordent.word); ++ return; ++ } ++ } ++ else ++ { ++ /* It's new. Insert the word. */ ++ dp = tinsert (&wordent); ++#ifndef NO_CAPITALIZATION_SUPPORT ++ if (captype (dp->flagfield) == FOLLOWCASE) ++ (void) addvheader (dp); ++#endif ++ } ++ newwords |= keep; ++ hcount++; ++} ++ ++Local struct dent * ++tinsert ( ++ struct dent * proto) /* Prototype entry to copy */ ++{ ++ ichar_t iword[INPUTWORDLEN + MAXAFFIXLEN]; ++ register int hcode; ++ register struct dent * hp; /* Next trial entry in hash table */ ++ register struct dent * php; /* Prev. value of hp, for chaining */ ++ ++ if (strtoichar (iword, proto->word, sizeof iword, 1)) ++ (void) fprintf (stderr, WORD_TOO_LONG (proto->word)); ++#ifdef NO_CAPITALIZATION_SUPPORT ++ upcase (iword); ++#endif ++ hcode = hash (iword, pershsize); ++ php = NULL; ++ hp = &pershtab[hcode]; ++ if (hp->flagfield & USED) ++ { ++ while (hp != NULL) ++ { ++ php = hp; ++ hp = hp->next; ++ } ++ hp = (struct dent *) calloc (1, sizeof (struct dent)); ++ if (hp == NULL) ++ { ++ (void) fprintf (stderr, TREE_C_NO_SPACE); ++ exit (1); ++ } ++ } ++ *hp = *proto; ++ if (php != NULL) ++ php->next = hp; ++ hp->next = NULL; ++ return hp; ++} ++ ++Public struct dent * ++treelookup (register ichar_t * word) ++ ++{ ++ register int hcode; ++ register struct dent * hp; ++ char chword[INPUTWORDLEN + MAXAFFIXLEN]; ++ ++ if (pershsize <= 0) ++ return NULL; ++ (void) ichartostr (chword, word, sizeof chword, 1); ++ hcode = hash (word, pershsize); ++ hp = &pershtab[hcode]; ++ while (hp != NULL && (hp->flagfield & USED)) ++ { ++ if (strcmp (chword, hp->word) == 0) ++ break; ++#ifndef NO_CAPITALIZATION_SUPPORT ++ while (hp->flagfield & MOREVARIANTS) ++ hp = hp->next; ++#endif ++ hp = hp->next; ++ } ++ if (hp != NULL && (hp->flagfield & USED)) ++ return hp; ++ else ++ return NULL; ++} ++ ++#if SORTPERSONAL != 0 ++/* Comparison routine for sorting the personal dictionary with qsort */ ++Local int ++pdictcmp ( ++ struct dent ** enta, ++ struct dent ** entb) ++{ ++ ++ /* The parentheses around *enta and *entb below are NECESSARY! ++ ** Otherwise the compiler reads it as *(enta->word), or ++ ** enta->word[0], which is illegal (but pcc takes it and ++ ** produces wrong code). ++ **/ ++ return casecmp ((*enta)->word, (*entb)->word, 1); ++} ++#endif ++ ++Public void ++treeoutput () ++ ++{ ++ register struct dent * cent; /* Current entry */ ++ register struct dent * lent; /* Linked entry */ ++#if SORTPERSONAL != 0 ++ int pdictsize; /* Number of entries to write */ ++ struct dent ** sortlist; /* List of entries to be sorted */ ++ register struct dent ** sortptr; /* Handy pointer into sortlist */ ++#endif ++ register struct dent * ehtab; /* End of pershtab, for fast looping */ ++ ++ if (newwords == 0) ++ return; ++ ++ if ((dictf = fopen (personaldict, "w")) == NULL) ++ { ++ (void) fprintf (stderr, CANT_CREATE, personaldict); ++ return; ++ } ++ ++#if SORTPERSONAL != 0 ++ /* ++ ** If we are going to sort the personal dictionary, we must know ++ ** how many items are going to be sorted. ++ */ ++ pdictsize = 0; ++ if (hcount >= SORTPERSONAL) ++ sortlist = NULL; ++ else ++ { ++ for (cent = pershtab, ehtab = pershtab + pershsize; cent < ehtab; ++ cent++) ++ { ++ for (lent = cent; lent != NULL; lent = lent->next) ++ { ++ if ((lent->flagfield & (USED | KEEP)) == (USED | KEEP)) ++ pdictsize++; ++#ifndef NO_CAPITALIZATION_SUPPORT ++ while (lent->flagfield & MOREVARIANTS) ++ lent = lent->next; ++#endif ++ } ++ } ++ for (cent = hashtbl, ehtab = hashtbl + hashsize; cent < ehtab; cent++) ++ { ++ if ((cent->flagfield & (USED | KEEP)) == (USED | KEEP)) ++ { ++ /* ++ ** We only want to count variant headers ++ ** and standalone entries. These happen ++ ** to share the characteristics in the ++ ** test below. This test will appear ++ ** several more times in this routine. ++ */ ++#ifndef NO_CAPITALIZATION_SUPPORT ++ if (captype (cent->flagfield) != FOLLOWCASE ++ && cent->word != NULL) ++#endif ++ pdictsize++; ++ } ++ } ++ sortlist = (struct dent **) malloc (pdictsize * sizeof (struct dent)); ++ } ++ if (sortlist == NULL) ++ { ++#endif ++ for (cent = pershtab, ehtab = pershtab + pershsize; cent < ehtab; ++ cent++) ++ { ++ for (lent = cent; lent != NULL; lent = lent->next) ++ { ++ if ((lent->flagfield & (USED | KEEP)) == (USED | KEEP)) ++ { ++ toutent (dictf, lent, 1); ++#ifndef NO_CAPITALIZATION_SUPPORT ++ while (lent->flagfield & MOREVARIANTS) ++ lent = lent->next; ++#endif ++ } ++ } ++ } ++ for (cent = hashtbl, ehtab = hashtbl + hashsize; cent < ehtab; cent++) ++ { ++ if ((cent->flagfield & (USED | KEEP)) == (USED | KEEP)) ++ { ++#ifndef NO_CAPITALIZATION_SUPPORT ++ if (captype (cent->flagfield) != FOLLOWCASE ++ && cent->word != NULL) ++#endif ++ toutent (dictf, cent, 1); ++ } ++ } ++#if SORTPERSONAL != 0 ++ return; ++ } ++ /* ++ ** Produce dictionary in sorted order. We used to do this ++ ** destructively, but that turns out to fail because in some modes ++ ** the dictionary is written more than once. So we build an ++ ** auxiliary pointer table (in sortlist) and sort that. This ++ ** is faster anyway, though it uses more memory. ++ */ ++ sortptr = sortlist; ++ for (cent = pershtab, ehtab = pershtab + pershsize; cent < ehtab; cent++) ++ { ++ for (lent = cent; lent != NULL; lent = lent->next) ++ { ++ if ((lent->flagfield & (USED | KEEP)) == (USED | KEEP)) ++ { ++ *sortptr++ = lent; ++#ifndef NO_CAPITALIZATION_SUPPORT ++ while (lent->flagfield & MOREVARIANTS) ++ lent = lent->next; ++#endif ++ } ++ } ++ } ++ for (cent = hashtbl, ehtab = hashtbl + hashsize; cent < ehtab; cent++) ++ { ++ if ((cent->flagfield & (USED | KEEP)) == (USED | KEEP)) ++ { ++#ifndef NO_CAPITALIZATION_SUPPORT ++ if (captype (cent->flagfield) != FOLLOWCASE ++ && cent->word != NULL) ++#endif ++ *sortptr++ = cent; ++ } ++ } ++ /* Sort the list */ ++ qsort ((char *) sortlist, (unsigned) pdictsize, ++ sizeof (sortlist[0]), ++ (int (*) (const void *, const void *)) pdictcmp); ++ /* Write it out */ ++ for (sortptr = sortlist; --pdictsize >= 0; ) ++ toutent (dictf, *sortptr++, 1); ++ free ((char *) sortlist); ++#endif ++ ++ newwords = 0; ++ ++ (void) fclose (dictf); ++} ++ ++#ifdef REGEX_LOOKUP ++ ++/* check the hashed dictionary for words matching the regex. return the */ ++/* a matching string if found else return NULL */ ++char * ++do_regex_lookup ( ++ char * expr, /* regular expression to use in the match */ ++ int whence) /* 0 = start at the beg with new regx, else */ ++ /* continue from cur point w/ old regex */ ++{ ++ static struct dent * curent; ++ static int curindex; ++ static struct dent * curpersent; ++ static int curpersindex; ++ static REGCTYPE cmp_expr = (REGCTYPE)0; ++ char dummy[INPUTWORDLEN + MAXAFFIXLEN]; ++ ichar_t * is; ++ ++ if (whence == 0) ++ { ++ is = strtosichar (expr, 0); ++ upcase (is); ++ expr = ichartosstr (is, 1); ++ REGFREE (cmp_expr); /* free previous compiled pattern, if any */ ++ cmp_expr = REGCMP (cmp_expr, expr); ++ curent = hashtbl; ++ curindex = 0; ++ curpersent = pershtab; ++ curpersindex = 0; ++ } ++ ++ /* search the dictionary until the word is found or the words run out */ ++ for ( ; curindex < hashsize; curent++, curindex++) ++ { ++ if (curent->word != NULL ++ && REGEX (cmp_expr, curent->word, dummy) != NULL) ++ { ++ curindex++; ++ /* Everybody's gotta write a wierd expression once in a while! */ ++ return curent++->word; ++ } ++ } ++ /* Try the personal dictionary too */ ++ for ( ; curpersindex < pershsize; curpersent++, curpersindex++) ++ { ++ if ((curpersent->flagfield & USED) != 0 ++ && curpersent->word != NULL ++ && REGEX (cmp_expr, curpersent->word, dummy) != NULL) ++ { ++ curpersindex++; ++ /* Everybody's gotta write a wierd expression once in a while! */ ++ return curpersent++->word; ++ } ++ } ++ return NULL; ++} ++#endif /* REGEX_LOOKUP */ +diff -Nur vim60am.old/src/spell/util.c vim60am/src/spell/util.c +--- vim60am.old/src/spell/util.c Thu Jan 1 01:00:00 1970 ++++ vim60am/src/spell/util.c Wed Jun 27 19:16:55 2001 +@@ -0,0 +1,351 @@ ++#include ++#include "ispell.h" ++ ++Local char *myrindex(char *s, char c); ++ ++Public int ++casecmp ( ++ char * a, ++ char * b, ++ int canonical) /* NZ for canonical string chars */ ++{ ++ register ichar_t * ap; ++ register ichar_t * bp; ++ ichar_t inta[INPUTWORDLEN + 4 * MAXAFFIXLEN + 4]; ++ ichar_t intb[INPUTWORDLEN + 4 * MAXAFFIXLEN + 4]; ++ ++ (void) strtoichar (inta, a, sizeof inta, canonical); ++ (void) strtoichar (intb, b, sizeof intb, canonical); ++ for (ap = inta, bp = intb; *ap != 0; ap++, bp++) ++ { ++ if (*ap != *bp) ++ { ++ if (*bp == '\0') ++ return hashheader.sortorder[*ap]; ++ else if (mylower (*ap)) ++ { ++ if (mylower (*bp) || mytoupper (*ap) != *bp) ++ return (int) hashheader.sortorder[*ap] - ++ (int) hashheader.sortorder[*bp]; ++ } ++ else ++ { ++ if (myupper (*bp) || mytolower (*ap) != *bp) ++ return (int) hashheader.sortorder[*ap] - ++ (int) hashheader.sortorder[*bp]; ++ } ++ } ++ } ++ if (*bp != '\0') ++ return -(int) hashheader.sortorder[*bp]; ++ for (ap = inta, bp = intb; *ap; ap++, bp++) ++ { ++ if (*ap != *bp) ++ { ++ return (int) hashheader.sortorder[*ap] - ++ (int) hashheader.sortorder[*bp]; ++ } ++ } ++ return 0; ++} ++ ++Public int ++ins_root_cap ( ++ register ichar_t * word, ++ register ichar_t * pattern, ++ int prestrip, ++ int preadd, ++ int sufstrip, ++ int sufadd, ++ struct dent * firstdent, ++ struct flagent * pfxent, ++ struct flagent * sufent) ++{ ++ int i; /* Index into savearea */ ++ ichar_t savearea[MAX_CAPS][INPUTWORDLEN + MAXAFFIXLEN]; ++ int nsaved; /* Number of words saved */ ++ ++ nsaved = 0; ++ save_root_cap (word, pattern, prestrip, preadd, sufstrip, sufadd, ++ firstdent, pfxent, sufent, savearea, &nsaved); ++ for (i = 0; i < nsaved; i++) ++ { ++ if (insert (savearea[i]) < 0) ++ return -1; ++ } ++ return 0; ++} ++ ++Public void ++save_root_cap( ++ register ichar_t * word, /* Word to be saved */ ++ register ichar_t * pattern, /* Capitalization pattern */ ++ int prestrip, /* No. chars stripped from front */ ++ int preadd, /* No. chars added to front of root */ ++ int sufstrip, /* No. chars stripped from back */ ++ int sufadd, /* No. chars added to back of root */ ++ struct dent * firstdent, /* First dent for root */ ++ struct flagent * pfxent, /* Pfx-flag entry for word */ ++ struct flagent * sufent, /* Sfx-flag entry for word */ ++ ichar_t savearea[MAX_CAPS][INPUTWORDLEN + MAXAFFIXLEN], ++ /* Room to save words */ ++ int * nsaved) /* Number saved so far (updated) */ ++{ ++#ifndef NO_CAPITALIZATION_SUPPORT ++ register struct dent * dent; ++#endif /* NO_CAPITALIZATION_SUPPORT */ ++ int firstisupper; ++ ichar_t newword[INPUTWORDLEN + 4 * MAXAFFIXLEN + 4]; ++#ifndef NO_CAPITALIZATION_SUPPORT ++ register ichar_t * p; ++ int len; ++ int i; ++ int limit; ++#endif /* NO_CAPITALIZATION_SUPPORT */ ++ ++ if (*nsaved >= MAX_CAPS) ++ return; ++ (void) icharcpy (newword, word); ++ firstisupper = myupper (pattern[0]); ++#ifdef NO_CAPITALIZATION_SUPPORT ++ /* ++ ** Apply the old, simple-minded capitalization rules. ++ */ ++ if (firstisupper) ++ { ++ if (myupper (pattern[1])) ++ upcase (newword); ++ else ++ { ++ lowcase (newword); ++ newword[0] = mytoupper (newword[0]); ++ } ++ } ++ else ++ lowcase (newword); ++ (void) icharcpy (savearea[*nsaved], newword); ++ (*nsaved)++; ++ return; ++#else /* NO_CAPITALIZATION_SUPPORT */ ++#define flagsareok(dent) \ ++ ((pfxent == NULL \ ++ || TSTMASKBIT (dent->mask, pfxent->flagbit)) \ ++ && (sufent == NULL \ ++ || TSTMASKBIT (dent->mask, sufent->flagbit))) ++ ++ dent = firstdent; ++ if ((dent->flagfield & (CAPTYPEMASK | MOREVARIANTS)) == ALLCAPS) ++ { ++ upcase (newword); /* Uppercase required */ ++ (void) icharcpy (savearea[*nsaved], newword); ++ (*nsaved)++; ++ return; ++ } ++ for (p = pattern; *p; p++) ++ { ++ if (mylower (*p)) ++ break; ++ } ++ if (*p == 0) ++ { ++ upcase (newword); /* Pattern was all caps */ ++ (void) icharcpy (savearea[*nsaved], newword); ++ (*nsaved)++; ++ return; ++ } ++ for (p = pattern + 1; *p; p++) ++ { ++ if (myupper (*p)) ++ break; ++ } ++ if (*p == 0) ++ { ++ /* ++ ** The pattern was all-lower or capitalized. If that's ++ ** legal, insert only that version. ++ */ ++ if (firstisupper) ++ { ++ if (captype (dent->flagfield) == CAPITALIZED ++ || captype (dent->flagfield) == ANYCASE) ++ { ++ lowcase (newword); ++ newword[0] = mytoupper (newword[0]); ++ (void) icharcpy (savearea[*nsaved], newword); ++ (*nsaved)++; ++ return; ++ } ++ } ++ else ++ { ++ if (captype (dent->flagfield) == ANYCASE) ++ { ++ lowcase (newword); ++ (void) icharcpy (savearea[*nsaved], newword); ++ (*nsaved)++; ++ return; ++ } ++ } ++ while (dent->flagfield & MOREVARIANTS) ++ { ++ dent = dent->next; ++ if (captype (dent->flagfield) == FOLLOWCASE ++ || !flagsareok (dent)) ++ continue; ++ if (firstisupper) ++ { ++ if (captype (dent->flagfield) == CAPITALIZED) ++ { ++ lowcase (newword); ++ newword[0] = mytoupper (newword[0]); ++ (void) icharcpy (savearea[*nsaved], newword); ++ (*nsaved)++; ++ return; ++ } ++ } ++ else ++ { ++ if (captype (dent->flagfield) == ANYCASE) ++ { ++ lowcase (newword); ++ (void) icharcpy (savearea[*nsaved], newword); ++ (*nsaved)++; ++ return; ++ } ++ } ++ } ++ } ++ /* ++ ** Either the sample had complex capitalization, or the simple ++ ** capitalizations (all-lower or capitalized) are illegal. ++ ** Insert all legal capitalizations, including those that are ++ ** all-lower or capitalized. If the prototype is capitalized, ++ ** capitalized all-lower samples. Watch out for affixes. ++ */ ++ dent = firstdent; ++ p = strtosichar (dent->word, 1); ++ len = icharlen (p); ++ if (dent->flagfield & MOREVARIANTS) ++ dent = dent->next; /* Skip place-holder entry */ ++ for ( ; ; ) ++ { ++ if (flagsareok (dent)) ++ { ++ if (captype (dent->flagfield) != FOLLOWCASE) ++ { ++ lowcase (newword); ++ if (firstisupper || captype (dent->flagfield) == CAPITALIZED) ++ newword[0] = mytoupper (newword[0]); ++ (void) icharcpy (savearea[*nsaved], newword); ++ (*nsaved)++; ++ if (*nsaved >= MAX_CAPS) ++ return; ++ } ++ else ++ { ++ /* Followcase is the tough one. */ ++ p = strtosichar (dent->word, 1); ++ (void) bcopy ((char *) (p + prestrip), ++ (char *) (newword + preadd), ++ (len - prestrip - sufstrip) * sizeof (ichar_t)); ++ if (myupper (p[prestrip])) ++ { ++ for (i = 0; i < preadd; i++) ++ newword[i] = mytoupper (newword[i]); ++ } ++ else ++ { ++ for (i = 0; i < preadd; i++) ++ newword[i] = mytolower (newword[i]); ++ } ++ limit = len + preadd + sufadd - prestrip - sufstrip; ++ i = len + preadd - prestrip - sufstrip; ++ p += len - sufstrip - 1; ++ if (myupper (*p)) ++ { ++ for (p = newword + i; i < limit; i++, p++) ++ *p = mytoupper (*p); ++ } ++ else ++ { ++ for (p = newword + i; i < limit; i++, p++) ++ *p = mytolower (*p); ++ } ++ (void) icharcpy (savearea[*nsaved], newword); ++ (*nsaved)++; ++ if (*nsaved >= MAX_CAPS) ++ return; ++ } ++ } ++ if ((dent->flagfield & MOREVARIANTS) == 0) ++ break; /* End of the line */ ++ dent = dent->next; ++ } ++ return; ++#endif /* NO_CAPITALIZATION_SUPPORT */ ++} ++Public int ++insert(register ichar_t * word) ++{ ++ register int i; ++ register char * realword; ++ ++ realword = ichartosstr (word, 0); ++ for (i = 0; i < pcount; i++) ++ if (strcmp (possibilities[i], realword) == 0) ++ return (0); ++ ++ (void) strcpy (possibilities[pcount++], realword); ++ i = strlen (realword); ++ if (i > maxposslen) ++ maxposslen = i; ++ if (pcount >= MAXPOSSIBLE) ++ return (-1); ++ else ++ return (0); ++} ++/* ++** A trivial wrapper for rindex (file '/') on Unix, but ++** saves a lot of ifdef-ing on MS-DOS. ++*/ ++ ++Public char * ++last_slash (char *file) ++ ++{ ++ char *slash = myrindex (file, '/'); ++#ifdef MSDOS ++ /* ++ ** Can have a backslash or a colon; both mean the basename ++ ** begins right after them. ++ */ ++ char *bs = myrindex (file, '\\'); ++ ++ /* ++ ** We can have both forward- and backslashes; return the ++ ** place of rightmost one of either gender. ++ */ ++ if (slash == NULL || (bs != NULL && bs > slash)) ++ slash = bs; ++ if (slash == NULL && file[0] != '\0' && file[1] == ':') ++ slash = file + 1; ++#endif ++ return slash; ++} ++ ++Local char * ++myrindex(char *s, register char c) ++ ++{ ++ register char *x; ++ ++ x = s + strlen(s) - 1; ++ ++ while(x >= s) ++ { ++ if(*x == c) ++ return(x); ++ x--; ++ } ++ return(NULL); ++} +diff -Nur vim60am.old/src/spell/version.h vim60am/src/spell/version.h +--- vim60am.old/src/spell/version.h Thu Jan 1 01:00:00 1970 ++++ vim60am/src/spell/version.h Wed Jun 27 19:16:55 2001 +@@ -0,0 +1,124 @@ ++/* ++ * Since the strings in this file are printed out when the "-v" switch is ++ * given to ispell, you may want to translate them into your native language. ++ * However, any translation of these strings MUST accurately preserve the ++ * legal rights under international law; you may wish to consult a lawyer ++ * about this since you will be responsible for the results of any ++ * incorrect translation. ++ */ ++ ++Local char *Version_ID[] = { ++ "@(#) International Ispell Version 3.1.20 10/10/95", ++ "@(#) Copyright (c), 1983, by Pace Willisson", ++ "@(#) International version Copyright (c) 1987, 1988, 1990-1995,", ++ "@(#) by Geoff Kuenning, Granada Hills, CA. All rights reserved.", ++ "@(#)", ++ "@(#) Redistribution and use in source and binary forms, with or without", ++ "@(#) modification, are permitted provided that the following conditions", ++ "@(#) are met:", ++ "@(#)", ++ "@(#) 1. Redistributions of source code must retain the above copyright", ++ "@(#) notice, this list of conditions and the following disclaimer.", ++ "@(#) 2. Redistributions in binary form must reproduce the above", ++ "@(#) copyright notice, this list of conditions and the following", ++ "@(#) disclaimer in the documentation and/or other materials provided", ++ "@(#) with the distribution.", ++ "@(#) 3. All modifications to the source code must be clearly marked as", ++ "@(#) such. Binary redistributions based on modified source code", ++ "@(#) must be clearly marked as modified versions in the documentation", ++ "@(#) and/or other materials provided with the distribution.", ++ "@(#) 4. All advertising materials mentioning features or use of this", ++ "@(#) software must display the following acknowledgment:", ++ "@(#) This product includes software developed by Geoff Kuenning and", ++ "@(#) other unpaid contributors.", ++ "@(#) 5. The name of Geoff Kuenning may not be used to endorse or promote", ++ "@(#) products derived from this software without specific prior", ++ "@(#) written permission.", ++ "@(#)", ++ "@(#) THIS SOFTWARE IS PROVIDED BY GEOFF KUENNING AND CONTRIBUTORS ``AS", ++ "@(#) IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT", ++ "@(#) LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS", ++ "@(#) FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GEOFF", ++ "@(#) KUENNING OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,", ++ "@(#) INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES", ++ "@(#) (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR", ++ "@(#) SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)", ++ "@(#) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,", ++ "@(#) STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)", ++ "@(#) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED", ++ "@(#) OF THE POSSIBILITY OF SUCH DAMAGE.", ++ NULL ++}; ++ ++static char RCS_Version_ID[] = ++ "$Id$"; ++ ++/* ++ * $Log$ ++ * Revision 1.44 1995/10/11 05:03:28 geoff ++ * Upgrade to patch level 20 ++ * ++ * Revision 1.43 1995/10/11 04:58:26 geoff ++ * Upgrade to patch 19 ++ * ++ * Revision 1.42 1995/01/15 01:23:26 geoff ++ * Upgrade to patch level 18 ++ * ++ * Revision 1.41 1995/01/15 01:14:30 geoff ++ * Upgrade to patch level 17 ++ * ++ * Revision 1.40 1995/01/15 01:03:55 geoff ++ * Upgrade to patch level 16 ++ * ++ * Revision 1.39 1995/01/15 01:01:01 geoff ++ * Upgrade to patch level 15 ++ * ++ * Revision 1.38 1995/01/15 00:54:19 geoff ++ * Upgrade to patch level 14 ++ * ++ * Revision 1.37 1994/11/21 07:03:01 geoff ++ * Update to patch level 13. ++ * ++ * Revision 1.36 1994/11/01 06:28:31 geoff ++ * Update to patch level 12 ++ * ++ * Revision 1.35 1994/11/01 06:12:42 geoff ++ * Update to patch level 11 ++ * ++ * Revision 1.34 1994/11/01 06:01:15 geoff ++ * Update to patch level 10 ++ * ++ * Revision 1.33 1994/11/01 05:36:43 geoff ++ * Update to patch level 9 ++ * ++ * Revision 1.32 1994/05/25 04:38:59 geoff ++ * Update to patch level 8 ++ * ++ * Revision 1.31 1994/05/18 03:07:26 geoff ++ * Update to patch level 7 ++ * ++ * Revision 1.30 1994/05/17 06:21:05 geoff ++ * Version update for ispell.el release ++ * ++ * Revision 1.29 1994/04/27 04:14:18 geoff ++ * Update to patch level 5 ++ * ++ * Revision 1.28 1994/03/21 02:00:50 geoff ++ * Update to patch level 4 ++ * ++ * Revision 1.27 1994/02/23 04:52:31 geoff ++ * Update to latest version. ++ * ++ * Revision 1.26 1994/02/08 05:59:20 geoff ++ * Update version ++ * ++ * Revision 1.25 1994/02/07 08:58:28 geoff ++ * Get rid of a comma that confuses patch ++ * ++ * Revision 1.24 1994/02/07 08:24:23 geoff ++ * Upate patch level ++ * ++ * Revision 1.23 1994/01/25 07:12:21 geoff ++ * Get rid of all old RCS log lines in preparation for the 3.1 release. ++ * ++ */ +diff -Nur vim60am.old/src/spell/wm.h vim60am/src/spell/wm.h +--- vim60am.old/src/spell/wm.h Thu Jan 1 01:00:00 1970 ++++ vim60am/src/spell/wm.h Wed Jun 27 19:16:55 2001 +@@ -0,0 +1,12 @@ ++#ifndef Public ++enum _logical {False,True}; ++typedef enum _logical Logical; ++ ++#define EOS '\0' ++ ++typedef unsigned int Word; ++typedef unsigned char Byte; ++ ++#define Public ++#define Local static ++#endif +diff -Nur vim60am.old/src/spell.c vim60am/src/spell.c +--- vim60am.old/src/spell.c Thu Jan 1 01:00:00 1970 ++++ vim60am/src/spell.c Tue Jul 3 13:44:50 2001 +@@ -0,0 +1,183 @@ ++#include "spell/wm.h" ++#include "vim.h" ++#define MAIN 1 ++#include "ispell.h" ++#define MAXWORDLEN 80 ++ ++#ifdef FEAT_SPELL_HL ++ ++int spell_flag = 0; ++Local char *err; ++void ++ex_spell(exarg_T *eap) ++ ++{ ++ if(strcmp(eap->arg, "on") == 0) ++ { ++ spell_flag = 1; ++ if(!inited) ++ { ++ if(!reload_dict()) ++ return; ++ } ++ } ++ else if(STRCMP(eap->arg, "off") == 0) ++ spell_flag = 0; ++ else ++ EMSG2("Invalid :spell %s", eap->arg); ++ redraw_all_later(NOT_VALID); ++ return; ++} ++ ++int ++reload_dict() ++ ++{ ++ if(spell_flag == 0) ++ return(TRUE); ++ spell_save_private_dict(); ++ inited = 0; ++ if(STRCMP(p_spell_lang, "") == 0) ++ { ++ EMSG("dictionary not defined"); ++ do_cmdline((char_u *)"spell off", NULL, NULL, DOCMD_VERBOSE); ++ spell_flag = 0; ++ return(FALSE); ++ } ++ if ((err = linit(hashname)) != NULL) ++ { ++ EMSG(err); ++ do_cmdline((char_u *)"spell off", NULL, NULL, DOCMD_VERBOSE); ++ spell_flag = 0; ++ return(FALSE); ++ } ++ treeinit (NULL, p_spell_lang); ++ return(TRUE); ++} ++ ++static colnr_T last_col; ++static ichar_t curr_word[MAXWORDLEN + 1]; /* assume max. keyword len is 80 */ ++static char word_to_spell[MAXWORDLEN + 1]; ++ int last_attr; ++static Logical in_word; ++ ++int my_is_char(char_u ccc); ++ ++int ++get_spell_attr(spell_col, col, line) ++ colnr_T spell_col; ++ colnr_T col; ++ char_u *line; ++{ ++ char_u *line_ptr; ++ colnr_T curr_col; ++ unsigned int i; ++ ++ if(spell_col == 0) ++ last_col = 0, in_word = False, last_attr = 0; ++ ++ if((spell_col < last_col) && in_word) ++ return(last_attr); ++ else if(spell_col >= last_col) ++ { ++ last_attr = 0; ++ in_word = False; ++ line_ptr = &line[spell_col]; ++ curr_col = spell_col; ++ if(iswordch((ichar_t)(*line_ptr)) && *line_ptr) ++ { ++ while((spell_col > 0) && my_is_char(*(line_ptr - 1))) ++ spell_col--, line_ptr--; ++ while(isboundarych((ichar_t)(*(line_ptr)))) ++ spell_col++, line_ptr++; ++ ++ line_ptr = &line[spell_col]; ++ curr_col = spell_col; ++ while(my_is_char(*line_ptr) && *line_ptr && ++ ((curr_col - spell_col) < MAXWORDLEN)) ++ curr_col++, line_ptr++; ++ while(isboundarych((ichar_t)(*(line_ptr - 1)))) ++ curr_col--, line_ptr--; ++ } ++ if(curr_col - spell_col > 1) ++ { ++ /*for(i = 0; i < curr_col - spell_col; i++) ++ curr_word[i] = line[spell_col + i]; ++ curr_word[curr_col - spell_col] = NUL;*/ ++ strtoichar(curr_word,line+spell_col,(curr_col-spell_col+1)*sizeof(ichar_t),0); ++ in_word = True; ++ ++/* for(i = 0; curr_word[i]; i++) ++ fprintf(stderr, "%c", curr_word[i]); ++ fprintf(stderr, "-%d\n", good((ichar_t *)curr_word, 0, 0, 0, 0)); wm */ ++ if(good((ichar_t *)curr_word, 0, 0, 0, 0) == 0) ++ last_attr = hl_attr(HLF_SPELL); ++ last_col = curr_col; ++ } ++ } ++ return(last_attr); ++} ++ ++int ++my_is_char(ccc) ++ char_u ccc; ++{ ++ if(iswordch((ichar_t)ccc) || isboundarych((ichar_t)ccc)) ++ return(TRUE); ++ else ++ return(FALSE); ++ ++} ++ ++static ichar_t *itok; ++ ++int ++set_to_private_dict(char *line, int cursor_col, int convert_to_lower) ++ ++{ ++ int i; ++ char_u *b, ++ *e; ++ ++ b = line + cursor_col; ++ e = b; ++ if(inited == 0) ++ return(TRUE); ++ if(iswordch((ichar_t)(*b)) || isboundarych((ichar_t)(*b))) ++ { ++ while((iswordch((ichar_t)(*(b - 1))) || ++ isboundarych((ichar_t)(*(b - 1)))) && ++ cursor_col > 0) ++ b--, cursor_col--; ++ while(isboundarych((ichar_t)(*b))) ++ b++; ++ while((iswordch((ichar_t)(*(e))) || isboundarych((ichar_t)(*(e)))) && ++ *e) ++ e++; ++ while(isboundarych((ichar_t)(*(e - 1)))) ++ e--; ++ for(i = 0; b < e;) ++ word_to_spell[i++] = *b++; ++ word_to_spell[i] = '\0'; ++ if(!convert_to_lower) ++ treeinsert (ichartosstr (strtosichar (word_to_spell, 0), 1), ++ ICHARTOSSTR_SIZE, 1); ++ else ++ { ++ itok = strtosichar (word_to_spell, 0); ++ lowcase (itok); ++ treeinsert (ichartosstr (itok, 1), ICHARTOSSTR_SIZE, 1); ++ } ++ redraw_all_later(NOT_VALID); ++ } ++ return(FALSE); ++} ++ ++void ++spell_save_private_dict(void) ++ ++{ ++ if(inited) ++ treeoutput (); ++} ++#endif +diff -Nur vim60am.old/src/syntax.c vim60am/src/syntax.c +--- vim60am.old/src/syntax.c Wed Jul 4 20:42:09 2001 ++++ vim60am/src/syntax.c Tue Jul 3 18:34:18 2001 +@@ -5771,6 +5771,9 @@ + "VertSplit term=reverse cterm=reverse gui=reverse", + "Visual term=reverse cterm=reverse gui=reverse guifg=Grey guibg=fg", + "VisualNOS term=underline,bold cterm=underline,bold gui=underline,bold", ++#ifdef FEAT_SPELL_HL ++ "Spell term=reverse ctermbg=NONE ctermfg=White guibg=NONE guifg=Red", ++#endif + "DiffText term=reverse cterm=bold ctermbg=Red gui=bold guibg=Red", + NULL + }; +@@ -5790,6 +5793,9 @@ + "Folded term=standout ctermbg=Grey ctermfg=DarkBlue guibg=LightGrey guifg=DarkBlue", + "FoldColumn term=standout ctermbg=Grey ctermfg=DarkBlue guibg=Grey guifg=DarkBlue", + "DiffAdd term=bold ctermbg=LightBlue guibg=LightBlue", ++#ifdef FEAT_SPELL_HL ++ "Spell term=reverse ctermbg=NONE ctermfg=White guibg=NONE guifg=Red", ++#endif + "DiffChange term=bold ctermbg=LightMagenta guibg=LightMagenta", + "DiffDelete term=bold ctermfg=Blue ctermbg=LightCyan gui=bold guifg=Blue guibg=LightCyan", + NULL +@@ -5810,6 +5816,9 @@ + "Folded term=standout ctermbg=DarkGrey ctermfg=Cyan guibg=DarkGrey guifg=Cyan", + "FoldColumn term=standout ctermbg=DarkGrey ctermfg=Cyan guibg=Grey guifg=Cyan", + "DiffAdd term=bold ctermbg=DarkBlue guibg=DarkBlue", ++#ifdef FEAT_SPELL_HL ++ "Spell term=reverse ctermbg=NONE ctermfg=White guibg=NONE guifg=Red", ++#endif + "DiffChange term=bold ctermbg=DarkMagenta guibg=DarkMagenta", + "DiffDelete term=bold ctermfg=Blue ctermbg=DarkCyan gui=bold guifg=Blue guibg=DarkCyan", + NULL +diff -Nur vim60am.old/src/version.c vim60am/src/version.c +--- vim60am.old/src/version.c Wed Jul 4 20:42:09 2001 ++++ vim60am/src/version.c Tue Jul 3 18:33:34 2001 +@@ -416,6 +416,11 @@ + #else + "-syntax", + #endif ++#ifdef FEAT_SPELL_HL ++ "+spell", ++#else ++ "-spell", ++#endif + /* only interesting on Unix systems */ + #if defined(USE_SYSTEM) && (defined(UNIX) || defined(__EMX__)) + "+system()", +@@ -953,7 +958,7 @@ + int add_version; + int attr; + { +- char_u vers[20]; ++ char_u vers[80]; + int col; + char_u *p; + int l; +diff -Nur vim60am.old/src/version.h vim60am/src/version.h +--- vim60am.old/src/version.h Wed Jul 4 20:42:09 2001 ++++ vim60am/src/version.h Tue Jul 3 19:04:36 2001 +@@ -33,6 +33,10 @@ + */ + #define VIM_VERSION_NODOT "vim60aq" + #define VIM_VERSION_SHORT "6.0aq" ++#ifdef FEAT_SPELL_HL ++#define VIM_VERSION_MEDIUM "6.0aq BETA + ispell 3.1.20 WM-3" ++#else + #define VIM_VERSION_MEDIUM "6.0aq BETA" ++#endif + #define VIM_VERSION_LONG "VIM - Vi IMproved 6.0aq BETA (2001 Aug 5)" + #define VIM_VERSION_LONG_DATE "VIM - Vi IMproved 6.0aq BETA (2001 Aug 5, compiled " +diff -Nur vim60am.old/src/vim.h vim60am/src/vim.h +--- vim60am.old/src/vim.h Wed Jul 4 20:42:09 2001 ++++ vim60am/src/vim.h Tue Jul 3 18:21:26 2001 +@@ -980,13 +980,14 @@ + , HLF_CHD /* Changed diff line */ + , HLF_DED /* Deleted diff line */ + , HLF_TXD /* Text Changed in diff line */ ++ , HLF_SPELL /* spell - string not in dictionary WM */ + , HLF_COUNT /* MUST be the last one */ + }; + + /* the HL_FLAGS must be in the same order as the HLF_ enums! */ + #define HL_FLAGS {'8', '@', 'd', 'e', 'h', 'i', 'l', 'm', 'M', \ + 'n', 'r', 's', 'S', 'c', 't', 'v', 'V', 'w', 'W', \ +- 'f', 'F', 'A', 'C', 'D', 'T'} ++ 'f', 'F', 'A', 'C', 'D', 'T', 'Z'} + + /* + * Boolean constants diff --git a/vim.spec b/vim.spec index 2a18e07..2e74744 100644 --- a/vim.spec +++ b/vim.spec @@ -5,6 +5,7 @@ # _without_motif - without Motif-based gvim # _without_gtk - without gtk+-based gvim support # _without_gnome - without gnome-based gvim support +# _with_ispell - with spell checking (non-standard feature; disables RIGHTLEFT and FKMAP) # Summary: Vi IMproved - a Vi clone Summary(de): VIsual editor iMproved @@ -33,6 +34,7 @@ Patch0: %{name}-sysconfdir.patch Patch1: %{name}-visual.patch Patch2: %{name}-phphighlight.patch Patch3: %{name}-paths.patch +Patch4: %{name}-ispell.patch URL: http://www.vim.org/ BuildRequires: gpm-devel BuildRequires: ncurses-devel @@ -215,6 +217,7 @@ biblioteki GNOME. %patch1 -p1 %patch2 -p1 %patch3 -p1 +%{?_with_ispell:%patch4 -p1} %build cd src -- 2.44.0