]> git.pld-linux.org Git - packages/vim.git/commitdiff
- added ispell patch with online spell checking feature
authorJakub Bogusz <qboosh@pld-linux.org>
Mon, 6 Aug 2001 22:48:19 +0000 (22:48 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
  (conditional as it's non-standard feature and not heavily tested)

Changed files:
    vim-ispell.patch -> 1.1
    vim.spec -> 1.75

vim-ispell.patch [new file with mode: 0644]
vim.spec

diff --git a/vim-ispell.patch b/vim-ispell.patch
new file mode 100644 (file)
index 0000000..0bba1fc
--- /dev/null
@@ -0,0 +1,7232 @@
+diff -Nur vim60am.old/src/Makefile vim60am/src/Makefile
+--- vim60am.old/src/Makefile   Wed Jul  4 20:42:09 2001
++++ vim60am/src/Makefile       Tue Jul  3 18:55:58 2001
+@@ -1077,6 +1077,22 @@
+ # Use this for cproto 3 patchlevel 7 or above (use "cproto -V" to check):
+ PROTO_FLAGS = -m -M__ARGS -d -E"$(CPP)" $(NO_ATTR)
++SPELL_SRC = spell.c \
++      spell/good.c \
++      spell/lookup.c \
++      spell/hash.c \
++      spell/makedent.c \
++      spell/tree.c \
++      spell/tgood.c \
++      spell/util.c 
++SPELL_OBJ = objects/spell.o \
++      objects/good.o \
++      objects/lookup.o \
++      objects/hash.o \
++      objects/makedent.o \
++      objects/tree.o \
++      objects/tgood.o \
++      objects/util.o 
+ ################################################
+ ##   no changes required below this line      ##
+@@ -1087,7 +1103,7 @@
+ .SUFFIXES:
+ .SUFFIXES: .cc .c .o .pro
+-PRE_DEFS = -Iproto $(DEFS) $(GUI_DEFS) $(GUI_IPATH) $(CPPFLAGS) $(EXTRA_IPATHS)
++PRE_DEFS = -Iproto -Ispell $(DEFS) $(GUI_DEFS) $(GUI_IPATH) $(CPPFLAGS) $(EXTRA_IPATHS)
+ POST_DEFS = $(X_CFLAGS) $(PERL_CFLAGS) $(PYTHON_CFLAGS) $(TCL_CFLAGS) $(RUBY_CFLAGS) $(EXTRA_DEFS)
+ ALL_CFLAGS = $(PRE_DEFS) $(CFLAGS) $(POST_DEFS)
+@@ -1167,6 +1183,7 @@
+       screen.c \
+       search.c \
+       syntax.c \
++      $(SPELL_SRC) \
+       tag.c \
+       term.c \
+       ui.c \
+@@ -1232,6 +1249,7 @@
+       objects/screen.o \
+       objects/search.o \
+       objects/syntax.o \
++      $(SPELL_OBJ) \
+       $(SNIFF_OBJ) \
+       objects/tag.o \
+       objects/term.o \
+@@ -2094,6 +2112,9 @@
+ objects/undo.o: undo.c
+       $(CCC) -o $@ undo.c
++objects/spell.o: spell.c spell/local.h
++      $(CCC) -o $@ spell.c
++
+ objects/window.o: window.c
+       $(CCC) -o $@ window.c
+@@ -2212,6 +2233,9 @@
+ objects/search.o: search.c vim.h auto/config.h feature.h os_unix.h \
+  auto/osdef.h ascii.h keymap.h term.h macros.h structs.h regexp.h \
+  gui.h option.h ex_cmds.h proto.h globals.h farsi.h
++objects/spell.o: spell.c vim.h spell/config.h feature.h os_unix.h auto/osdef.h ascii.h \
++ keymap.h term.h macros.h regexp.h structs.h gui.h globals.h farsi.h \
++ option.h ex_cmds.h proto.h spell/local.h spell/wm.h spell/ispell.h
+ objects/syntax.o: syntax.c vim.h auto/config.h feature.h os_unix.h \
+  auto/osdef.h ascii.h keymap.h term.h macros.h structs.h regexp.h \
+  gui.h option.h ex_cmds.h proto.h globals.h farsi.h
+@@ -2334,3 +2358,26 @@
+ objects/integration.o: integration.c vim.h auto/config.h feature.h os_unix.h \
+  auto/osdef.h ascii.h keymap.h term.h macros.h structs.h regexp.h \
+  gui.h option.h ex_cmds.h proto.h globals.h farsi.h integration.h
++
++SPELL_CFLAGS=$(CFLAGS) -pedantic -DUSG=1
++ 
++objects/good.o: spell/good.c spell/config.h spell/ispell.h spell/i_proto.h spell/msgs.h spell/local.h
++      $(CC) -c $(SPELL_CFLAGS) spell/good.c -o objects/good.o
++
++objects/lookup.o: spell/lookup.c spell/config.h spell/ispell.h spell/i_proto.h spell/msgs.h spell/local.h
++      $(CC) -c $(SPELL_CFLAGS) spell/lookup.c -o objects/lookup.o
++
++objects/hash.o: spell/hash.c spell/config.h spell/ispell.h spell/i_proto.h spell/local.h
++      $(CC) -c $(SPELL_CFLAGS) spell/hash.c -o objects/hash.o
++      
++objects/makedent.o: spell/makedent.c spell/config.h spell/ispell.h spell/i_proto.h spell/msgs.h spell/local.h
++      $(CC) -c $(SPELL_CFLAGS) spell/makedent.c -o objects/makedent.o
++
++objects/tree.o: spell/tree.c spell/config.h spell/ispell.h spell/i_proto.h spell/msgs.h spell/local.h
++      $(CC) -c $(SPELL_CFLAGS) spell/tree.c -o objects/tree.o
++      
++objects/tgood.o: spell/tgood.c spell/config.h spell/ispell.h spell/i_proto.h spell/local.h
++      $(CC) -c $(SPELL_CFLAGS) spell/tgood.c -o objects/tgood.o
++
++objects/util.o: spell/util.c spell/config.h spell/ispell.h spell/i_proto.h spell/local.h
++      $(CC) -c $(SPELL_CFLAGS) spell/util.c -o objects/util.o
+diff -Nur vim60am.old/src/edit.c vim60am/src/edit.c
+--- vim60am.old/src/edit.c     Wed Jul  4 20:42:09 2001
++++ vim60am/src/edit.c Tue Jul  3 18:50:12 2001
+@@ -613,7 +613,11 @@
+       if (c == Ctrl_V && ctrl_x_mode == CTRL_X_CMDLINE)
+           goto docomplete;
+ #endif
+-      if (c == Ctrl_V || c == Ctrl_Q)
++      if (c == Ctrl_V
++#ifndef FEAT_SPELL_HL    /* WM */
++              || c == Ctrl_Q
++#endif
++                              )
+       {
+           ins_ctrl_v();
+           c = Ctrl_V; /* pretend CTRL-V is last typed character */
+@@ -1133,6 +1137,20 @@
+               continue_status = 0;
+           break;
+ #endif /* FEAT_INS_EXPAND */
++#ifdef FEAT_SPELL_HL      /* WM */
++      case Ctrl_Q:
++          if(set_to_private_dict(
++              ml_get_buf(curbuf, curwin->w_cursor.lnum, FALSE),
++                                      curwin->w_cursor.col, FALSE))
++              vim_beep();
++          break;
++      case Ctrl_S:
++          if(set_to_private_dict(
++              ml_get_buf(curbuf, curwin->w_cursor.lnum, FALSE),
++                                      curwin->w_cursor.col, TRUE))
++              vim_beep();
++          break;
++#endif
+       case Ctrl_Y:            /* copy from previous line or scroll down */
+       case Ctrl_E:            /* copy from next line     or scroll up */
+diff -Nur vim60am.old/src/ex_cmds.h vim60am/src/ex_cmds.h
+--- vim60am.old/src/ex_cmds.h  Wed Jul  4 20:42:09 2001
++++ vim60am/src/ex_cmds.h      Tue Jul  3 18:49:12 2001
+@@ -700,6 +700,8 @@
+                       RANGE|WHOLEFOLD|EXTRA|CMDWIN|MODIFY),
+ EX(CMD_source,                "source",       ex_source,
+                       BANG|FILE1|TRLBAR|SBOXOK|CMDWIN),
++EX(CMD_spell,         "spell",        ex_spell,
++                      EXTRA|NOTRLCOM|CMDWIN),
+ EX(CMD_split,         "split",        ex_splitview,
+                       BANG|FILE1|RANGE|NOTADR|EDITCMD|ARGOPT|TRLBAR),
+ EX(CMD_sprevious,     "sprevious",    ex_previous,
+diff -Nur vim60am.old/src/ex_docmd.c vim60am/src/ex_docmd.c
+--- vim60am.old/src/ex_docmd.c Wed Jul  4 20:42:09 2001
++++ vim60am/src/ex_docmd.c     Tue Jul  3 18:47:38 2001
+@@ -218,6 +218,9 @@
+ #ifndef FEAT_SYN_HL
+ # define ex_syntax            ex_ni
+ #endif
++#ifndef FEAT_SPELL_HL
++# define ex_spell             ex_ni
++#endif
+ #ifndef FEAT_PERL
+ # define ex_perl              ex_ni
+ # define ex_perldo            ex_ni
+@@ -2546,6 +2549,12 @@
+           set_context_in_syntax_cmd(xp, arg);
+           break;
+ #endif
++#ifdef FEAT_SPELL_HL
++      case CMD_spell:
++          return arg;
++          break;
++#endif
++
+ #ifdef FEAT_EVAL
+       case CMD_let:
+       case CMD_if:
+diff -Nur vim60am.old/src/feature.h vim60am/src/feature.h
+--- vim60am.old/src/feature.h  Wed Jul  4 20:42:09 2001
++++ vim60am/src/feature.h      Tue Jul  3 18:46:14 2001
+@@ -315,6 +315,12 @@
+ # endif
+ # define FEAT_FKMAP
+ #endif
++#ifdef FEAT_BIG
++#undef FEAT_RIGHTLEFT
++#undef FEAT_FKMAP
++#define FEAT_SPELL_HL  /*WM*/
++#endif
++/* # define FEAT_PRINTER */
+ /*
+  * +emacs_tags                When FEAT_EMACS_TAGS defined: Include support for
+diff -Nur vim60am.old/src/globals.h vim60am/src/globals.h
+--- vim60am.old/src/globals.h  Wed Jul  4 20:42:09 2001
++++ vim60am/src/globals.h      Tue Jul  3 18:45:54 2001
+@@ -718,6 +718,9 @@
+ #ifdef USE_TERM_CONSOLE
+ EXTERN int    term_console INIT(= FALSE); /* set to TRUE when console used */
+ #endif
++#ifdef FEAT_SPELL_HL
++EXTERN char_u hashname[MAXPATHL];         /* name of the dictionary */
++#endif
+ EXTERN int    termcap_active INIT(= FALSE);   /* set by starttermcap() */
+ EXTERN int    cur_tmode INIT(= TMODE_COOK);   /* input terminal mode */
+ EXTERN int    bangredo INIT(= FALSE);     /* set to TRUE whith ! command */
+diff -Nur vim60am.old/src/main.c vim60am/src/main.c
+--- vim60am.old/src/main.c     Wed Jul  4 20:42:09 2001
++++ vim60am/src/main.c Tue Jul  3 18:45:08 2001
+@@ -1901,6 +1901,9 @@
+       }
+     }
+ #endif /* FEAT_VIMINFO */
++#ifdef FEAT_SPELL_HL
++    spell_save_private_dict();
++#endif
+ #ifdef FEAT_AUTOCMD
+     apply_autocmds(EVENT_VIMLEAVE, NULL, NULL, FALSE, curbuf);
+diff -Nur vim60am.old/src/normal.c vim60am/src/normal.c
+--- vim60am.old/src/normal.c   Wed Jul  4 20:42:09 2001
++++ vim60am/src/normal.c       Tue Jul  3 18:44:28 2001
+@@ -85,6 +85,10 @@
+ #ifdef FEAT_VISUAL
+ static int    get_visual_text __ARGS((cmdarg_T *cap, char_u **pp, int *lenp));
+ #endif
++#ifdef FEAT_SPELL_HL
++static void   nv_settodict_q __ARGS((cmdarg_T *cap));
++static void   nv_settodict_s __ARGS((cmdarg_T *cap));
++#endif
+ static void   nv_tagpop __ARGS((cmdarg_T *cap));
+ static void   nv_scroll __ARGS((cmdarg_T *cap));
+ static void   nv_kright __ARGS((cmdarg_T *cap));
+@@ -226,9 +230,17 @@
+     {Ctrl_N,  nv_down,        NV_STS,                 FALSE},
+     {Ctrl_O,  nv_ctrlo,       0,                      0},
+     {Ctrl_P,  nv_up,          NV_STS,                 FALSE},
++#ifdef FEAT_SPELL_HL
++    {Ctrl_Q,  nv_settodict_q, 0,                      0},
++#else
+     {Ctrl_Q,  nv_ignore,      0,                      0},
++#endif
+     {Ctrl_R,  nv_redo,        0,                      0},
++#ifdef FEAT_SPELL_HL
++    {Ctrl_S,  nv_settodict_s, 0,                      0},
++#else
+     {Ctrl_S,  nv_ignore,      0,                      0},
++#endif
+     {Ctrl_T,  nv_tagpop,      NV_NCW,                 0},
+     {Ctrl_U,  nv_halfpage,    0,                      0},
+ #ifdef FEAT_VISUAL
+@@ -7316,6 +7328,28 @@
+ #endif
+ }
++#ifdef FEAT_SPELL_HL
++static void
++nv_settodict_q(cap)
++    cmdarg_T  *cap;
++{    
++    if(set_to_private_dict(
++              ml_get_buf(curbuf, curwin->w_cursor.lnum, FALSE),
++                                      curwin->w_cursor.col, FALSE))
++      clearopbeep(cap->oap);
++}
++
++static void
++nv_settodict_s(cap)
++    cmdarg_T  *cap;
++{    
++    if(set_to_private_dict(
++              ml_get_buf(curbuf, curwin->w_cursor.lnum, FALSE),
++                                      curwin->w_cursor.col, TRUE))
++      clearopbeep(cap->oap);
++}         
++#endif
++ 
+ #ifdef FEAT_VISUAL
+ /*
+  * In exclusive Visual mode, may include the last character.
+diff -Nur vim60am.old/src/option.c vim60am/src/option.c
+--- vim60am.old/src/option.c   Wed Jul  4 20:42:09 2001
++++ vim60am/src/option.c       Tue Jul  3 18:42:14 2001
+@@ -116,6 +116,8 @@
+     , PV_SW
+     , PV_SWF
+     , PV_SYN
++    , PV_SPELL_DIR
++    , PV_SPELL_LANG
+     , PV_TAGS
+     , PV_TS
+     , PV_TSR
+@@ -216,6 +218,10 @@
+ #ifdef FEAT_SYN_HL
+ static char_u *p_syn;
+ #endif
++#ifdef FEAT_SPELL_HL
++static char_u *p_spelldirectory;
++static char_u *p_language;
++#endif
+ static long   p_ts;
+ static long   p_tw;
+ static int    p_tx;
+@@ -1001,7 +1007,7 @@
+                           {(char_u *)FALSE, (char_u *)0L}},
+     {"highlight",   "hl",   P_STRING|P_VI_DEF|P_RCLR|P_COMMA|P_NODUP,
+                           (char_u *)&p_hl, PV_NONE,
+-                          {(char_u *)"8:SpecialKey,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText",
++                          {(char_u *)"8:SpecialKey,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,Z:Spell",
+                               (char_u *)0L}},
+     {"history",           "hi",   P_NUM|P_VIM,
+                           (char_u *)&p_hi, PV_NONE,
+@@ -1247,6 +1253,13 @@
+                           (char_u *)NULL, PV_NONE,
+ #endif
+                           {(char_u *)"", (char_u *)0L}},
++    {"language",  "lang", P_STRING|P_ALLOCED|P_VI_DEF,
++#ifdef FEAT_SPELL_HL
++                          (char_u *)&p_language, PV_SPELL_LANG,
++#else
++                          (char_u *)NULL, PV_NONE,
++#endif
++                          {(char_u *)"", (char_u *)0L}},
+     {"laststatus",  "ls",   P_NUM|P_VI_DEF|P_RALL,
+ #ifdef FEAT_WINDOWS
+                           (char_u *)&p_ls, PV_NONE,
+@@ -1815,6 +1828,14 @@
+     {"sourceany",   NULL,   P_BOOL|P_VI_DEF,
+                           (char_u *)NULL, PV_NONE,
+                           {(char_u *)FALSE, (char_u *)0L}},
++    {"spelldirectory",  "spelldir", P_STRING|P_ALLOCED|P_VI_DEF|P_EXPAND,
++#ifdef FEAT_SPELL_HL
++                          (char_u *)&p_spelldirectory, PV_SPELL_DIR,
++                          {(char_u *)"/usr/lib/ispell", (char_u *)0L}},
++#else
++                          (char_u *)NULL, PV_NONE,
++                          {(char_u *)"", (char_u *)0L}},
++#endif
+     {"splitbelow",  "sb",   P_BOOL|P_VI_DEF,
+ #ifdef FEAT_WINDOWS
+                           (char_u *)&p_sb, PV_NONE,
+@@ -4337,6 +4357,26 @@
+           errmsg = e_invarg;
+     }
+ #endif
++#ifdef FEAT_SPELL_HL
++    else if (varp == &p_spell_dir)
++    {
++      STRCPY(hashname, p_spell_dir);
++      STRCAT(hashname, "/");
++      STRCAT(hashname, p_spell_lang);
++      STRCAT(hashname, ".hash");
++      reload_dict();
++      redraw_all_later(NOT_VALID);
++    }
++    else if (varp == &p_spell_lang)
++    {
++      STRCPY(hashname, p_spell_dir);
++      STRCAT(hashname, "/");
++      STRCAT(hashname, p_spell_lang);
++      STRCAT(hashname, ".hash");
++      reload_dict();
++      redraw_all_later(NOT_VALID);
++    }
++#endif
+ #ifdef FEAT_MBYTE
+     /* 'encoding' and 'fileencoding' */
+@@ -6998,6 +7038,10 @@
+       case PV_SWF:    return (char_u *)&(curbuf->b_p_swf);
+ #ifdef FEAT_SYN_HL
+       case PV_SYN:    return (char_u *)&(curbuf->b_p_syn);
++#endif
++#ifdef FEAT_SPELL_HL
++      case PV_SPELL_DIR:      return (char_u *)&(p_spell_dir);
++      case PV_SPELL_LANG:     return (char_u *)&(p_spell_lang);
+ #endif
+       case PV_SW:     return (char_u *)&(curbuf->b_p_sw);
+       case PV_TS:     return (char_u *)&(curbuf->b_p_ts);
+diff -Nur vim60am.old/src/option.h vim60am/src/option.h
+--- vim60am.old/src/option.h   Wed Jul  4 20:42:09 2001
++++ vim60am/src/option.h       Tue Jul  3 18:40:28 2001
+@@ -336,6 +336,8 @@
+ EXTERN char_u *p_dex;         /* 'diffexpr' */
+ # endif
+ #endif
++EXTERN char_u  *p_spell_dir;  /* directory with spell hash*/
++EXTERN char_u  *p_spell_lang; /* name of language (spell hash file)*/
+ #ifdef FEAT_INS_EXPAND
+ EXTERN char_u *p_dict;        /* 'dictionary' */
+ #endif
+diff -Nur vim60am.old/src/os_msdos.c vim60am/src/os_msdos.c
+--- vim60am.old/src/os_msdos.c Wed Jul  4 20:42:09 2001
++++ vim60am/src/os_msdos.c     Tue Jul  3 18:39:48 2001
+@@ -78,7 +78,7 @@
+  */
+ unsigned long S_ulScreenBase = 0xb8000;
+-unsigned short        S_uiAttribute = 0;
++unsigned short        S_uiAttribute =  7 << 8;
+ int           S_iCurrentRow = 0;      /* These are 0 offset */
+ int           S_iCurrentColumn = 0;
+ int           S_iLeft = 0;    /* Scroll window; these are 1 offset */
+@@ -248,6 +248,9 @@
+     }
+     else
+     {
++      if(iChar == ' ')
++      uiValue = ((S_uiAttribute & 0xf700) | 0x700) | ' ';
++      else
+       uiValue = S_uiAttribute | (unsigned char)iChar;
+       /*
+@@ -309,6 +312,7 @@
+ mytextattr(int iAttribute)
+ {
+     S_uiAttribute = (unsigned short)iAttribute << 8;
++    textattr(iAttribute);             /* for delline() etc */
+ }
+     static void
+@@ -322,6 +326,7 @@
+ {
+     S_uiAttribute = (unsigned short)((S_uiAttribute & 0xf000)
+                                          | (unsigned short)iTextColor << 8);
++    textattr(S_uiAttribute >> 8);     /* for delline() etc */
+ }
+     static void
+@@ -329,6 +334,7 @@
+ {
+     S_uiAttribute = (unsigned short)((S_uiAttribute & 0x0f00)
+                                        | (unsigned short)(iBkgColor << 12));
++    textattr(S_uiAttribute >> 8);     /* for delline() etc */
+ }
+ /*
+  * Getdigits: Get a number from a string and skip over it.
+@@ -470,6 +476,7 @@
+     static union REGS     regs;
+     static int                    saved = FALSE;
++    return;   /* WM */
+     if (restore)
+     {
+       if (saved)
+@@ -495,6 +502,7 @@
+ mch_set_cursor_shape(int thickness)
+ {
+     union REGS            regs;
++    return;   /* WM */
+     regs.h.ch = 7 - thickness;            /*Starting Line*/
+     regs.h.cl = 7;                /*Ending Line*/
+@@ -508,6 +516,7 @@
+     int               idx;
+     int               thickness;
++    return;   /* WM */
+     /*
+      * How the cursor is drawn depends on the current mode.
+      */
+@@ -2226,6 +2235,7 @@
+     char *
+ djgpp_setlocale(void)
+ {
++     char *country;
+     __dpmi_regs regs;
+     struct { char id; unsigned short off, seg; } __attribute__ ((packed)) info;
+     unsigned char buffer[0x82], lower, upper;
+@@ -2267,6 +2277,127 @@
+               __dj_ctype_tolower[upper+1] = lower;
+       }
+     }
++     if ((country = getenv("COUNTRY")) != NULL)
++        {
++         if(!strcmp(country, "MAZOWIA"))
++         {
++          __dj_ctype_flags[(unsigned char)'\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
index 2a18e0739d6c95a8165d8664285ca36e34e8f7db..2e747446115965e75e546d7e1627c53f29b056aa 100644 (file)
--- a/vim.spec
+++ b/vim.spec
@@ -5,6 +5,7 @@
 # _without_motif       - without Motif-based gvim
 # _without_gtk         - without gtk+-based gvim support
 # _without_gnome       - without gnome-based gvim support
+# _with_ispell         - with spell checking (non-standard feature; disables RIGHTLEFT and FKMAP)
 #
 Summary:       Vi IMproved - a Vi clone
 Summary(de):   VIsual editor iMproved
@@ -33,6 +34,7 @@ Patch0:               %{name}-sysconfdir.patch
 Patch1:                %{name}-visual.patch
 Patch2:                %{name}-phphighlight.patch
 Patch3:                %{name}-paths.patch
+Patch4:                %{name}-ispell.patch
 URL:           http://www.vim.org/
 BuildRequires: gpm-devel
 BuildRequires: ncurses-devel
@@ -215,6 +217,7 @@ biblioteki GNOME.
 %patch1 -p1
 %patch2 -p1
 %patch3 -p1
+%{?_with_ispell:%patch4 -p1}
 
 %build
 cd src
This page took 0.333957 seconds and 4 git commands to generate.