📄 tktextbtree.c
字号:
nodePtr->summaryPtr = summaryPtr->nextPtr; } else { prevPtr->nextPtr = summaryPtr->nextPtr; } ckfree((char *) summaryPtr); } else { /* * This tag isn't currently in the summary information list. */ if (rootLevel == nodePtr->level) { /* * The old tag root is at the same level in the tree as this * node, but it isn't at this node. Move the tag root up * a level, in the hopes that it will now cover this node * as well as the old root (if not, we'll move it up again * the next time through the loop). To push it up one level * we copy the original toggle count into the summary * information at the old root and change the root to its * parent node. */ Node *rootNodePtr = tagPtr->tagRootPtr; summaryPtr = (Summary *) ckalloc(sizeof(Summary)); summaryPtr->tagPtr = tagPtr; summaryPtr->toggleCount = tagPtr->toggleCount - delta; summaryPtr->nextPtr = rootNodePtr->summaryPtr; rootNodePtr->summaryPtr = summaryPtr; rootNodePtr = rootNodePtr->parentPtr; rootLevel = rootNodePtr->level; tagPtr->tagRootPtr = rootNodePtr; } summaryPtr = (Summary *) ckalloc(sizeof(Summary)); summaryPtr->tagPtr = tagPtr; summaryPtr->toggleCount = delta; summaryPtr->nextPtr = nodePtr->summaryPtr; nodePtr->summaryPtr = summaryPtr; } } /* * If we've decremented the toggle count, then it may be necessary * to push the tag root down one or more levels. */ if (delta >= 0) { return; } if (tagPtr->toggleCount == 0) { tagPtr->tagRootPtr = (Node *) NULL; return; } nodePtr = tagPtr->tagRootPtr; while (nodePtr->level > 0) { /* * See if a single child node accounts for all of the tag's * toggles. If so, push the root down one level. */ for (node2Ptr = nodePtr->children.nodePtr; node2Ptr != (Node *)NULL ; node2Ptr = node2Ptr->nextPtr) { for (prevPtr = NULL, summaryPtr = node2Ptr->summaryPtr; summaryPtr != NULL; prevPtr = summaryPtr, summaryPtr = summaryPtr->nextPtr) { if (summaryPtr->tagPtr == tagPtr) { break; } } if (summaryPtr == NULL) { continue; } if (summaryPtr->toggleCount != tagPtr->toggleCount) { /* * No node has all toggles, so the root is still valid. */ return; } /* * This node has all the toggles, so push down the root. */ if (prevPtr == NULL) { node2Ptr->summaryPtr = summaryPtr->nextPtr; } else { prevPtr->nextPtr = summaryPtr->nextPtr; } ckfree((char *) summaryPtr); tagPtr->tagRootPtr = node2Ptr; break; } nodePtr = tagPtr->tagRootPtr; }}/* *---------------------------------------------------------------------- * * FindTagStart -- * * Find the start of the first range of a tag. * * Results: * The return value is a pointer to the first tag toggle segment * for the tag. This can be either a tagon or tagoff segments because * of the way TkBTreeAdd removes a tag. * Sets *indexPtr to be the index of the tag toggle. * * Side effects: * None. * *---------------------------------------------------------------------- */static TkTextSegment *FindTagStart(tree, tagPtr, indexPtr) TkTextBTree tree; /* Tree to search within */ TkTextTag *tagPtr; /* Tag to search for. */ TkTextIndex *indexPtr; /* Return - index information */{ register Node *nodePtr; register TkTextLine *linePtr; register TkTextSegment *segPtr; register Summary *summaryPtr; int offset; nodePtr = tagPtr->tagRootPtr; if (nodePtr == (Node *) NULL) { return NULL; } /* * Search from the root of the subtree that contains the tag down * to the level 0 node. */ while (nodePtr->level > 0) { for (nodePtr = nodePtr->children.nodePtr ; nodePtr != (Node *) NULL; nodePtr = nodePtr->nextPtr) { for (summaryPtr = nodePtr->summaryPtr ; summaryPtr != NULL; summaryPtr = summaryPtr->nextPtr) { if (summaryPtr->tagPtr == tagPtr) { goto gotNodeWithTag; } } } gotNodeWithTag: continue; } /* * Work through the lines attached to the level-0 node. */ for (linePtr = nodePtr->children.linePtr; linePtr != (TkTextLine *) NULL; linePtr = linePtr->nextPtr) { for (offset = 0, segPtr = linePtr->segPtr ; segPtr != NULL; offset += segPtr->size, segPtr = segPtr->nextPtr) { if (((segPtr->typePtr == &tkTextToggleOnType) || (segPtr->typePtr == &tkTextToggleOffType)) && (segPtr->body.toggle.tagPtr == tagPtr)) { /* * It is possible that this is a tagoff tag, but that * gets cleaned up later. */ indexPtr->tree = tree; indexPtr->linePtr = linePtr; indexPtr->charIndex = offset; return segPtr; } } } return NULL;}/* *---------------------------------------------------------------------- * * FindTagEnd -- * * Find the end of the last range of a tag. * * Results: * The return value is a pointer to the last tag toggle segment * for the tag. This can be either a tagon or tagoff segments because * of the way TkBTreeAdd removes a tag. * Sets *indexPtr to be the index of the tag toggle. * * Side effects: * None. * *---------------------------------------------------------------------- */static TkTextSegment *FindTagEnd(tree, tagPtr, indexPtr) TkTextBTree tree; /* Tree to search within */ TkTextTag *tagPtr; /* Tag to search for. */ TkTextIndex *indexPtr; /* Return - index information */{ register Node *nodePtr, *lastNodePtr; register TkTextLine *linePtr ,*lastLinePtr; register TkTextSegment *segPtr, *lastSegPtr, *last2SegPtr; register Summary *summaryPtr; int lastoffset, lastoffset2, offset; nodePtr = tagPtr->tagRootPtr; if (nodePtr == (Node *) NULL) { return NULL; } /* * Search from the root of the subtree that contains the tag down * to the level 0 node. */ while (nodePtr->level > 0) { for (lastNodePtr = NULL, nodePtr = nodePtr->children.nodePtr ; nodePtr != (Node *) NULL; nodePtr = nodePtr->nextPtr) { for (summaryPtr = nodePtr->summaryPtr ; summaryPtr != NULL; summaryPtr = summaryPtr->nextPtr) { if (summaryPtr->tagPtr == tagPtr) { lastNodePtr = nodePtr; break; } } } nodePtr = lastNodePtr; } /* * Work through the lines attached to the level-0 node. */ last2SegPtr = NULL; lastoffset2 = 0; lastoffset = 0; for (lastLinePtr = NULL, linePtr = nodePtr->children.linePtr; linePtr != (TkTextLine *) NULL; linePtr = linePtr->nextPtr) { for (offset = 0, lastSegPtr = NULL, segPtr = linePtr->segPtr ; segPtr != NULL; offset += segPtr->size, segPtr = segPtr->nextPtr) { if (((segPtr->typePtr == &tkTextToggleOnType) || (segPtr->typePtr == &tkTextToggleOffType)) && (segPtr->body.toggle.tagPtr == tagPtr)) { lastSegPtr = segPtr; lastoffset = offset; } } if (lastSegPtr != NULL) { lastLinePtr = linePtr; last2SegPtr = lastSegPtr; lastoffset2 = lastoffset; } } indexPtr->tree = tree; indexPtr->linePtr = lastLinePtr; indexPtr->charIndex = lastoffset2; return last2SegPtr;}/* *---------------------------------------------------------------------- * * TkBTreeStartSearch -- * * This procedure sets up a search for tag transitions involving * a given tag (or all tags) in a given range of the text. * * Results: * None. * * Side effects: * The information at *searchPtr is set up so that subsequent calls * to TkBTreeNextTag or TkBTreePrevTag will return information about the * locations of tag transitions. Note that TkBTreeNextTag or * TkBTreePrevTag must be called to get the first transition. * Note: unlike TkBTreeNextTag and TkBTreePrevTag, this routine does not * guarantee that searchPtr->curIndex is equal to *index1Ptr. It may be * greater than that if *index1Ptr is less than the first tag transition. * *---------------------------------------------------------------------- */voidTkBTreeStartSearch(index1Ptr, index2Ptr, tagPtr, searchPtr) TkTextIndex *index1Ptr; /* Search starts here. Tag toggles * at this position will not be * returned. */ TkTextIndex *index2Ptr; /* Search stops here. Tag toggles * at this position *will* be * returned. */ TkTextTag *tagPtr; /* Tag to search for. NULL means * search for any tag. */ register TkTextSearch *searchPtr; /* Where to store information about * search's progress. */{ int offset; TkTextIndex index0; /* First index of the tag */ TkTextSegment *seg0Ptr; /* First segment of the tag */ /* * Find the segment that contains the first toggle for the tag. This * may become the starting point in the search. */ seg0Ptr = FindTagStart(index1Ptr->tree, tagPtr, &index0); if (seg0Ptr == (TkTextSegment *) NULL) { /* * Even though there are no toggles, the display code still * uses the search curIndex, so initialize that anyway. */ searchPtr->linesLeft = 0; searchPtr->curIndex = *index1Ptr; searchPtr->segPtr = NULL; searchPtr->nextPtr = NULL; return; } if (TkTextIndexCmp(index1Ptr, &index0) < 0) { /* * Adjust start of search up to the first range of the tag */ searchPtr->curIndex = index0; searchPtr->segPtr = NULL; searchPtr->nextPtr = seg0Ptr; /* Will be returned by NextTag */ index1Ptr = &index0; } else { searchPtr->curIndex = *index1Ptr; searchPtr->segPtr = NULL; searchPtr->nextPtr = TkTextIndexToSeg(index1Ptr, &offset); searchPtr->curIndex.charIndex -= offset; } searchPtr->lastPtr = TkTextIndexToSeg(index2Ptr, (int *) NULL); searchPtr->tagPtr = tagPtr; searchPtr->linesLeft = TkBTreeLineIndex(index2Ptr->linePtr) + 1 - TkBTreeLineIndex(index1Ptr->linePtr); searchPtr->allTags = (tagPtr == NULL); if (searchPtr->linesLeft == 1) { /* * Starting and stopping segments are in the same line; mark the * search as over immediately if the second segment is before the * first. A search does not return a toggle at the very start of * the range, unless the range is artificially moved up to index0. */ if (((index1Ptr == &index0) && (index1Ptr->charIndex > index2Ptr->charIndex)) || ((index1Ptr != &index0) && (index1Ptr->charIndex >= index2Ptr->charIndex))) { searchPtr->linesLeft = 0; } }}/* *---------------------------------------------------------------------- * * TkBTreeStartSearchBack -- * * This procedure sets up a search backwards for tag transitions involving * a given tag (or all tags) in a given range of the text. In the * normal case the first index (*index1Ptr) is beyond the second * index (*index2Ptr). * * * Results: * None. * * Side effects: * The information at *searchPtr is set up so that subsequent calls * to TkBTreePrevTag will return information about the * locations of tag transitions. Note that TkBTreePrevTag must be called * to get the first transition. * Note: unlike TkBTreeNextTag and TkBTreePrevTag, this routine does not * guarantee that searchPtr->curIndex is equal to *index1Ptr. It may be * less than that if *index1Ptr is greater than the last tag transition. * *---------------------------------------------------------------------- */voidTkBTreeStartSearchBack(index1Ptr, index2Ptr, tagPtr, searchPtr) TkTextIndex *index1Ptr; /* Search starts here. Tag toggles * at this position will not be * returned. */ TkTextIndex *index2Ptr; /* Search stops here. Tag toggles * at this position *will* be * returned. */ TkTextTag *tagPtr; /* Tag to search for. NULL means * search for any tag. */ register TkTextSearch *searchPtr; /* Where to store information about * search's progress. */{ int offset; TkTextIndex index0; /* Last index of the tag */ TkTextIndex backOne; /* One character before starting index */ TkTextSegment *seg0Ptr; /* Last segment of the tag */ /* * Find the segment that contains the last toggle for the tag. This * may become the starting point in the search. */ seg0Ptr = FindTagEnd(index1Ptr->tree, tagPtr, &index0); if (seg0Ptr == (TkTextSegment *) NULL) { /* * Even though there are no toggles, the display code still * uses the search curIndex, so initialize that anyway. */ searchPtr->linesLeft = 0; searchPtr->curIndex = *index1Ptr; searchPtr->segPtr = NULL; searchPtr->nextPtr = NULL; return; } /* * Adjust the start of the search so it doesn't find any tag toggles * that are right at the index specified by the user. */ if (TkTextIndexCmp(index1Ptr, &index0) > 0) { searchPtr->curIndex = index0; index1Ptr = &index0; } else { TkTextIndexBackChars(index1Ptr, 1, &searchPtr->curIndex); } searchPtr->segPtr = NULL; searchPtr->nextPtr = TkTextIndexToSeg(&searchPtr->curIndex, &offset); searchPtr->curIndex.charIndex -= offset; /* * Adjust the end of the search so it does find toggles that are right * at the second index specified by the user. */ if ((TkBTreeLineIndex(index2Ptr->linePtr) == 0) && (index2Ptr->charIndex == 0)) { backOne = *index2Ptr; searchPtr->lastPtr = NULL; /* Signals special case for 1.0 */ } else { TkTextIndexBackChars(index2Ptr, 1, &backOne); searchPtr->lastPtr = TkTextIndexToSeg(&backOne, (int *) NULL); } searchPtr->tagPtr = tagPtr; searchPtr->linesLeft = TkBTreeLineIndex(index1Ptr->linePtr) + 1 - TkBTreeLineIndex(backOne.linePtr); searchPtr->allTags = (tagPtr == NULL); if (searchPtr->linesLeft == 1) { /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -