+ new_size = dst - dst_buf;
+ if (p && p->cat != b->no_cat-1 &&
+ new_size > b->file[p->cat].head.block_max)
+ {
+ /* non-btree block will be removed */
+ close_block (b, p);
+ /* delete it too!! */
+ p = 0; /* make a new one anyway */
+ }
+ if (!p)
+ { /* must create a new one */
+ int i;
+ for (i = 0; i < b->no_cat; i++)
+ if (new_size <= b->file[i].head.block_max)
+ break;
+ if (i == b->no_cat)
+ i = b->no_cat - 1;
+ p = new_leaf (b, i);
+ }
+ if (new_size > b->file[p->cat].head.block_max)
+ {
+ char *first_dst;
+ char *cut_item = cut_item_buf;
+
+ assert (half1);
+ assert (half2);
+
+ /* first half */
+ p->size = half1 - dst_buf;
+ memcpy (p->bytes, dst_buf, half1 - dst_buf);
+
+ /* second half */
+ *sp2 = new_leaf (b, p->cat);
+
+ (*b->method->code_reset)(c2);
+
+ first_dst = (*sp2)->bytes;
+
+ (*b->method->code_item)(ISAMC_ENCODE, c2, &first_dst, &cut_item);
+
+ memcpy (first_dst, half2, dst - half2);
+
+ (*sp2)->size = (first_dst - (*sp2)->bytes) + (dst - half2);
+ (*sp2)->dirty = 1;
+ p->dirty = 1;
+ memcpy (sub_item, cut_item_buf, cut_item_size);
+ *sub_size = cut_item_size;
+ }
+ else
+ {
+ memcpy (p->bytes, dst_buf, dst - dst_buf);
+ p->size = new_size;
+ }
+ (*b->method->code_stop)(ISAMC_DECODE, c1);
+ (*b->method->code_stop)(ISAMC_ENCODE, c2);
+ *sp1 = p;
+ return more;
+}
+
+int insert_sub (ISAMB b, struct ISAMB_block **p, void *new_item,
+ ISAMC_I stream,
+ struct ISAMB_block **sp,
+ void *sub_item, int *sub_size,
+ void *max_item)
+{
+ if (!*p || (*p)->leaf)
+ return insert_leaf (b, p, new_item, stream, sp, sub_item, sub_size,
+ max_item);
+ else
+ return insert_int (b, *p, new_item, stream, sp, sub_item, sub_size);
+}
+
+int isamb_merge (ISAMB b, ISAMC_P pos, ISAMC_I stream)
+{
+ char item_buf[DST_ITEM_MAX];
+ char *item_ptr;
+ int i_mode;
+ int more;
+
+ item_ptr = item_buf;
+ more = (*stream->read_item)(stream->clientData, &item_ptr, &i_mode);
+ while (more)
+ {
+ struct ISAMB_block *p = 0, *sp = 0;
+ char sub_item[DST_ITEM_MAX];
+ int sub_size;
+
+ if (pos)
+ p = open_block (b, pos);
+ more = insert_sub (b, &p, item_buf, stream, &sp,
+ sub_item, &sub_size, 0);
+ if (sp)
+ { /* increase level of tree by one */
+ struct ISAMB_block *p2 = new_int (b, p->cat);
+ char *dst = p2->bytes + p2->size;
+
+ encode_ptr (&dst, p->pos);
+ assert (sub_size < 20);
+ encode_ptr (&dst, sub_size);
+ memcpy (dst, sub_item, sub_size);
+ dst += sub_size;
+ encode_ptr (&dst, sp->pos);
+
+ p2->size = dst - p2->bytes;
+ pos = p2->pos; /* return new super page */
+ close_block (b, sp);
+ close_block (b, p2);
+ }
+ else
+ pos = p->pos; /* return current one (again) */
+ close_block (b, p);
+ }
+ return pos;
+}
+
+ISAMB_PP isamb_pp_open (ISAMB isamb, ISAMB_P pos)
+{
+ ISAMB_PP pp = xmalloc (sizeof(*pp));
+
+ pp->isamb = isamb;
+ pp->block = xmalloc (10 * sizeof(*pp->block));
+
+ pp->level = 0;
+ while (1)
+ {
+ struct ISAMB_block *p = open_block (isamb, pos);
+ char *src = p->bytes + p->offset;
+ pp->block[pp->level] = p;
+
+ if (p->bytes[0]) /* leaf */
+ break;
+
+ decode_ptr (&src, &pos);
+ p->offset = src - p->bytes;
+ pp->level++;
+ }
+ pp->block[pp->level+1] = 0;
+ return pp;
+}
+
+void isamb_pp_close (ISAMB_PP pp)
+{
+ int i;
+ if (!pp)
+ return;
+ for (i = 0; i <= pp->level; i++)
+ close_block (pp->isamb, pp->block[i]);
+ xfree (pp->block);
+ xfree (pp);
+}
+
+int isamb_pp_read (ISAMB_PP pp, void *buf)
+{
+ char *dst = buf;
+ char *src;
+ struct ISAMB_block *p = pp->block[pp->level];
+ if (!p)
+ return 0;
+
+ while (p->offset == p->size)
+ {
+ int pos, item_len;
+ while (p->offset == p->size)
+ {
+ if (pp->level == 0)
+ return 0;
+ close_block (pp->isamb, pp->block[pp->level]);
+ pp->block[pp->level] = 0;
+ (pp->level)--;
+ p = pp->block[pp->level];
+ assert (p->bytes[0] == 0); /* must be int */
+ }
+ src = p->bytes + p->offset;
+
+ decode_ptr (&src, &item_len);
+ src += item_len;
+ decode_ptr (&src, &pos);
+
+ p->offset = src - (char*) p->bytes;
+
+ ++(pp->level);
+
+ while (1)
+ {
+ pp->block[pp->level] = p = open_block (pp->isamb, pos);
+
+ if (p->leaf) /* leaf */
+ {
+ break;
+ }
+ src = p->bytes + p->offset;
+ decode_ptr (&src, &pos);
+ p->offset = src - (char*) p->bytes;
+ pp->level++;
+ }
+ }
+ assert (p->offset < p->size);
+ assert (p->bytes[0]);
+ src = p->bytes + p->offset;
+ (*pp->isamb->method->code_item)(ISAMC_DECODE, p->decodeClientData,
+ &dst, &src);
+ p->offset = src - (char*) p->bytes;
+ return 1;
+}
+
+int isamb_pp_num (ISAMB_PP pp)
+{
+ return 1;