📄 rangeset.c
字号:
last = rangeset->last_index; /* try to profit from the last lookup by using its index */ if (last >= len || last < 0) { last = (len > 0) ? len - 1 : 0; /* make sure last is in range */ rangeset->last_index = last; } len *= 2; last *= 2; if (pos >= ranges[last]) { /* last even: this is a start */ if (pos < ranges[last + 1]) /* checking an end here */ return last / 2; /* no need to change rangeset->last_index */ else last += 2; /* not in this range: move on */ if (last == len) return -1; /* moved on too far */ /* find the entry in the upper portion of ranges */ index = weighted_at_or_before(ranges, last, len, pos); /* search end only */ } else if (last > 0) { index = weighted_at_or_before(ranges, 0, last, pos); /* search front only */ } else index = 0; rangeset->last_index = index / 2; if (index == len) return -1; /* beyond end */ if (index & 1) { /* index odd: references an end marker */ if (pos < ranges[index]) return index / 2; /* return the range index */ } else { /* index even: references start marker */ if (pos == ranges[index]) return index / 2; /* return the range index */ } return -1; /* not in any range */}/* -------------------------------------------------------------------------- *//*** Merge the ranges in rangeset plusSet into rangeset origSet.*/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; /* no ranges in plusSet - nothing to do */ newRanges = RangesNew(nOrigRanges + nPlusRanges); if (nOrigRanges == 0) { /* no ranges in destination: just copy the ranges from the other set */ 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; /* in the following we merrily swap the pointers/counters of the two input ranges (from origSet and plusSet) - don't worry, they're both consulted read-only - building the merged set in newRanges */ isOld = 1; /* true if origRanges points to a range in oldRanges[] */ while (nOrigRanges > 0 || nPlusRanges > 0) { /* make the range with the lowest start value the origRanges range */ if (nOrigRanges == 0 || (nPlusRanges > 0 && origRanges->start > plusRanges->start)) { SWAPval(Range *, &origRanges, &plusRanges); SWAPval(int, &nOrigRanges, &nPlusRanges); isOld = !isOld; } origSet->n_ranges++; /* we're using a new result range */ *newRanges = *origRanges++; nOrigRanges--; if (!isOld) RangesetRefreshRange(origSet, newRanges->start, newRanges->end); /* now we must cycle over plusRanges, merging in the overlapped ranges */ 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); /* by now, newRanges->end may have extended to overlap more ranges in origRanges, so swap and start again */ SWAPval(Range *, &origRanges, &plusRanges); SWAPval(int, &nOrigRanges, &nPlusRanges); isOld = !isOld; } /* OK: now *newRanges holds the result of merging all the first ranges from origRanges and plusRanges - now we have a break in contiguity, so move on to the next newRanges in the result */ newRanges++; } /* finally, forget the old rangeset values, and reallocate the new ones */ RangesFree(oldRanges); origSet->ranges = RangesRealloc(origSet->ranges, origSet->n_ranges); return origSet->n_ranges;}/* -------------------------------------------------------------------------- *//*** Subtract the ranges of minusSet from rangeset origSet.*/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; /* no ranges in origSet or minusSet - nothing to do */ /* we must provide more space: each range in minusSet might split a range in origSet */ newRanges = RangesNew(origSet->n_ranges + minusSet->n_ranges); oldRanges = origRanges; origSet->ranges = newRanges; origSet->n_ranges = 0; /* consider each range in origRanges - we do not change any of minusRanges's data, but we may change origRanges's - it will be discarded at the end */ while (nOrigRanges > 0) { do { /* skip all minusRanges ranges strictly in front of *origRanges */ while (nMinusRanges > 0 && minusRanges->end <= origRanges->start) { minusRanges++; /* *minusRanges in front of *origRanges: move onto next *minusRanges */ nMinusRanges--; } if (nMinusRanges > 0) { /* keep all origRanges ranges strictly in front of *minusRanges */ while (nOrigRanges > 0 && origRanges->end <= minusRanges->start) { *newRanges++ = *origRanges++; /* *minusRanges beyond *origRanges: save *origRanges in *newRanges */ nOrigRanges--; origSet->n_ranges++; } } else { /* no more minusRanges ranges to remove - save the rest of origRanges */ while (nOrigRanges > 0) { *newRanges++ = *origRanges++; nOrigRanges--; origSet->n_ranges++; } } } while (nMinusRanges > 0 && minusRanges->end <= origRanges->start); /* any more non-overlaps */ /* when we get here either we're done, or we have overlap */ if (nOrigRanges > 0) { if (minusRanges->start <= origRanges->start) { /* origRanges->start inside *minusRanges */ if (minusRanges->end < origRanges->end) { RangesetRefreshRange(origSet, origRanges->start, minusRanges->end); origRanges->start = minusRanges->end; /* cut off front of original *origRanges */ minusRanges++; /* dealt with this *minusRanges: move on */ nMinusRanges--; } else { /* all *origRanges inside *minusRanges */ RangesetRefreshRange(origSet, origRanges->start, origRanges->end); origRanges++; /* all of *origRanges can be skipped */ nOrigRanges--; } } else { /* minusRanges->start inside *origRanges: save front, adjust or skip rest */ newRanges->start = origRanges->start; /* save front of *origRanges in *newRanges */ newRanges->end = minusRanges->start; newRanges++; origSet->n_ranges++; if (minusRanges->end < origRanges->end) { /* all *minusRanges inside *origRanges */ RangesetRefreshRange(origSet, minusRanges->start, minusRanges->end); origRanges->start = minusRanges->end; /* cut front of *origRanges upto end *minusRanges */ minusRanges++; /* dealt with this *minusRanges: move on */ nMinusRanges--; } else { /* minusRanges->end beyond *origRanges */ RangesetRefreshRange(origSet, minusRanges->start, origRanges->end); origRanges++; /* skip rest of *origRanges */ nOrigRanges--; } } } } /* finally, forget the old rangeset values, and reallocate the new ones */ RangesFree(oldRanges); origSet->ranges = RangesRealloc(origSet->ranges, origSet->n_ranges); return origSet->n_ranges;}/* -------------------------------------------------------------------------- *//*** Get number of ranges in rangeset.*/int RangesetGetNRanges(Rangeset *rangeset){ return rangeset ? rangeset->n_ranges : 0;}/* ** Get information about rangeset.*/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; }}/* -------------------------------------------------------------------------- *//*** Set maxpos for rangeset rangeset.*/void RangesetSetMaxpos(Rangeset *rangeset, int maxpos){ if (rangeset) rangeset->maxpos = maxpos;}/* -------------------------------------------------------------------------- */static Rangeset *rangesetFixMaxpos(Rangeset *rangeset, int ins, int del){ rangeset->maxpos += ins - del; return rangeset;}/* -------------------------------------------------------------------------- *//*** Allocate and initialise, or empty and free a ranges set table.*/RangesetTable *RangesetTableAlloc(textBuffer *buffer){ int i; RangesetTable *table = (RangesetTable *)XtMalloc(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'; /* Range sets must be updated before the text display callbacks are called to avoid highlighted ranges getting out of sync. */ 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]); XtFree((char *)table); } return (RangesetTable *)0;}/*** Find a range set given its label in the table.*/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;}/*** Assign the range set table list.*/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';}/*** Return true if label is a valid identifier for a range set.*/int RangesetLabelOK(int label){ return strchr((char*)rangeset_labels, label) != NULL;}/*** Helper routines for managing the order and depth tables.*/static int activateRangeset(RangesetTable *table, int active){ int depth, i, j; if (table->active[active]) return 0; /* already active */ depth = table->depth[active]; /* we want to make the "active" set the most recent (lowest depth value): shuffle table->order[0..depth-1] to table->order[1..depth] readjust the entries in table->depth[] accordingly */ for (i = depth; i > 0; i--) { j = table->order[i] = table->order[i - 1]; table->depth[j] = i; } /* insert the new one: first in order, of depth 0 */ table->order[0] = active; table->depth[active] = 0; /* and finally... */ 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; /* already inactive */ /* we want to start by swapping the deepest entry in order with active shuffle table->order[depth+1..n_set-1] to table->order[depth..n_set-2] readjust the entries in table->depth[] accordingly */ depth = table->depth[active];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -