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