📄 rangeset.c
字号:
int end_del, movement; n = 2 * rangeset->n_ranges; i = rangesetWeightedAtOrBefore(rangeset, pos); if (i == n) return rangesetFixMaxpos(rangeset, ins, del); /* all beyond the end */ /* if the insert occurs at the start of a range, the following lines will extend the range, leaving the start of the range at pos. */ if (is_start(i) && rangeTable[i] == pos && ins > 0) i++; end_del = pos + del; movement = ins - del; /* the idea now is to determine the first range not concerned with the movement: its index will be j. For indices j to n-1, we will adjust position by movement only. (They may need shuffling up or down, depending on whether ranges have been deleted or created by the change.) */ j = i; while (j < n && rangeTable[j] <= end_del) /* skip j to first ind beyond changes */ j++; /* if j moved forward, we have deleted over rangeTable[i] - reduce it accordingly, accounting for inserts. */ if (j > i) rangeTable[i] = pos + ins; /* If i and j both index starts or ends, just copy all the rangeTable[] values down by j - i spaces, adjusting on the way. Otherwise, move beyond rangeTable[i] before doing this. */ 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); /* final adjustments */ return rangesetFixMaxpos(rangeset, ins, del);}/* "Delete/Insert": if the start point is in a range (start < pos &&** pos <= end), and the end of deletion is also in a range** (start <= pos + del && pos + del < end) any text inserted will extend that** range. Deletions appear to occur before insertions. This will never add new** ranges.*/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); /* all beyond the end */ end_del = pos + del; movement = ins - del; /* the idea now is to determine the first range not concerned with the movement: its index will be j. For indices j to n-1, we will adjust position by movement only. (They may need shuffling up or down, depending on whether ranges have been deleted or created by the change.) */ j = i; while (j < n && rangeTable[j] <= end_del) /* skip j to first ind beyond changes */ j++; /* if j moved forward, we have deleted over rangeTable[i] - reduce it accordingly, accounting for inserts. (Note: if rangeTable[j] is an end position, inserted text will belong to the range that rangeTable[j] closes; otherwise inserted text does not belong to a range.) */ if (j > i) rangeTable[i] = (is_end(j)) ? pos + ins : pos; /* If i and j both index starts or ends, just copy all the rangeTable[] values down by j - i spaces, adjusting on the way. Otherwise, move beyond rangeTable[i] before doing this. */ 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); /* final adjustments */ return rangesetFixMaxpos(rangeset, ins, del);}/* "Exclusive": if the start point is in, but not at the end of, a range** (start < pos && pos < end), and the end of deletion is also in a range** (start <= pos + del && pos + del < end) any text inserted will extend that** range. Deletions appear to occur before insertions. This will never add new** ranges. (Almost identical to rangesetDelInsMaintain().)*/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); /* all beyond the end */ /* if the insert occurs at the end of a range, the following lines will skip the range, leaving the end of the range at pos. */ if (is_end(i) && rangeTable[i] == pos && ins > 0) i++; end_del = pos + del; movement = ins - del; /* the idea now is to determine the first range not concerned with the movement: its index will be j. For indices j to n-1, we will adjust position by movement only. (They may need shuffling up or down, depending on whether ranges have been deleted or created by the change.) */ j = i; while (j < n && rangeTable[j] <= end_del) /* skip j to first ind beyond changes */ j++; /* if j moved forward, we have deleted over rangeTable[i] - reduce it accordingly, accounting for inserts. (Note: if rangeTable[j] is an end position, inserted text will belong to the range that rangeTable[j] closes; otherwise inserted text does not belong to a range.) */ if (j > i) rangeTable[i] = (is_end(j)) ? pos + ins : pos; /* If i and j both index starts or ends, just copy all the rangeTable[] values down by j - i spaces, adjusting on the way. Otherwise, move beyond rangeTable[i] before doing this. */ 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); /* final adjustments */ return rangesetFixMaxpos(rangeset, ins, del);}/* "Break": if the modification point pos is strictly inside a range, that range** may be broken in two if the deletion point pos+del does not extend beyond the** end. Inserted text is never included in the range.*/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); /* all beyond the end */ /* if the insert occurs at the end of a range, the following lines will skip the range, leaving the end of the range at pos. */ if (is_end(i) && rangeTable[i] == pos && ins > 0) i++; end_del = pos + del; movement = ins - del; /* the idea now is to determine the first range not concerned with the movement: its index will be j. For indices j to n-1, we will adjust position by movement only. (They may need shuffling up or down, depending on whether ranges have been deleted or created by the change.) */ j = i; while (j < n && rangeTable[j] <= end_del) /* skip j to first ind beyond changes */ j++; if (j > i) rangeTable[i] = pos; /* do we need to insert a gap? yes if pos is in a range and ins > 0 */ /* The logic for the next statement: if i and j are both range ends, range boundaries indicated by index values between i and j (if any) have been "skipped". This means that rangeTable[i-1],rangeTable[j] is the current range. We will be inserting in that range, splitting it. */ need_gap = (is_end(i) && is_end(j) && ins > 0); /* if we've got start-end or end-start, skip rangeTable[i] */ if (is_start(i) != is_start(j)) { /* one is start, other is end */ if (is_start(i)) { if (rangeTable[i] == pos) rangeTable[i] = pos + ins; /* move the range start */ } i++; /* skip to next index */ } /* values rangeTable[j] to rangeTable[n-1] must be adjusted by movement and placed in position. */ if (need_gap) i += 2; /* make space for the break */ /* adjust other position values: shuffle them up or down if necessary */ rangesetShuffleToFrom(rangeTable, i, j, n - j, movement); if (need_gap) { /* add the gap informations */ 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); /* final adjustments */ return rangesetFixMaxpos(rangeset, ins, del);}/* -------------------------------------------------------------------------- *//*** Invert the rangeset (replace it with its complement in the range 0-maxpos).** Returns the number of ranges if successful, -1 otherwise. Never adds more** than one range.*/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) { rangeTable[0] = 0; rangeTable[1] = rangeset->maxpos; n = 2; } else { n = rangeset->n_ranges * 2; /* find out what we have */ has_zero = (rangeTable[0] == 0); has_end = (rangeTable[n - 1] == rangeset->maxpos); /* fill the entry "beyond the end" with the buffer's length */ rangeTable[n + 1] = rangeTable[n] = rangeset->maxpos; if (has_zero) { /* shuffle down by one */ rangesetShuffleToFrom(rangeTable, 0, 1, n, 0); n -= 1; } else { /* shuffle up by one */ 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;}/* -------------------------------------------------------------------------- *//*** Add the range indicated by the positions start and end. Returns the** new number of ranges in the set.*/int RangesetAddBetween(Rangeset *rangeset, int start, int end){ int i, j, n, *rangeTable = (int *)rangeset->ranges; if (start > end) { i = start; /* quietly sort the positions */ start = end; end = i; } else if (start == end) { return rangeset->n_ranges; /* no-op - empty range == no range */ } n = 2 * rangeset->n_ranges; if (n == 0) { /* make sure we have space */ rangeset->ranges = RangesNew(1); rangeTable = (int *)rangeset->ranges; i = 0; } else i = rangesetWeightedAtOrBefore(rangeset, start); if (i == n) { /* beyond last range: just add it */ 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) /* skip j to first ind beyond changes */ j++; if (i == j) { if (is_start(i)) { /* is_start(i): need to make a gap in range rangeTable[i-1], rangeTable[i] */ rangesetShuffleToFrom(rangeTable, i + 2, i, n - i, 0); /* shuffle up */ rangeTable[i] = start; /* load up new range's limits */ rangeTable[i + 1] = end; rangeset->n_ranges++; /* we've just created a new range */ rangeset->ranges = RangesRealloc(rangeset->ranges, rangeset->n_ranges); } else { return rangeset->n_ranges; /* no change */ } } else { /* we'll be shuffling down */ 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;}/*** Remove the range indicated by the positions start and end. Returns the** new number of ranges in the set.*/int RangesetRemoveBetween(Rangeset *rangeset, int start, int end){ int i, j, n, *rangeTable = (int *)rangeset->ranges; if (start > end) { i = start; /* quietly sort the positions */ start = end; end = i; } else if (start == end) { return rangeset->n_ranges; /* no-op - empty range == no range */ } n = 2 * rangeset->n_ranges; i = rangesetWeightedAtOrBefore(rangeset, start); if (i == n) return rangeset->n_ranges; /* beyond last range */ j = i; while (j < n && rangeTable[j] <= end) /* skip j to first ind beyond changes */ j++; if (i == j) { /* removal occurs in front of rangeTable[i] */ if (is_start(i)) return rangeset->n_ranges; /* no change */ else { /* is_end(i): need to make a gap in range rangeTable[i-1], rangeTable[i] */ i--; /* start of current range */ rangesetShuffleToFrom(rangeTable, i + 2, i, n - i, 0); /* shuffle up */ rangeTable[i + 1] = start; /* change end of current range */ rangeTable[i + 2] = end; /* change start of new range */ rangeset->n_ranges++; /* we've just created a new range */ rangeset->ranges = RangesRealloc(rangeset->ranges, rangeset->n_ranges); } } else { /* removal occurs in front of rangeTable[j]: we'll be shuffling down */ 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;}/* -------------------------------------------------------------------------- */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -