--- /dev/null
+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)'\86' + 1] = LOCASE;
++ __dj_ctype_flags[(unsigned char)'\8f' + 1] = UPCASE;
++ __dj_ctype_flags[(unsigned char)'\8d' + 1] = LOCASE;
++ __dj_ctype_flags[(unsigned char)'\95' + 1] = UPCASE;
++ __dj_ctype_flags[(unsigned char)'\91' + 1] = LOCASE;
++ __dj_ctype_flags[(unsigned char)'\90' + 1] = UPCASE;
++ __dj_ctype_flags[(unsigned char)'\92' + 1] = LOCASE;
++ __dj_ctype_flags[(unsigned char)'\9c' + 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)'\9e' + 1] = LOCASE;
++ __dj_ctype_flags[(unsigned char)'\98' + 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)'\86'+ 1] = (unsigned char)'\8f';
++ __dj_ctype_toupper[(unsigned char)'\8f'+ 1] = (unsigned char)'\8f';
++ __dj_ctype_toupper[(unsigned char)'\8d'+ 1] = (unsigned char)'\95';
++ __dj_ctype_toupper[(unsigned char)'\95'+ 1] = (unsigned char)'\95';
++ __dj_ctype_toupper[(unsigned char)'\91'+ 1] = (unsigned char)'\90';
++ __dj_ctype_toupper[(unsigned char)'\90'+ 1] = (unsigned char)'\90';
++ __dj_ctype_toupper[(unsigned char)'\92'+ 1] = (unsigned char)'\9c';
++ __dj_ctype_toupper[(unsigned char)'\9c'+ 1] = (unsigned char)'\9c';
++ __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)'\9e'+ 1] = (unsigned char)'\98';
++ __dj_ctype_toupper[(unsigned char)'\98'+ 1] = (unsigned char)'\98';
++ __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)'\86'+ 1] = (unsigned char)'\86';
++ __dj_ctype_tolower[(unsigned char)'\8f'+ 1] = (unsigned char)'\86';
++ __dj_ctype_tolower[(unsigned char)'\8d'+ 1] = (unsigned char)'\8d';
++ __dj_ctype_tolower[(unsigned char)'\95'+ 1] = (unsigned char)'\8d';
++ __dj_ctype_tolower[(unsigned char)'\91'+ 1] = (unsigned char)'\91';
++ __dj_ctype_tolower[(unsigned char)'\90'+ 1] = (unsigned char)'\91';
++ __dj_ctype_tolower[(unsigned char)'\92'+ 1] = (unsigned char)'\92';
++ __dj_ctype_tolower[(unsigned char)'\9c'+ 1] = (unsigned char)'\92';
++ __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)'\9e'+ 1] = (unsigned char)'\9e';
++ __dj_ctype_tolower[(unsigned char)'\98'+ 1] = (unsigned char)'\9e';
++ __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)'\1c' + 1] = LOCASE;
++ __dj_ctype_flags[(unsigned char)'\f' + 1] = UPCASE;
++ __dj_ctype_flags[(unsigned char)'\1f' + 1] = LOCASE;
++ __dj_ctype_flags[(unsigned char)'\ f' + 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)'\1c'+ 1] = (unsigned char)'\f';
++ __dj_ctype_toupper[(unsigned char)'\f'+ 1] = (unsigned char)'\f';
++ __dj_ctype_toupper[(unsigned char)'\1f'+ 1] = (unsigned char)'\ f';
++ __dj_ctype_toupper[(unsigned char)'\ f'+ 1] = (unsigned char)'\ f';
++ __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)'\1c'+ 1] = (unsigned char)'\1c';
++ __dj_ctype_tolower[(unsigned char)'\f'+ 1] = (unsigned char)'\1c';
++ __dj_ctype_tolower[(unsigned char)'\1f'+ 1] = (unsigned char)'\1f';
++ __dj_ctype_tolower[(unsigned char)'\ f'+ 1] = (unsigned char)'\1f';
++ __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);\r
++void ex_spell(exarg_T *eap);\r
++int get_spell_attr(colnr_T spell_col, colnr_T col, char_u *line);\r
++int set_to_private_dict(char *line, int cursor_col, int convert_to_lower);\r
++void spell_save_private_dict(void);\r
+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 <sys/param.h>
++#include <sys/types.h>
++#endif
++#ifndef USG
++# ifndef FEAT_SPELL_HL
++# if HAVE_DIRENT_H
++# include <dirent.h>
++# 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 <sys/ndir.h>
++# endif
++# if HAVE_SYS_DIR_H
++# include <sys/dir.h>
++# endif
++# if HAVE_NDIR_H
++# include <ndir.h>
++# 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:
++**
++** <language>[,<make-options>...] [<language> [,<make-options> ...] ...]
++**
++** 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 <sys/types.h>
++** #include <regex.h>
++** #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 <ctype.h>
++#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 <string.h>
++
++#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 <stdio.h>
++#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 <eliz@is.elta.co.il>
++ *
++ * 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:
++**
++** <language>[,<make-options>...] [<language> [,<make-options> ...] ...]
++**
++** 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 <sys/types.h>
++#include <regex.h>
++#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 <pc.h>
++#include <keys.h>
++#define GETKEYSTROKE() getxkey()
++#else
++#define GETKEYSTROKE() getchar()
++#endif
++
++/*
++** We include <fcntl.h> to have the definition of O_BINARY. The
++** configuration script will notice this and define MSDOS_BINARY_OPEN.
++*/
++#include <fcntl.h>
++
++/*
++** 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 <stdlib.h>
++#include <fcntl.h>
++#ifdef WIN32
++#include <io.h>
++#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 <stdlib.h>
++#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] <number> 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 <ctype.h>
++#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 <ctype.h>
++#include <stdlib.h>
++#include <errno.h>
++#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 <ctype.h>
++#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