#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include "textBuf.h"
#include "textDisp.h"
#include "rangeset.h"
#include "../util/nedit_malloc.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifdef HAVE_DEBUG_H
#include "../debug.h"
#endif
struct _Range {
int start, end;
};
typedef Rangeset *RangesetUpdateFn(Rangeset *p,
int pos,
int ins,
int del);
struct _Rangeset {
RangesetUpdateFn *update_fn;
char *update_name;
int maxpos;
int last_index;
int n_ranges;
Range *ranges;
unsigned char label;
signed char color_set;
char *color_name;
XftColor color;
textBuffer *buf;
char *name;
};
struct _RangesetTable {
int n_set;
textBuffer *buf;
Rangeset set[
N_RANGESETS];
unsigned char order[
N_RANGESETS];
unsigned char active[
N_RANGESETS];
unsigned char depth[
N_RANGESETS];
unsigned char list[
N_RANGESETS +
1];
};
#define SWAPval(
T,a,b) {
T t; t = *(a); *(a) = *(b); *(b) = t; }
static unsigned char rangeset_labels[
N_RANGESETS +
1] = {
58,
10,
15,
1,
27,
52,
14,
3,
61,
13,
31,
30,
45,
28,
41,
55,
33,
20,
62,
34,
42,
18,
57,
47,
24,
49,
19,
50,
25,
38,
40,
2,
21,
39,
59,
22,
60,
4,
6,
16,
29,
37,
48,
46,
54,
43,
32,
56,
51,
7,
9,
63,
5,
8,
36,
44,
26,
11,
23,
17,
53,
35,
12,
0
};
static RangesetUpdateFn rangesetInsDelMaintain;
static RangesetUpdateFn rangesetInclMaintain;
static RangesetUpdateFn rangesetDelInsMaintain;
static RangesetUpdateFn rangesetExclMaintain;
static RangesetUpdateFn rangesetBreakMaintain;
#define DEFAULT_UPDATE_FN_NAME "maintain"
static struct {
char *name;
RangesetUpdateFn *update_fn;
} RangesetUpdateMap[] = {
{
DEFAULT_UPDATE_FN_NAME, rangesetInsDelMaintain},
{
"ins_del", rangesetInsDelMaintain},
{
"include", rangesetInclMaintain},
{
"del_ins", rangesetDelInsMaintain},
{
"exclude", rangesetExclMaintain},
{
"break", rangesetBreakMaintain},
{(
char *)
0, (RangesetUpdateFn *)
0}
};
static Range *RangesNew(
int n)
{
Range *newRanges;
if (n !=
0) {
n = (n >=
256) ? ((n +
64) & ~
63) : ((n +
16) & ~
15);
newRanges = (Range *)NEditMalloc(n *
sizeof (Range));
return newRanges;
}
return NULL;
}
static Range* RangesRealloc(Range* ranges,
int n)
{
int size;
Range* newRanges;
if (n >
0)
{
n = (n >=
256) ? ((n +
64) & ~
63) : ((n +
16) & ~
15);
size = n *
sizeof (Range);
newRanges = (Range*)NEditRealloc(ranges,size);
return newRanges;
}
else {
NEditFree(ranges);
}
return NULL;
}
static Range *RangesFree(Range *ranges)
{
NEditFree(ranges);
return NULL;
}
void RangesetRefreshRange(Rangeset *rangeset,
int start,
int end)
{
if (rangeset->buf !=
NULL)
BufCheckDisplay(rangeset->buf, start, end);
}
static void rangesetRefreshAllRanges(Rangeset *rangeset)
{
int i;
for (i =
0; i < rangeset->n_ranges; i++)
RangesetRefreshRange(rangeset, rangeset->ranges[i].start, rangeset->ranges[i].end);
}
void RangesetEmpty(Rangeset *rangeset)
{
Range *ranges = rangeset->ranges;
int start, end;
if (rangeset->color_name && rangeset->color_set >
0) {
rangeset->color_set = -
1;
while (rangeset->n_ranges--) {
start = ranges[rangeset->n_ranges].start;
end = ranges[rangeset->n_ranges].end;
RangesetRefreshRange(rangeset, start, end);
}
}
NEditFree(rangeset->color_name);
NEditFree(rangeset->name);
rangeset->color_name = (
char *)
0;
rangeset->name = (
char *)
0;
rangeset->ranges = RangesFree(rangeset->ranges);
}
void RangesetInit(Rangeset *rangeset,
int label, textBuffer *buf)
{
rangeset->label = (
unsigned char)label;
rangeset->maxpos =
0;
rangeset->last_index =
0;
rangeset->n_ranges =
0;
rangeset->ranges = (Range *)
0;
rangeset->color_name = (
char *)
0;
rangeset->name = (
char *)
0;
rangeset->color_set =
0;
rangeset->buf = buf;
rangeset->maxpos = buf->length;
RangesetChangeModifyResponse(rangeset,
DEFAULT_UPDATE_FN_NAME);
}
int RangesetChangeModifyResponse(Rangeset *rangeset,
char *name)
{
int i;
if (name ==
NULL)
name =
DEFAULT_UPDATE_FN_NAME;
for (i =
0; RangesetUpdateMap[i].name; i++)
if (strcmp(RangesetUpdateMap[i].name, name) ==
0) {
rangeset->update_fn = RangesetUpdateMap[i].update_fn;
rangeset->update_name = RangesetUpdateMap[i].name;
return 1;
}
return 0;
}
static int at_or_before(
int *table,
int base,
int len,
int val)
{
int lo, mid =
0, hi;
if (base >= len)
return len;
lo = base;
hi = len -
1;
while (lo <= hi) {
mid = (lo + hi) /
2;
if (val == table[mid])
return mid;
if (val < table[mid])
hi = mid -
1;
else
lo = mid +
1;
}
if (val > table[mid])
mid++;
return mid;
}
static int weighted_at_or_before(
int *table,
int base,
int len,
int val)
{
int lo, mid =
0, hi;
int min, max;
if (base >= len)
return len;
lo = base;
hi = len -
1;
min = table[lo];
max = table[hi];
if (val <= min)
return lo;
else if (val > max)
return len;
else if (val == max)
return hi;
while (lo <= hi) {
mid = lo + (
int)((hi - lo) * (
double)(val - min) / (max - min));
if (val == table[mid])
return mid;
if (val < table[mid]) {
hi = mid -
1;
max = table[mid];
}
else {
lo = mid +
1;
min = table[mid];
}
}
if (val > table[mid])
return mid +
1;
return mid;
}
int RangesetFindRangeNo(Rangeset *rangeset,
int index,
int *start,
int *end)
{
if (!rangeset || index <
0 || rangeset->n_ranges <= index || !rangeset->ranges)
return 0;
*start = rangeset->ranges[index].start;
*end = rangeset->ranges[index].end;
return 1;
}
int RangesetFindRangeOfPos(Rangeset *rangeset,
int pos,
int incl_end)
{
int *ranges;
int len, ind;
if (!rangeset || !rangeset->n_ranges || !rangeset->ranges)
return -
1;
ranges = (
int *)rangeset->ranges;
len = rangeset->n_ranges *
2;
ind = at_or_before(ranges,
0, len, pos);
if (ind == len)
return -
1;
if (ind &
1) {
if (pos < ranges[ind] || (incl_end && pos == ranges[ind]))
return ind /
2;
}
else {
if (pos == ranges[ind])
return ind /
2;
}
return -
1;
}
int RangesetCheckRangeOfPos(Rangeset *rangeset,
int pos)
{
int *ranges;
int len, index, last;
len = rangeset->n_ranges;
if (len ==
0)
return -
1;
ranges = (
int *)rangeset->ranges;
last = rangeset->last_index;
if (last >= len || last <
0) {
last = (len >
0) ? len -
1 :
0;
rangeset->last_index = last;
}
len *=
2;
last *=
2;
if (pos >= ranges[last]) {
if (pos < ranges[last +
1])
return last /
2;
else
last +=
2;
if (last == len)
return -
1;
index = weighted_at_or_before(ranges, last, len, pos);
}
else if (last >
0) {
index = weighted_at_or_before(ranges,
0, last, pos);
}
else
index =
0;
rangeset->last_index = index /
2;
if (index == len)
return -
1;
if (index &
1) {
if (pos < ranges[index])
return index /
2;
}
else {
if (pos == ranges[index])
return index /
2;
}
return -
1;
}
int RangesetAdd(Rangeset *origSet, Rangeset *plusSet)
{
Range *origRanges, *plusRanges, *newRanges, *oldRanges;
int nOrigRanges, nPlusRanges;
int isOld;
origRanges = origSet->ranges;
nOrigRanges = origSet->n_ranges;
plusRanges = plusSet->ranges;
nPlusRanges = plusSet->n_ranges;
if (nPlusRanges ==
0)
return nOrigRanges;
newRanges = RangesNew(nOrigRanges + nPlusRanges);
if (nOrigRanges ==
0) {
memcpy(newRanges, plusRanges, nPlusRanges *
sizeof (Range));
RangesFree(origSet->ranges);
origSet->ranges = newRanges;
origSet->n_ranges = nPlusRanges;
for (nOrigRanges =
0; nOrigRanges < nPlusRanges; nOrigRanges++) {
RangesetRefreshRange(origSet, newRanges->start, newRanges->end);
newRanges++;
}
return nPlusRanges;
}
oldRanges = origRanges;
origSet->ranges = newRanges;
origSet->n_ranges =
0;
isOld =
1;
while (nOrigRanges >
0 || nPlusRanges >
0) {
if (nOrigRanges ==
0 ||
(nPlusRanges >
0 && origRanges->start > plusRanges->start)) {
SWAPval(Range *, &origRanges, &plusRanges);
SWAPval(
int, &nOrigRanges, &nPlusRanges);
isOld = !isOld;
}
origSet->n_ranges++;
*newRanges = *origRanges++;
nOrigRanges--;
if (!isOld)
RangesetRefreshRange(origSet, newRanges->start, newRanges->end);
while (nPlusRanges >
0 && newRanges->end >= plusRanges->start) {
do {
if (newRanges->end < plusRanges->end) {
if (isOld)
RangesetRefreshRange(origSet, newRanges->end, plusRanges->end);
newRanges->end = plusRanges->end;
}
plusRanges++;
nPlusRanges--;
}
while (nPlusRanges >
0 && newRanges->end >= plusRanges->start);
SWAPval(Range *, &origRanges, &plusRanges);
SWAPval(
int, &nOrigRanges, &nPlusRanges);
isOld = !isOld;
}
newRanges++;
}
RangesFree(oldRanges);
origSet->ranges = RangesRealloc(origSet->ranges, origSet->n_ranges);
return origSet->n_ranges;
}
int RangesetRemove(Rangeset *origSet, Rangeset *minusSet)
{
Range *origRanges, *minusRanges, *newRanges, *oldRanges;
int nOrigRanges, nMinusRanges;
origRanges = origSet->ranges;
nOrigRanges = origSet->n_ranges;
minusRanges = minusSet->ranges;
nMinusRanges = minusSet->n_ranges;
if (nOrigRanges ==
0 || nMinusRanges ==
0)
return 0;
newRanges = RangesNew(origSet->n_ranges + minusSet->n_ranges);
oldRanges = origRanges;
origSet->ranges = newRanges;
origSet->n_ranges =
0;
while (nOrigRanges >
0) {
do {
while (nMinusRanges >
0
&& minusRanges->end <= origRanges->start) {
minusRanges++;
nMinusRanges--;
}
if (nMinusRanges >
0) {
while (nOrigRanges >
0
&& origRanges->end <= minusRanges->start) {
*newRanges++ = *origRanges++;
nOrigRanges--;
origSet->n_ranges++;
}
}
else {
while (nOrigRanges >
0) {
*newRanges++ = *origRanges++;
nOrigRanges--;
origSet->n_ranges++;
}
}
}
while (nMinusRanges >
0 && minusRanges->end <= origRanges->start);
if (nOrigRanges >
0) {
if (minusRanges->start <= origRanges->start) {
if (minusRanges->end < origRanges->end) {
RangesetRefreshRange(origSet, origRanges->start,
minusRanges->end);
origRanges->start = minusRanges->end;
minusRanges++;
nMinusRanges--;
}
else {
RangesetRefreshRange(origSet, origRanges->start,
origRanges->end);
origRanges++;
nOrigRanges--;
}
}
else {
newRanges->start = origRanges->start;
newRanges->end = minusRanges->start;
newRanges++;
origSet->n_ranges++;
if (minusRanges->end < origRanges->end) {
RangesetRefreshRange(origSet, minusRanges->start,
minusRanges->end);
origRanges->start = minusRanges->end;
minusRanges++;
nMinusRanges--;
}
else {
RangesetRefreshRange(origSet, minusRanges->start,
origRanges->end);
origRanges++;
nOrigRanges--;
}
}
}
}
RangesFree(oldRanges);
origSet->ranges = RangesRealloc(origSet->ranges, origSet->n_ranges);
return origSet->n_ranges;
}
int RangesetGetNRanges(Rangeset *rangeset)
{
return rangeset ? rangeset->n_ranges :
0;
}
void RangesetGetInfo(Rangeset *rangeset,
int *defined,
int *label,
int *count,
char **color,
char **name,
char **mode)
{
if (rangeset ==
NULL) {
*defined = False;
*label =
0;
*count =
0;
*color =
"";
*name =
"";
*mode =
"";
}
else {
*defined = True;
*label = (
int)rangeset->label;
*count = rangeset->n_ranges;
*color = rangeset->color_name ? rangeset->color_name :
"";
*name = rangeset->name ? rangeset->name :
"";
*mode = rangeset->update_name;
}
}
static Rangeset *rangesetFixMaxpos(Rangeset *rangeset,
int ins,
int del)
{
rangeset->maxpos += ins - del;
return rangeset;
}
RangesetTable *RangesetTableAlloc(textBuffer *buffer)
{
int i;
RangesetTable *table = (RangesetTable *)NEditMalloc(
sizeof (RangesetTable));
if (!table)
return table;
table->buf = buffer;
for (i =
0; i <
N_RANGESETS; i++) {
RangesetInit(&table->set[i], rangeset_labels[i], buffer);
table->order[i] = (
unsigned char)i;
table->active[i] =
0;
table->depth[i] = (
unsigned char)i;
}
table->n_set =
0;
table->list[
0] =
'\0';
BufAddHighPriorityModifyCB(buffer, RangesetBufModifiedCB, table);
return table;
}
RangesetTable *RangesetTableFree(RangesetTable *table)
{
int i;
if (table) {
BufRemoveModifyCB(table->buf, RangesetBufModifiedCB, table);
for (i =
0; i <
N_RANGESETS; i++)
RangesetEmpty(&table->set[i]);
NEditFree(table);
}
return (RangesetTable *)
0;
}
static void rangesetClone(Rangeset *destRangeset, Rangeset *srcRangeset)
{
destRangeset->update_fn = srcRangeset->update_fn;
destRangeset->update_name = srcRangeset->update_name;
destRangeset->maxpos = srcRangeset->maxpos;
destRangeset->last_index = srcRangeset->last_index;
destRangeset->n_ranges = srcRangeset->n_ranges;
destRangeset->color_set = srcRangeset->color_set;
destRangeset->color = srcRangeset->color;
if (srcRangeset->color_name) {
destRangeset->color_name = (
char*)NEditMalloc(strlen(srcRangeset->color_name) +
1);
strcpy(destRangeset->color_name, srcRangeset->color_name);
}
if (srcRangeset->name) {
destRangeset->name = (
char*)NEditMalloc(strlen(srcRangeset->name) +
1);
strcpy(destRangeset->name, srcRangeset->name);
}
if (srcRangeset->ranges) {
destRangeset->ranges = RangesNew(srcRangeset->n_ranges);
memcpy(destRangeset->ranges, srcRangeset->ranges,
srcRangeset->n_ranges *
sizeof(Range));
}
}
RangesetTable *RangesetTableClone(RangesetTable *srcTable,
textBuffer *destBuffer)
{
RangesetTable *newTable =
NULL;
int i;
if (srcTable ==
NULL)
return NULL;
newTable = RangesetTableAlloc(destBuffer);
newTable->n_set = srcTable->n_set;
memcpy(newTable->order, srcTable->order,
sizeof(
unsigned char) *
N_RANGESETS);
memcpy(newTable->active, srcTable->active,
sizeof(
unsigned char) *
N_RANGESETS);
memcpy(newTable->depth, srcTable->depth,
sizeof(
unsigned char) *
N_RANGESETS);
memcpy(newTable->list, srcTable->list,
sizeof(
unsigned char) *(
N_RANGESETS +
1));
for (i =
0; i <
N_RANGESETS; i++)
rangesetClone(&newTable->set[i], &srcTable->set[i]);
return newTable;
}
int RangesetFindIndex(RangesetTable *table,
int label,
int must_be_active)
{
int i;
unsigned char *p_label;
if(label ==
0) {
return -
1;
}
if (table !=
NULL) {
p_label = (
unsigned char*)strchr((
char*)rangeset_labels, label);
if (p_label) {
i = p_label - rangeset_labels;
if (!must_be_active || table->active[i])
return i;
}
}
return -
1;
}
static void RangesetTableListSet(RangesetTable *table)
{
int i;
for (i =
0; i < table->n_set; i++)
table->list[i] = rangeset_labels[(
int)table->order[i]];
table->list[table->n_set] =
'\0';
}
int RangesetLabelOK(
int label)
{
return strchr((
char*)rangeset_labels, label) !=
NULL;
}
static int activateRangeset(RangesetTable *table,
int active)
{
int depth, i, j;
if (table->active[active])
return 0;
depth = table->depth[active];
for (i = depth; i >
0; i--) {
j = table->order[i] = table->order[i -
1];
table->depth[j] = i;
}
table->order[
0] = active;
table->depth[active] =
0;
table->active[active] =
1;
table->n_set++;
RangesetTableListSet(table);
return 1;
}
static int deactivateRangeset(RangesetTable *table,
int active)
{
int depth, n, i, j;
if (!table->active[active])
return 0;
depth = table->depth[active];
n = table->n_set -
1;
for (i = depth; i < n; i++) {
j = table->order[i] = table->order[i +
1];
table->depth[j] = i;
}
table->order[n] = active;
table->depth[active] = n;
table->active[active] =
0;
table->n_set--;
RangesetTableListSet(table);
return 1;
}
int nRangesetsAvailable(RangesetTable *table)
{
return(
N_RANGESETS - table->n_set);
}
int RangesetCreate(RangesetTable *table)
{
int label;
int setIndex;
size_t firstAvailableIndex = strspn((
char*)rangeset_labels, (
char*)table->list);
if(firstAvailableIndex >=
sizeof(rangeset_labels))
return 0;
label = rangeset_labels[firstAvailableIndex];
setIndex = RangesetFindIndex(table, label,
0);
if (setIndex <
0)
return 0;
if (table->active[setIndex])
return label;
if (activateRangeset(table, setIndex))
RangesetInit(&table->set[setIndex],
rangeset_labels[setIndex], table->buf);
return label;
}
Rangeset *RangesetForget(RangesetTable *table,
int label)
{
int set_ind = RangesetFindIndex(table, label,
1);
if (set_ind <
0)
return (Rangeset *)
0;
if (deactivateRangeset(table, set_ind))
RangesetEmpty(&table->set[set_ind]);
return &table->set[set_ind];
}
Rangeset *RangesetFetch(RangesetTable *table,
int label)
{
int rangesetIndex = RangesetFindIndex(table, label,
0);
if (rangesetIndex <
0)
return (Rangeset *)
NULL;
if (table->active[rangesetIndex])
return &table->set[rangesetIndex];
else
return (Rangeset *)
NULL;
}
unsigned char *RangesetGetList(RangesetTable *table)
{
return table ? table->list : (
unsigned char *)
"";
}
void RangesetTableUpdatePos(RangesetTable *table,
int pos,
int ins,
int del)
{
int i;
Rangeset *p;
if (!table || (ins ==
0 && del ==
0))
return;
for (i =
0; i < table->n_set; i++) {
p = &table->set[(
int)table->order[i]];
p->update_fn(p, pos, ins, del);
}
}
void RangesetBufModifiedCB(
int pos,
int nInserted,
int nDeleted,
int nRestyled,
const char *deletedText,
void *cbArg)
{
RangesetTable *table = (RangesetTable *)cbArg;
if ((nInserted != nDeleted) || BufCmp(table->buf, pos, nInserted, deletedText) !=
0) {
RangesetTableUpdatePos(table, pos, nInserted, nDeleted);
}
}
int RangesetIndex1ofPos(RangesetTable *table,
int pos,
int needs_color)
{
int i;
Rangeset *rangeset;
if (!table)
return 0;
for (i =
0; i < table->n_set; i++) {
rangeset = &table->set[(
int)table->order[i]];
if (RangesetCheckRangeOfPos(rangeset, pos) >=
0) {
if (needs_color && rangeset->color_set >=
0 && rangeset->color_name)
return table->order[i] +
1;
}
}
return 0;
}
int RangesetAssignColorName(Rangeset *rangeset,
char *color_name)
{
char *cp;
if (color_name && color_name[
0] ==
'\0')
color_name = (
char *)
0;
if (color_name) {
cp = (
char*)NEditMalloc(strlen(color_name) +
1);
strcpy(cp, color_name);
}
else
cp = color_name;
NEditFree(rangeset->color_name);
rangeset->color_name = cp;
rangeset->color_set =
0;
rangesetRefreshAllRanges(rangeset);
return 1;
}
int RangesetAssignName(Rangeset *rangeset,
char *name)
{
char *cp;
if (name && name[
0] ==
'\0')
name = (
char *)
0;
if (name) {
cp = (
char*)NEditMalloc(strlen(name) +
1);
strcpy(cp, name);
}
else {
cp = name;
}
NEditFree(rangeset->name);
rangeset->name = cp;
return 1;
}
int RangesetAssignColorPixel(Rangeset *rangeset, XftColor color,
int ok)
{
rangeset->color_set = ok ?
1 : -
1;
rangeset->color = color;
return 1;
}
char *RangesetGetName(Rangeset *rangeset)
{
return rangeset->name;
}
int RangesetGetColorValid(Rangeset *rangeset, XftColor *color)
{
*color = rangeset->color;
return rangeset->color_set;
}
char *RangesetTableGetColorName(RangesetTable *table,
int index)
{
Rangeset *rangeset = &table->set[index];
return rangeset->color_name;
}
int RangesetTableGetColorValid(RangesetTable *table,
int index, XftColor *color, Rangeset **rs)
{
Rangeset *rangeset = &table->set[index];
*color = rangeset->color;
*rs = rangeset;
return rangeset->color_set;
}
Rangeset* RangesetTableAssignColorPixel(RangesetTable *table,
int index, XftColor color,
int ok)
{
Rangeset *rangeset = &table->set[index];
rangeset->color_set = ok ?
1 : -
1;
rangeset->color = color;
return rangeset;
}
XftColor* RangesetGetColor(Rangeset *rangeset)
{
return &rangeset->color;
}
#define is_start(i) !((i) &
1)
#define is_end(i) ((i) &
1)
static int rangesetWeightedAtOrBefore(Rangeset *rangeset,
int pos)
{
int i, last, n, *rangeTable = (
int *)rangeset->ranges;
n = rangeset->n_ranges;
if (n ==
0)
return 0;
last = rangeset->last_index;
if (last >= n || last <
0)
last =
0;
n *=
2;
last *=
2;
if (pos >= rangeTable[last])
i = weighted_at_or_before(rangeTable, last, n, pos);
else
i = weighted_at_or_before(rangeTable,
0, last, pos);
rangeset->last_index = i /
2;
return i;
}
static int rangesetShuffleToFrom(
int *rangeTable,
int to,
int from,
int n,
int delta)
{
int end, diff = from - to;
if (n <=
0)
return 0;
if (delta !=
0) {
if (diff >
0) {
for (end = to + n; to < end; to++)
rangeTable[to] = rangeTable[to + diff] + delta;
}
else if (diff <
0) {
for (end = to, to += n; --to >= end;)
rangeTable[to] = rangeTable[to + diff] + delta;
}
else {
for (end = n; end--;)
rangeTable[to++] += delta;
}
}
else {
if (diff >
0) {
for (end = to + n; to < end; to++)
rangeTable[to] = rangeTable[to + diff];
}
else if (diff <
0) {
for (end = to, to += n; --to >= end;)
rangeTable[to] = rangeTable[to + diff];
}
}
return n;
}
static Rangeset *rangesetInsDelMaintain(Rangeset *rangeset,
int pos,
int ins,
int del)
{
int i, j, n, *rangeTable = (
int *)rangeset->ranges;
int end_del, movement;
n =
2 * rangeset->n_ranges;
i = rangesetWeightedAtOrBefore(rangeset, pos);
if (i == n)
return rangesetFixMaxpos(rangeset, ins, del);
end_del = pos + del;
movement = ins - del;
j = i;
while (j < n && rangeTable[j] <= end_del)
j++;
if (j > i)
rangeTable[i] = pos + ins;
if (is_start(i) != is_start(j))
i++;
rangesetShuffleToFrom(rangeTable, i, j, n - j, movement);
n -= j - i;
rangeset->n_ranges = n /
2;
rangeset->ranges = RangesRealloc(rangeset->ranges, rangeset->n_ranges);
return rangesetFixMaxpos(rangeset, ins, del);
}
static Rangeset *rangesetInclMaintain(Rangeset *rangeset,
int pos,
int ins,
int del)
{
int i, j, n, *rangeTable = (
int *)rangeset->ranges;
int end_del, movement;
n =
2 * rangeset->n_ranges;
i = rangesetWeightedAtOrBefore(rangeset, pos);
if (i == n)
return rangesetFixMaxpos(rangeset, ins, del);
if (is_start(i) && rangeTable[i] == pos && ins >
0)
i++;
end_del = pos + del;
movement = ins - del;
j = i;
while (j < n && rangeTable[j] <= end_del)
j++;
if (j > i)
rangeTable[i] = pos + ins;
if (is_start(i) != is_start(j))
i++;
rangesetShuffleToFrom(rangeTable, i, j, n - j, movement);
n -= j - i;
rangeset->n_ranges = n /
2;
rangeset->ranges = RangesRealloc(rangeset->ranges, rangeset->n_ranges);
return rangesetFixMaxpos(rangeset, ins, del);
}
static Rangeset *rangesetDelInsMaintain(Rangeset *rangeset,
int pos,
int ins,
int del)
{
int i, j, n, *rangeTable = (
int *)rangeset->ranges;
int end_del, movement;
n =
2 * rangeset->n_ranges;
i = rangesetWeightedAtOrBefore(rangeset, pos);
if (i == n)
return rangesetFixMaxpos(rangeset, ins, del);
end_del = pos + del;
movement = ins - del;
j = i;
while (j < n && rangeTable[j] <= end_del)
j++;
if (j > i)
rangeTable[i] = (is_end(j)) ? pos + ins : pos;
if (is_start(i) != is_start(j))
i++;
rangesetShuffleToFrom(rangeTable, i, j, n - j, movement);
n -= j - i;
rangeset->n_ranges = n /
2;
rangeset->ranges = RangesRealloc(rangeset->ranges, rangeset->n_ranges);
return rangesetFixMaxpos(rangeset, ins, del);
}
static Rangeset *rangesetExclMaintain(Rangeset *rangeset,
int pos,
int ins,
int del)
{
int i, j, n, *rangeTable = (
int *)rangeset->ranges;
int end_del, movement;
n =
2 * rangeset->n_ranges;
i = rangesetWeightedAtOrBefore(rangeset, pos);
if (i == n)
return rangesetFixMaxpos(rangeset, ins, del);
if (is_end(i) && rangeTable[i] == pos && ins >
0)
i++;
end_del = pos + del;
movement = ins - del;
j = i;
while (j < n && rangeTable[j] <= end_del)
j++;
if (j > i)
rangeTable[i] = (is_end(j)) ? pos + ins : pos;
if (is_start(i) != is_start(j))
i++;
rangesetShuffleToFrom(rangeTable, i, j, n - j, movement);
n -= j - i;
rangeset->n_ranges = n /
2;
rangeset->ranges = RangesRealloc(rangeset->ranges, rangeset->n_ranges);
return rangesetFixMaxpos(rangeset, ins, del);
}
static Rangeset *rangesetBreakMaintain(Rangeset *rangeset,
int pos,
int ins,
int del)
{
int i, j, n, *rangeTable = (
int *)rangeset->ranges;
int end_del, movement, need_gap;
n =
2 * rangeset->n_ranges;
i = rangesetWeightedAtOrBefore(rangeset, pos);
if (i == n)
return rangesetFixMaxpos(rangeset, ins, del);
if (is_end(i) && rangeTable[i] == pos && ins >
0)
i++;
end_del = pos + del;
movement = ins - del;
j = i;
while (j < n && rangeTable[j] <= end_del)
j++;
if (j > i)
rangeTable[i] = pos;
need_gap = (is_end(i) && is_end(j) && ins >
0);
if (is_start(i) != is_start(j)) {
if (is_start(i)) {
if (rangeTable[i] == pos)
rangeTable[i] = pos + ins;
}
i++;
}
if (need_gap)
i +=
2;
rangesetShuffleToFrom(rangeTable, i, j, n - j, movement);
if (need_gap) {
rangeTable[i -
2] = pos;
rangeTable[i -
1] = pos + ins;
}
n -= j - i;
rangeset->n_ranges = n /
2;
rangeset->ranges = RangesRealloc(rangeset->ranges, rangeset->n_ranges);
return rangesetFixMaxpos(rangeset, ins, del);
}
int RangesetInverse(Rangeset *rangeset)
{
int *rangeTable;
int n, has_zero, has_end;
if (!rangeset)
return -
1;
rangeTable = (
int *)rangeset->ranges;
if (rangeset->n_ranges ==
0) {
if (!rangeTable) {
rangeset->ranges = RangesNew(
1);
rangeTable = (
int *)rangeset->ranges;
}
rangeTable[
0] =
0;
rangeTable[
1] = rangeset->maxpos;
n =
2;
}
else {
n = rangeset->n_ranges *
2;
has_zero = (rangeTable[
0] ==
0);
has_end = (rangeTable[n -
1] == rangeset->maxpos);
rangeTable[n +
1] = rangeTable[n] = rangeset->maxpos;
if (has_zero) {
rangesetShuffleToFrom(rangeTable,
0,
1, n,
0);
n -=
1;
}
else {
rangesetShuffleToFrom(rangeTable,
1,
0, n,
0);
rangeTable[
0] =
0;
n +=
1;
}
if (has_end)
n -=
1;
else
n +=
1;
}
rangeset->n_ranges = n /
2;
rangeset->ranges = RangesRealloc((Range *)rangeTable, rangeset->n_ranges);
RangesetRefreshRange(rangeset,
0, rangeset->maxpos);
return rangeset->n_ranges;
}
int RangesetAddBetween(Rangeset *rangeset,
int start,
int end)
{
int i, j, n, *rangeTable = (
int *)rangeset->ranges;
if (start > end) {
i = start;
start = end;
end = i;
}
else if (start == end) {
return rangeset->n_ranges;
}
n =
2 * rangeset->n_ranges;
if (n ==
0) {
rangeset->ranges = RangesNew(
1);
rangeTable = (
int *)rangeset->ranges;
i =
0;
}
else
i = rangesetWeightedAtOrBefore(rangeset, start);
if (i == n) {
rangeTable[n] = start;
rangeTable[n +
1] = end;
rangeset->n_ranges++;
rangeset->ranges = RangesRealloc(rangeset->ranges, rangeset->n_ranges);
RangesetRefreshRange(rangeset, start, end);
return rangeset->n_ranges;
}
j = i;
while (j < n && rangeTable[j] <= end)
j++;
if (i == j) {
if (is_start(i)) {
rangesetShuffleToFrom(rangeTable, i +
2, i, n - i,
0);
rangeTable[i] = start;
rangeTable[i +
1] = end;
rangeset->n_ranges++;
rangeset->ranges = RangesRealloc(rangeset->ranges, rangeset->n_ranges);
}
else {
return rangeset->n_ranges;
}
}
else {
if (is_start(i))
rangeTable[i++] = start;
if (is_start(j))
rangeTable[--j] = end;
if (i < j)
rangesetShuffleToFrom(rangeTable, i, j, n - j,
0);
n -= j - i;
rangeset->n_ranges = n /
2;
rangeset->ranges = RangesRealloc(rangeset->ranges, rangeset->n_ranges);
}
RangesetRefreshRange(rangeset, start, end);
return rangeset->n_ranges;
}
int RangesetRemoveBetween(Rangeset *rangeset,
int start,
int end)
{
int i, j, n, *rangeTable = (
int *)rangeset->ranges;
if (start > end) {
i = start;
start = end;
end = i;
}
else if (start == end) {
return rangeset->n_ranges;
}
n =
2 * rangeset->n_ranges;
i = rangesetWeightedAtOrBefore(rangeset, start);
if (i == n)
return rangeset->n_ranges;
j = i;
while (j < n && rangeTable[j] <= end)
j++;
if (i == j) {
if (is_start(i))
return rangeset->n_ranges;
else {
i--;
rangesetShuffleToFrom(rangeTable, i +
2, i, n - i,
0);
rangeTable[i +
1] = start;
rangeTable[i +
2] = end;
rangeset->n_ranges++;
rangeset->ranges = RangesRealloc(rangeset->ranges, rangeset->n_ranges);
}
}
else {
if (is_end(i))
rangeTable[i++] = start;
if (is_end(j))
rangeTable[--j] = end;
if (i < j)
rangesetShuffleToFrom(rangeTable, i, j, n - j,
0);
n -= j - i;
rangeset->n_ranges = n /
2;
rangeset->ranges = RangesRealloc(rangeset->ranges, rangeset->n_ranges);
}
RangesetRefreshRange(rangeset, start, end);
return rangeset->n_ranges;
}