summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2005-04-20 19:37:22 +0000
committerBram Moolenaar <Bram@vim.org>2005-04-20 19:37:22 +0000
commit2cf8b301df39f742c07d10dadbbe19218dcc1845 (patch)
tree21b7335c37fdcde16ea27ee645406fa2548ab5e0 /src
parent2c5bc17eb722da0257d125fae18e48ab0122f460 (diff)
downloadvim-2cf8b301df39f742c07d10dadbbe19218dcc1845.zip
updated for version 7.0069
Diffstat (limited to 'src')
-rw-r--r--src/normal.c9
-rw-r--r--src/spell.c442
2 files changed, 344 insertions, 107 deletions
diff --git a/src/normal.c b/src/normal.c
index 85d84c45b..e5404ef53 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -6071,9 +6071,14 @@ nv_brackets(cap)
*/
else if (cap->nchar == 's' || cap->nchar == 'S')
{
- if (spell_move_to(cap->cmdchar == ']' ? FORWARD : BACKWARD,
+ setpcmark();
+ for (n = 0; n < cap->count1; ++n)
+ if (spell_move_to(cap->cmdchar == ']' ? FORWARD : BACKWARD,
cap->nchar == 's' ? TRUE : FALSE) == FAIL)
- clearopbeep(cap->oap);
+ {
+ clearopbeep(cap->oap);
+ break;
+ }
}
#endif
diff --git a/src/spell.c b/src/spell.c
index 618b4d390..cc71b8d7d 100644
--- a/src/spell.c
+++ b/src/spell.c
@@ -203,6 +203,7 @@ typedef struct langp_S
#define BWF_ALLCAP 0x0400 /* all letters must be capital (not used
for single-letter words) */
#define BWF_KEEPCAP 0x0800 /* Keep case as-is */
+#define BWF_ADDS_M 0x1000 /* there are more than 255 additions */
#define BWF_ADDHASH 0x8000 /* Internal: use hashtab for additions */
@@ -212,6 +213,8 @@ typedef struct langp_S
/* flags used for addition in the spell file */
#define ADD_REGION 0x02 /* region byte follows */
#define ADD_ONECAP 0x04 /* first letter must be capital */
+#define ADD_LEADLEN 0x10 /* there is a leadlen byte */
+#define ADD_COPYLEN 0x20 /* there is a copylen byte */
#define ADD_ALLCAP 0x40 /* all letters must be capital (not used
for single-letter words) */
#define ADD_KEEPCAP 0x80 /* fixed case */
@@ -220,7 +223,7 @@ typedef struct langp_S
* (Needed to keep ADD_ flags in one byte.) */
#define ADD2BWF(x) (((x) & 0x0f) | (((x) & 0xf0) << 4))
-#define VIMSPELLMAGIC "VIMspell02" /* string at start of Vim spell file */
+#define VIMSPELLMAGIC "VIMspell03" /* string at start of Vim spell file */
#define VIMSPELLMAGICL 10
/*
@@ -1164,13 +1167,17 @@ spell_move_to(dir, allwords)
int dir; /* FORWARD or BACKWARD */
int allwords; /* TRUE for "[s" and "]s" */
{
- pos_T pos;
+ linenr_T lnum;
+ pos_T found_pos;
char_u *line;
char_u *p;
int wc;
int nwc;
int attr = 0;
int len;
+ int has_syntax = syntax_present(curbuf);
+ int col;
+ int can_spell;
if (!curwin->w_p_spell || *curwin->w_buffer->b_p_spl == NUL)
{
@@ -1178,37 +1185,81 @@ spell_move_to(dir, allwords)
return FAIL;
}
- /* TODO: moving backwards */
-
- /* Start looking for bad word at the start of the line, because we can't
- * start halfway a word and know where it ends. */
- pos = curwin->w_cursor;
- pos.col = 0;
- wc = FALSE;
+ /*
+ * Start looking for bad word at the start of the line, because we can't
+ * start halfway a word, we don't know where it starts or ends.
+ *
+ * When searching backwards, we continue in the line to find the last
+ * bad word (in the cursor line: before the cursor).
+ */
+ lnum = curwin->w_cursor.lnum;
+ found_pos.lnum = 0;
while (!got_int)
{
- line = ml_get(pos.lnum);
- p = line + pos.col;
+ line = ml_get(lnum);
+ p = line;
+ wc = FALSE;
+
while (*p != NUL)
{
nwc = spell_iswordc(p);
if (!wc && nwc)
{
+ /* When searching backward don't search after the cursor. */
+ if (dir == BACKWARD
+ && lnum == curwin->w_cursor.lnum
+ && (colnr_T)(p - line) >= curwin->w_cursor.col)
+ break;
+
/* start of word */
- /* TODO: check for bad word attr */
len = spell_check(curwin, line, p, &attr);
+
if (attr != 0)
{
- if (curwin->w_cursor.lnum < pos.lnum
- || (curwin->w_cursor.lnum == pos.lnum
- && curwin->w_cursor.col < (colnr_T)(p - line)))
+ /* We found a bad word. Check the attribute. */
+ /* TODO: check for syntax @Spell cluster. */
+ if (allwords || attr == highlight_attr[HLF_SPB])
{
- curwin->w_cursor.lnum = pos.lnum;
- curwin->w_cursor.col = p - line;
- return OK;
+ /* When searching forward only accept a bad word after
+ * the cursor. */
+ if (dir == BACKWARD
+ || lnum > curwin->w_cursor.lnum
+ || (lnum == curwin->w_cursor.lnum
+ && (colnr_T)(p - line)
+ > curwin->w_cursor.col))
+ {
+ if (has_syntax)
+ {
+ col = p - line;
+ (void)syn_get_id(lnum, (colnr_T)col,
+ FALSE, &can_spell);
+
+ /* have to get the line again, a multi-line
+ * regexp may make it invalid */
+ line = ml_get(lnum);
+ p = line + col;
+ }
+ else
+ can_spell = TRUE;
+
+ if (can_spell)
+ {
+ found_pos.lnum = lnum;
+ found_pos.col = p - line;
+#ifdef FEAT_VIRTUALEDIT
+ found_pos.coladd = 0;
+#endif
+ if (dir == FORWARD)
+ {
+ /* No need to search further. */
+ curwin->w_cursor = found_pos;
+ return OK;
+ }
+ }
+ }
}
- attr = 0; /* bad word is before or at cursor */
+ attr = 0;
}
p += len;
if (*p == NUL)
@@ -1222,11 +1273,24 @@ spell_move_to(dir, allwords)
}
/* Advance to next line. */
- if (pos.lnum == curbuf->b_ml.ml_line_count)
- return FAIL;
- ++pos.lnum;
- pos.col = 0;
- wc = FALSE;
+ if (dir == BACKWARD)
+ {
+ if (found_pos.lnum != 0)
+ {
+ /* Use the last match in the line. */
+ curwin->w_cursor = found_pos;
+ return OK;
+ }
+ if (lnum == 1)
+ return FAIL;
+ --lnum;
+ }
+ else
+ {
+ if (lnum == curbuf->b_ml.ml_line_count)
+ return FAIL;
+ ++lnum;
+ }
line_breakcheck();
}
@@ -1773,7 +1837,10 @@ formerr:
fw->fw_adds = NULL;
if (flags & BWF_ADDS)
{
- adds = (getc(fd) << 8) + getc(fd); /* <addcnt> */
+ if (flags & BWF_ADDS_M)
+ adds = (getc(fd) << 8) + getc(fd); /* <addcnt> */
+ else
+ adds = getc(fd); /* <addcnt> */
if (adds > 30)
{
@@ -1795,8 +1862,8 @@ formerr:
while (--adds >= 0)
{
- /* <add>: <addflags> <addlen> [<leadlen> <addstring>]
- * [<region>] */
+ /* <add>: <addflags> <addlen> [<leadlen>] [<copylen>]
+ * [<addstring>] [<region>] */
flags = getc(fd); /* <addflags> */
addlen = getc(fd); /* <addlen> */
if (addlen == EOF)
@@ -1804,15 +1871,21 @@ formerr:
if (addlen >= MAXWLEN)
goto formerr;
+ if (flags & ADD_LEADLEN)
+ leadlen = getc(fd); /* <leadlen> */
+ else
+ leadlen = 0;
+
if (addlen > 0)
{
- leadlen = getc(fd); /* <leadlen> */
- for (i = 0; i < addlen; ++i) /* <addstring> */
+ if (flags & ADD_COPYLEN)
+ i = getc(fd); /* <copylen> */
+ else
+ i = 0;
+ for ( ; i < addlen; ++i) /* <addstring> */
cbuf[i] = getc(fd);
cbuf[i] = NUL;
}
- else
- leadlen = 0;
if (flags & ADD_KEEPCAP)
{
@@ -2292,6 +2365,20 @@ typedef struct affhash_S
static affhash_T dumas;
#define HI2AS(hi) ((affhash_T *)((hi)->hi_key - (dumas.as_word - (char_u *)&dumas)))
+/* info for writing the spell file */
+typedef struct winfo_S
+{
+ FILE *wif_fd;
+ basicword_T *wif_prevbw; /* last written basic word */
+ int wif_regionmask; /* regions supported */
+ int wif_prefm; /* 1 or 2 bytes used for prefix NR */
+ int wif_suffm; /* 1 or 2 bytes used for suffix NR */
+ long wif_wcount; /* written word count */
+ long wif_acount; /* written addition count */
+ long wif_addmax; /* max number of additions on one word */
+ char_u *wif_addmaxw; /* word with max additions */
+} winfo_T;
+
static afffile_T *spell_read_aff __ARGS((char_u *fname, vimconv_T *conv, int ascii));
static void spell_free_aff __ARGS((afffile_T *aff));
@@ -2313,7 +2400,7 @@ static void put_bytes __ARGS((FILE *fd, long_u nr, int len));
static void write_affix __ARGS((FILE *fd, affheader_T *ah));
static void write_affixlist __ARGS((FILE *fd, garray_T *aff, int bytes));
static void write_vim_spell __ARGS((char_u *fname, garray_T *prefga, garray_T *suffga, hashtab_T *newwords, int regcount, char_u *regchars));
-static void write_bword __ARGS((FILE *fd, basicword_T *bw, int lowcap, basicword_T **prevbw, int regionmask, int prefm, int suffm));
+static void write_bword __ARGS((winfo_T *wif, basicword_T *bw, int lowcap));
static void free_wordtable __ARGS((hashtab_T *ht));
static void free_basicword __ARGS((basicword_T *bw));
static void free_affixentries __ARGS((affentry_T *first));
@@ -4019,7 +4106,7 @@ write_affixlist(fd, aff, bytes)
*
* <HEADER>: <fileID> <regioncnt> <regionname> ...
*
- * <fileID> 10 bytes "VIMspell02"
+ * <fileID> 10 bytes "VIMspell03"
* <regioncnt> 1 byte number of regions following (8 supported)
* <regionname> 2 bytes Region name: ca, au, etc.
* First <regionname> is region 1.
@@ -4085,6 +4172,8 @@ write_affixlist(fd, aff, bytes)
* BWF_PREFIX
* 0x04: all letters must be upper-case, BWF_ALLCAP
* 0x08: case must match, BWF_KEEPCAP
+ * 0x10: has more than 255 additions, <addcnt> is two
+ * bytes, BWF_ADDS_M
* 0x10-0x80: unset
* <caselen> 1 byte Length of <caseword>.
* <caseword> N bytes Word with matching case.
@@ -4094,20 +4183,23 @@ write_affixlist(fd, aff, bytes)
* <region> 1 byte Bitmask for regions in which word is valid. When
* omitted it's valid in all regions.
* Lowest bit is for region 1.
- * <addcnt> 2 bytes Number of <add> items following.
+ * <addcnt> 1 or 2 byte Number of <add> items following.
*
- * <add>: <addflags> <addlen> [<leadlen> <addstring>] [<region>]
+ * <add>: <addflags> <addlen> [<leadlen>] [<copylen>] [<addstring>] [<region>]
*
* <addflags> 1 byte 0x01: unset
* 0x02: has region byte, ADD_REGION
* 0x04: first letter must be upper-case, ADD_ONECAP
- * 0x08-0x20: unset
+ * 0x08: unset
+ * 0x10: has a <leadlen>, ADD_LEADLEN
+ * 0x20: has a <copylen>, ADD_COPYLEN
* 0x40: all letters must be upper-case, ADD_ALLCAP
* 0x80: fixed case, <addstring> is the whole word
* with matching case, ADD_KEEPCAP.
* <addlen> 1 byte Length of <addstring> in bytes.
* <leadlen> 1 byte Number of bytes at start of <addstring> that must
* come before the start of the basic word.
+ * <copylen> 1 byte Number of bytes copied from previous <addstring>.
* <addstring> N bytes Word characters, before/in/after the word.
*
* All text characters are in 'encoding': <affchop>, <affadd>, <string>,
@@ -4128,48 +4220,48 @@ write_vim_spell(fname, prefga, suffga, newwords, regcount, regchars)
int regcount; /* number of regions */
char_u *regchars; /* region names */
{
- FILE *fd;
+ winfo_T wif;
garray_T *gap;
hashitem_T *hi;
char_u **wtab;
int todo;
int flags, aflags;
- basicword_T *bw, *bwf, *bw2 = NULL, *prevbw = NULL;
- int regionmask; /* mask for all relevant region bits */
+ basicword_T *bw, *bwf, *bw2 = NULL;
int i;
int cnt;
affentry_T *ae;
int round;
- int prefm, suffm;
garray_T bwga;
- fd = fopen((char *)fname, "w");
- if (fd == NULL)
+ vim_memset(&wif, 0, sizeof(winfo_T));
+
+ wif.wif_fd = fopen((char *)fname, "w");
+ if (wif.wif_fd == NULL)
{
EMSG2(_(e_notopen), fname);
return;
}
- fwrite(VIMSPELLMAGIC, VIMSPELLMAGICL, (size_t)1, fd);
+ fwrite(VIMSPELLMAGIC, VIMSPELLMAGICL, (size_t)1, wif.wif_fd);
/* write the region names if there is more than one */
if (regcount > 1)
{
- putc(regcount, fd);
- fwrite(regchars, (size_t)(regcount * 2), (size_t)1, fd);
- regionmask = (1 << regcount) - 1;
+ putc(regcount, wif.wif_fd);
+ fwrite(regchars, (size_t)(regcount * 2), (size_t)1, wif.wif_fd);
+ wif.wif_regionmask = (1 << regcount) - 1;
}
else
{
- putc(0, fd);
- regionmask = 0;
+ putc(0, wif.wif_fd);
+ wif.wif_regionmask = 0;
}
/* Write the prefix and suffix lists. */
for (round = 1; round <= 2; ++round)
{
gap = round == 1 ? prefga : suffga;
- put_bytes(fd, (long_u)gap->ga_len, 2); /* <affcount> */
+ put_bytes(wif.wif_fd, (long_u)gap->ga_len, 2); /* <affcount> */
/* Count the total number of affix items. */
cnt = 0;
@@ -4177,27 +4269,28 @@ write_vim_spell(fname, prefga, suffga, newwords, regcount, regchars)
for (ae = ((affheader_T *)gap->ga_data + i)->ah_first;
ae != NULL; ae = ae->ae_next)
++cnt;
- put_bytes(fd, (long_u)cnt, 2); /* <afftotcnt> */
+ put_bytes(wif.wif_fd, (long_u)cnt, 2); /* <afftotcnt> */
for (i = 0; i < gap->ga_len; ++i)
- write_affix(fd, (affheader_T *)gap->ga_data + i);
+ write_affix(wif.wif_fd, (affheader_T *)gap->ga_data + i);
}
/* Number of bytes used for affix NR depends on affix count. */
- prefm = (prefga->ga_len > 256) ? 2 : 1;
- suffm = (suffga->ga_len > 256) ? 2 : 1;
+ wif.wif_prefm = (prefga->ga_len > 256) ? 2 : 1;
+ wif.wif_suffm = (suffga->ga_len > 256) ? 2 : 1;
/* Write the suggest info. TODO */
- put_bytes(fd, 0L, 4);
+ put_bytes(wif.wif_fd, 0L, 4);
/*
* Write the word list. <wordcount> <worditem> ...
*/
/* number of basic words in 4 bytes */
- put_bytes(fd, newwords->ht_used, 4); /* <wordcount> */
+ put_bytes(wif.wif_fd, newwords->ht_used, 4); /* <wordcount> */
/*
- * Sort the word list, so that we can reuse as many bytes as possible.
+ * Sort the word list, so that we can copy as many bytes as possible from
+ * the previous word.
*/
wtab = (char_u **)alloc((unsigned)(sizeof(char_u *) * newwords->ht_used));
if (wtab != NULL)
@@ -4279,23 +4372,78 @@ write_vim_spell(fname, prefga, suffga, newwords, regcount, regchars)
* without VALID flag first (makes it easier to read the list back
* in). */
if (bw->bw_flags & BWF_KEEPCAP)
- write_bword(fd, bw, TRUE, &prevbw, regionmask, prefm, suffm);
- write_bword(fd, bw, FALSE, &prevbw, regionmask, prefm, suffm);
+ write_bword(&wif, bw, TRUE);
+ write_bword(&wif, bw, FALSE);
/* Write other basic words, with different caps. */
for (i = 0; i < bwga.ga_len; ++i)
{
bw2 = ((basicword_T **)bwga.ga_data)[i];
if (bw2 != bw)
- write_bword(fd, bw2, FALSE, &prevbw, regionmask,
- prefm, suffm);
+ write_bword(&wif, bw2, FALSE);
}
}
ga_clear(&bwga);
}
- fclose(fd);
+ fclose(wif.wif_fd);
+
+ /* Print a few statistics. */
+ if (wif.wif_addmaxw == NULL)
+ wif.wif_addmaxw = (char_u *)"";
+ smsg((char_u *)_("Maximum number of adds on a word: %ld (%s)"),
+ wif.wif_addmax, wif.wif_addmaxw);
+ smsg((char_u *)_("Average number of adds on a word: %f"),
+ (float)wif.wif_acount / (float)wif.wif_wcount);
+}
+
+/*
+ * Compare two basic words for their <addstring>.
+ */
+static int
+#ifdef __BORLANDC__
+_RTLENTRYF
+#endif
+bw_compare __ARGS((const void *s1, const void *s2));
+
+ static int
+#ifdef __BORLANDC__
+_RTLENTRYF
+#endif
+bw_compare(s1, s2)
+ const void *s1;
+ const void *s2;
+{
+ basicword_T *bw1 = *(basicword_T **)s1;
+ basicword_T *bw2 = *(basicword_T **)s2;
+ int i = 0;
+
+ /* compare the leadstrings */
+ if (bw1->bw_leadstring == NULL)
+ {
+ if (bw2->bw_leadstring != NULL)
+ return 1;
+ }
+ else if (bw2->bw_leadstring == NULL)
+ return -1;
+ else
+ i = STRCMP(bw1->bw_leadstring, bw2->bw_leadstring);
+
+ if (i == 0)
+ {
+ /* leadstrings are identical, compare the addstrings */
+ if (bw1->bw_addstring == NULL)
+ {
+ if (bw2->bw_addstring != NULL)
+ return 1;
+ }
+ else if (bw2->bw_addstring == NULL)
+ return -1;
+ else
+ i = STRCMP(bw1->bw_addstring, bw2->bw_addstring);
+ }
+ return i;
}
/*
@@ -4309,34 +4457,36 @@ write_vim_spell(fname, prefga, suffga, newwords, regcount, regchars)
* [<addcnt> <add> ...]
*/
static void
-write_bword(fd, bwf, lowcap, prevbw, regionmask, prefm, suffm)
- FILE *fd;
+write_bword(wif, bwf, lowcap)
+ winfo_T *wif; /* info for writing */
basicword_T *bwf;
int lowcap; /* write KEEPKAP word as not-valid */
- basicword_T **prevbw; /* last written basic word */
- int regionmask; /* mask that includes all possible regions */
- int prefm;
- int suffm;
{
+ FILE *fd = wif->wif_fd;
int flags;
int aflags;
int len;
int leadlen, addlen;
+ int copylen;
int clen;
int adds = 0;
int i;
+ int idx;
basicword_T *bw, *bw2;
+ basicword_T **wtab;
+ int count;
+ int l;
/* Check how many bytes can be copied from the previous word. */
len = STRLEN(bwf->bw_word);
- if (*prevbw == NULL)
+ if (wif->wif_prevbw == NULL)
clen = 0;
else
for (clen = 0; clen < len
- && (*prevbw)->bw_word[clen] == bwf->bw_word[clen]; ++clen)
+ && wif->wif_prevbw->bw_word[clen] == bwf->bw_word[clen]; ++clen)
;
putc(clen, fd); /* <nr> */
- *prevbw = bwf;
+ wif->wif_prevbw = bwf;
/* <string> */
if (len > clen)
fwrite(bwf->bw_word + clen, (size_t)(len - clen), (size_t)1, fd);
@@ -4360,7 +4510,8 @@ write_bword(fd, bwf, lowcap, prevbw, regionmask, prefm, suffm)
/* Flags: add the region byte if the word isn't valid in all
* regions. */
- if (regionmask != 0 && (bw->bw_region & regionmask) != regionmask)
+ if (wif->wif_regionmask != 0 && (bw->bw_region & wif->wif_regionmask)
+ != wif->wif_regionmask)
flags |= BWF_REGION;
}
/* Add the prefix/suffix list if there are prefixes/suffixes. */
@@ -4371,7 +4522,11 @@ write_bword(fd, bwf, lowcap, prevbw, regionmask, prefm, suffm)
/* Flags: may have additions. */
if (adds > 0)
+ {
flags |= BWF_ADDS;
+ if (adds >= 256)
+ flags |= BWF_ADDS_M;
+ }
/* The dummy word before a KEEPCAP word doesn't have any flags, they are
* in the actual word that follows. */
@@ -4403,56 +4558,133 @@ write_bword(fd, bwf, lowcap, prevbw, regionmask, prefm, suffm)
/* write prefix and suffix lists: <affixcnt> <affixNR> ... */
if (flags & BWF_PREFIX)
- write_affixlist(fd, &bw->bw_prefix, prefm);
+ write_affixlist(fd, &bw->bw_prefix, wif->wif_prefm);
if (flags & BWF_SUFFIX)
- write_affixlist(fd, &bw->bw_suffix, suffm);
+ write_affixlist(fd, &bw->bw_suffix, wif->wif_suffm);
if (flags & BWF_REGION)
putc(bw->bw_region, fd); /* <region> */
+ ++wif->wif_wcount;
+
/*
* Additions.
*/
if (adds > 0)
{
- put_bytes(fd, (long_u)adds, 2); /* <addcnt> */
+ if (adds >= 256)
+ put_bytes(fd, (long_u)adds, 2); /* 2 byte <addcnt> */
+ else
+ putc(adds, fd); /* 1 byte <addcnt> */
+ /* statistics */
+ wif->wif_acount += adds;
+ if (wif->wif_addmax < adds)
+ {
+ wif->wif_addmax = adds;
+ wif->wif_addmaxw = bw->bw_word;
+ }
+
+ /*
+ * Sort the list of additions, so that we can copy as many bytes as
+ * possible from the previous addstring.
+ */
+
+ /* Make a table with pointers to each basic word that has additions. */
+ wtab = (basicword_T **)alloc((unsigned)(sizeof(basicword_T *) * adds));
+ if (wtab == NULL)
+ return;
+ count = 0;
for (bw = bwf; bw != NULL; bw = bw->bw_cnext)
if (bw->bw_leadstring != NULL || bw->bw_addstring != NULL)
+ wtab[count++] = bw;
+
+ /* Sort. */
+ qsort((void *)wtab, (size_t)count, sizeof(basicword_T *), bw_compare);
+
+ /* Now write each basic word to the spell file. Copy bytes from the
+ * previous leadstring/addstring if possible. */
+ bw2 = NULL;
+ for (idx = 0; idx < count; ++idx)
+ {
+ bw = wtab[idx];
+
+ /* <add>: <addflags> <addlen> [<leadlen>] [<copylen>]
+ * [<addstring>] [<region>] */
+ copylen = 0;
+ if (bw->bw_leadstring == NULL)
+ leadlen = 0;
+ else
{
- /* <add>: <addflags> <addlen> [<leadlen> <addstring>]
- * [<region>] */
- aflags = 0;
- if (bw->bw_flags & BWF_ONECAP)
- aflags |= ADD_ONECAP;
- if (bw->bw_flags & BWF_ALLCAP)
- aflags |= ADD_ALLCAP;
- if (bw->bw_flags & BWF_KEEPCAP)
- aflags |= ADD_KEEPCAP;
- if (regionmask != 0
- && (bw->bw_region & regionmask) != regionmask)
- aflags |= ADD_REGION;
- putc(aflags, fd); /* <addflags> */
-
- if (bw->bw_leadstring == NULL)
- leadlen = 0;
- else
- leadlen = STRLEN(bw->bw_leadstring);
- if (bw->bw_addstring == NULL)
- addlen = 0;
+ leadlen = STRLEN(bw->bw_leadstring);
+ if (bw2 != NULL && bw2->bw_leadstring != NULL)
+ for ( ; copylen < leadlen; ++copylen)
+ if (bw->bw_leadstring[copylen]
+ != bw2->bw_leadstring[copylen])
+ break;
+ }
+ if (bw->bw_addstring == NULL)
+ addlen = 0;
+ else
+ {
+ addlen = STRLEN(bw->bw_addstring);
+ if (bw2 != NULL && copylen == leadlen
+ && bw2->bw_addstring != NULL)
+ {
+ for (i = 0; i < addlen; ++i)
+ if (bw->bw_addstring[i] != bw2->bw_addstring[i])
+ break;
+ copylen += i;
+ }
+ }
+
+ aflags = 0;
+ /* Only copy bytes when it's more than one, the length itself
+ * takes an extra byte. */
+ if (copylen > 1)
+ aflags |= ADD_COPYLEN;
+ else
+ copylen = 0;
+
+ if (bw->bw_flags & BWF_ONECAP)
+ aflags |= ADD_ONECAP;
+ if (bw->bw_flags & BWF_ALLCAP)
+ aflags |= ADD_ALLCAP;
+ if (bw->bw_flags & BWF_KEEPCAP)
+ aflags |= ADD_KEEPCAP;
+ if (wif->wif_regionmask != 0 && (bw->bw_region
+ & wif->wif_regionmask) != wif->wif_regionmask)
+ aflags |= ADD_REGION;
+ if (leadlen > 0)
+ aflags |= ADD_LEADLEN;
+ putc(aflags, fd); /* <addflags> */
+
+ putc(leadlen + addlen, fd); /* <addlen> */
+ if (aflags & ADD_LEADLEN)
+ putc(leadlen, fd); /* <leadlen> */
+ if (aflags & ADD_COPYLEN)
+ putc(copylen, fd); /* <copylen> */
+
+ /* <addstring> */
+ if (leadlen > copylen && bw->bw_leadstring != NULL)
+ fwrite(bw->bw_leadstring + copylen,
+ (size_t)(leadlen - copylen), (size_t)1, fd);
+ if (leadlen + addlen > copylen && bw->bw_addstring != NULL)
+ {
+ if (copylen >= leadlen)
+ l = copylen - leadlen;
else
- addlen = STRLEN(bw->bw_addstring);
- putc(leadlen + addlen, fd); /* <addlen> */
- putc(leadlen, fd); /* <leadlen> */
- /* <addstring> */
- if (bw->bw_leadstring != NULL)
- fwrite(bw->bw_leadstring, (size_t)leadlen, (size_t)1, fd);
- if (bw->bw_addstring != NULL)
- fwrite(bw->bw_addstring, (size_t)addlen, (size_t)1, fd);
-
- if (aflags & ADD_REGION)
- putc(bw->bw_region, fd); /* <region> */
+ l = 0;
+ fwrite(bw->bw_addstring + l,
+ (size_t)(addlen - l), (size_t)1, fd);
}
+
+ if (aflags & ADD_REGION)
+ putc(bw->bw_region, fd); /* <region> */
+
+ bw2 = bw;
+ }
+ vim_free(wtab);
}
}