~ubuntu-branches/ubuntu/dapper/perl-tk/dapper

« back to all changes in this revision

Viewing changes to pTk/mTk/generic/tkTextBTree.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael C. Schultheiss
  • Date: 2006-01-16 16:54:02 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060116165402-1ppygm8hh8ahel2x
Tags: 1:804.027-2
* Incorporate changes from NMU (Thanks to Steve Kowalik.
  Closes: #348086)
* debian/control: Update Standards-Version (no changes needed)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* 
 
1
/*
2
2
 * tkTextBTree.c --
3
3
 *
4
4
 *      This file contains code that manages the B-tree representation
11
11
 * See the file "license.terms" for information on usage and redistribution
12
12
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13
13
 *
14
 
 * RCS: @(#) $Id: tkTextBTree.c,v 1.2 1998/09/14 18:23:18 stanton Exp $
 
14
 * RCS: @(#) $Id: tkTextBTree.c,v 1.6 2002/08/05 04:30:40 dgp Exp $
15
15
 */
16
16
 
17
17
#include "tkInt.h"
127
127
static void             CleanupLine _ANSI_ARGS_((TkTextLine *linePtr));
128
128
static void             DeleteSummaries _ANSI_ARGS_((Summary *tagPtr));
129
129
static void             DestroyNode _ANSI_ARGS_((Node *nodePtr));
130
 
static TkTextSegment *  FindTagEnd _ANSI_ARGS_((TkTextBTree tree, 
 
130
static TkTextSegment *  FindTagEnd _ANSI_ARGS_((TkTextBTree tree,
131
131
                            TkTextTag *tagPtr, TkTextIndex *indexPtr));
132
132
static void             IncCount _ANSI_ARGS_((TkTextTag *tagPtr, int inc,
133
133
                            TagInfo *tagInfoPtr));
191
191
    (Tk_SegLayoutProc *) NULL,                  /* layoutProc */
192
192
    ToggleCheckProc                             /* checkProc */
193
193
};
194
 
 
 
194
 
195
195
/*
196
196
 *----------------------------------------------------------------------
197
197
 *
262
262
 
263
263
    return (TkTextBTree) treePtr;
264
264
}
265
 
 
 
265
 
266
266
/*
267
267
 *----------------------------------------------------------------------
268
268
 *
282
282
 
283
283
void
284
284
TkBTreeDestroy(tree)
285
 
    TkTextBTree tree;                   /* Pointer to tree to delete. */ 
 
285
    TkTextBTree tree;                   /* Pointer to tree to delete. */
286
286
{
287
287
    BTree *treePtr = (BTree *) tree;
288
288
 
289
289
    DestroyNode(treePtr->rootPtr);
290
290
    ckfree((char *) treePtr);
291
291
}
292
 
 
 
292
 
293
293
/*
294
294
 *----------------------------------------------------------------------
295
295
 *
337
337
    DeleteSummaries(nodePtr->summaryPtr);
338
338
    ckfree((char *) nodePtr);
339
339
}
340
 
 
 
340
 
341
341
/*
342
342
 *----------------------------------------------------------------------
343
343
 *
367
367
        summaryPtr = nextPtr;
368
368
    }
369
369
}
370
 
 
 
370
 
371
371
/*
372
372
 *----------------------------------------------------------------------
373
373
 *
393
393
                                         * index is no longer valid because
394
394
                                         * of changes to the segment
395
395
                                         * structure. */
396
 
    char *string;                       /* Pointer to bytes to insert (may
 
396
    CONST char *string;                 /* Pointer to bytes to insert (may
397
397
                                         * contain newlines, must be null-
398
398
                                         * terminated). */
399
399
{
402
402
                                         * new segment (NULL means new segment
403
403
                                         * is at beginning of line). */
404
404
    TkTextSegment *curPtr;              /* Current segment;  new characters
405
 
                                         * are inserted just after this one. 
 
405
                                         * are inserted just after this one.
406
406
                                         * NULL means insert at beginning of
407
407
                                         * line. */
408
408
    TkTextLine *linePtr;                /* Current line (new segments are
410
410
    register TkTextSegment *segPtr;
411
411
    TkTextLine *newLinePtr;
412
412
    int chunkSize;                      /* # characters in current chunk. */
413
 
    register char *eol;                 /* Pointer to character just after last
 
413
    register CONST char *eol;           /* Pointer to character just after last
414
414
                                         * one in current chunk. */
415
415
    int changeToLineCount;              /* Counts change to total number of
416
416
                                         * lines in file. */
498
498
        TkBTreeCheck(indexPtr->tree);
499
499
    }
500
500
}
501
 
 
 
501
 
502
502
/*
503
503
 *--------------------------------------------------------------
504
504
 *
535
535
    TkTextSegment *prevPtr, *segPtr;
536
536
    int count;
537
537
 
538
 
    for (count = indexPtr->charIndex, prevPtr = NULL,
 
538
    for (count = indexPtr->byteIndex, prevPtr = NULL,
539
539
            segPtr = indexPtr->linePtr->segPtr; segPtr != NULL;
540
540
            count -= segPtr->size, prevPtr = segPtr, segPtr = segPtr->nextPtr) {
541
541
        if (segPtr->size > count) {
557
557
    panic("SplitSeg reached end of line!");
558
558
    return NULL;
559
559
}
560
 
 
 
560
 
561
561
/*
562
562
 *--------------------------------------------------------------
563
563
 *
612
612
        }
613
613
    }
614
614
}
615
 
 
 
615
 
616
616
/*
617
617
 *----------------------------------------------------------------------
618
618
 *
798
798
        TkBTreeCheck(index1Ptr->tree);
799
799
    }
800
800
}
801
 
 
 
801
 
802
802
/*
803
803
 *----------------------------------------------------------------------
804
804
 *
861
861
    }
862
862
    return linePtr;
863
863
}
864
 
 
 
864
 
865
865
/*
866
866
 *----------------------------------------------------------------------
867
867
 *
912
912
    }
913
913
    return nodePtr->children.linePtr;
914
914
}
915
 
 
 
915
 
916
916
/*
917
917
 *----------------------------------------------------------------------
918
918
 *
968
968
            break;
969
969
        }
970
970
    }
971
 
    for (node2Ptr = nodePtr->parentPtr->children.nodePtr; ; 
 
971
    for (node2Ptr = nodePtr->parentPtr->children.nodePtr; ;
972
972
            node2Ptr = node2Ptr->children.nodePtr) {
973
973
        while (node2Ptr->nextPtr != nodePtr) {
974
974
            node2Ptr = node2Ptr->nextPtr;
984
984
        }
985
985
    }
986
986
}
987
 
 
 
987
 
988
988
/*
989
989
 *----------------------------------------------------------------------
990
990
 *
1045
1045
    }
1046
1046
    return index;
1047
1047
}
1048
 
 
 
1048
 
1049
1049
/*
1050
1050
 *----------------------------------------------------------------------
1051
1051
 *
1088
1088
        TkBTreeCheck(indexPtr->tree);
1089
1089
    }
1090
1090
}
1091
 
 
 
1091
 
1092
1092
/*
1093
1093
 *----------------------------------------------------------------------
1094
1094
 *
1127
1127
    }
1128
1128
    CleanupLine(linePtr);
1129
1129
}
1130
 
 
 
1130
 
1131
1131
/*
1132
1132
 *----------------------------------------------------------------------
1133
1133
 *
1273
1273
        TkBTreeCheck(index1Ptr->tree);
1274
1274
    }
1275
1275
}
1276
 
 
 
1276
 
1277
1277
/*
1278
1278
 *----------------------------------------------------------------------
1279
1279
 *
1330
1330
         * See if there's already an entry for this tag for this node.  If so,
1331
1331
         * perhaps all we have to do is adjust its count.
1332
1332
         */
1333
 
    
 
1333
 
1334
1334
        for (prevPtr = NULL, summaryPtr = nodePtr->summaryPtr;
1335
1335
                summaryPtr != NULL;
1336
1336
                prevPtr = summaryPtr, summaryPtr = summaryPtr->nextPtr) {
1354
1354
                panic("ChangeNodeToggleCount: bad toggle count (%d) max (%d)",
1355
1355
                    summaryPtr->toggleCount, tagPtr->toggleCount);
1356
1356
            }
1357
 
    
 
1357
 
1358
1358
            /*
1359
1359
             * Zero toggle count;  must remove this tag from the list.
1360
1360
             */
1369
1369
            /*
1370
1370
             * This tag isn't currently in the summary information list.
1371
1371
             */
1372
 
    
 
1372
 
1373
1373
            if (rootLevel == nodePtr->level) {
1374
 
    
 
1374
 
1375
1375
                /*
1376
1376
                 * The old tag root is at the same level in the tree as this
1377
1377
                 * node, but it isn't at this node.  Move the tag root up
1382
1382
                 * information at the old root and change the root to its
1383
1383
                 * parent node.
1384
1384
                 */
1385
 
    
 
1385
 
1386
1386
                Node *rootNodePtr = tagPtr->tagRootPtr;
1387
1387
                summaryPtr = (Summary *) ckalloc(sizeof(Summary));
1388
1388
                summaryPtr->tagPtr = tagPtr;
1457
1457
        nodePtr = tagPtr->tagRootPtr;
1458
1458
    }
1459
1459
}
1460
 
 
 
1460
 
1461
1461
/*
1462
1462
 *----------------------------------------------------------------------
1463
1463
 *
1530
1530
                 */
1531
1531
                indexPtr->tree = tree;
1532
1532
                indexPtr->linePtr = linePtr;
1533
 
                indexPtr->charIndex = offset;
 
1533
                indexPtr->byteIndex = offset;
1534
1534
                return segPtr;
1535
1535
            }
1536
1536
        }
1537
1537
    }
1538
1538
    return NULL;
1539
1539
}
1540
 
 
 
1540
 
1541
1541
/*
1542
1542
 *----------------------------------------------------------------------
1543
1543
 *
1602
1602
    for (lastLinePtr = NULL, linePtr = nodePtr->children.linePtr;
1603
1603
            linePtr != (TkTextLine *) NULL; linePtr = linePtr->nextPtr) {
1604
1604
        for (offset = 0, lastSegPtr = NULL, segPtr = linePtr->segPtr ;
1605
 
                segPtr != NULL; 
 
1605
                segPtr != NULL;
1606
1606
                offset += segPtr->size, segPtr = segPtr->nextPtr) {
1607
1607
            if (((segPtr->typePtr == &tkTextToggleOnType)
1608
1608
                    || (segPtr->typePtr == &tkTextToggleOffType))
1619
1619
    }
1620
1620
    indexPtr->tree = tree;
1621
1621
    indexPtr->linePtr = lastLinePtr;
1622
 
    indexPtr->charIndex = lastoffset2;
 
1622
    indexPtr->byteIndex = lastoffset2;
1623
1623
    return last2SegPtr;
1624
1624
}
1625
 
 
 
1625
 
1626
1626
/*
1627
1627
 *----------------------------------------------------------------------
1628
1628
 *
1637
1637
 * Side effects:
1638
1638
 *      The information at *searchPtr is set up so that subsequent calls
1639
1639
 *      to TkBTreeNextTag or TkBTreePrevTag will return information about the
1640
 
 *      locations of tag transitions.  Note that TkBTreeNextTag or 
 
1640
 *      locations of tag transitions.  Note that TkBTreeNextTag or
1641
1641
 *      TkBTreePrevTag must be called to get the first transition.
1642
1642
 *      Note: unlike TkBTreeNextTag and TkBTreePrevTag, this routine does not
1643
1643
 *      guarantee that searchPtr->curIndex is equal to *index1Ptr.  It may be
1694
1694
        searchPtr->curIndex = *index1Ptr;
1695
1695
        searchPtr->segPtr = NULL;
1696
1696
        searchPtr->nextPtr = TkTextIndexToSeg(index1Ptr, &offset);
1697
 
        searchPtr->curIndex.charIndex -= offset;
 
1697
        searchPtr->curIndex.byteIndex -= offset;
1698
1698
    }
1699
1699
    searchPtr->lastPtr = TkTextIndexToSeg(index2Ptr, (int *) NULL);
1700
1700
    searchPtr->tagPtr = tagPtr;
1708
1708
         * first.  A search does not return a toggle at the very start of
1709
1709
         * the range, unless the range is artificially moved up to index0.
1710
1710
         */
1711
 
        if (((index1Ptr == &index0) && 
1712
 
                (index1Ptr->charIndex > index2Ptr->charIndex)) ||
1713
 
            ((index1Ptr != &index0) && 
1714
 
                (index1Ptr->charIndex >= index2Ptr->charIndex))) {
 
1711
        if (((index1Ptr == &index0) &&
 
1712
                (index1Ptr->byteIndex > index2Ptr->byteIndex)) ||
 
1713
            ((index1Ptr != &index0) &&
 
1714
                (index1Ptr->byteIndex >= index2Ptr->byteIndex))) {
1715
1715
                searchPtr->linesLeft = 0;
1716
1716
        }
1717
1717
    }
1718
1718
}
1719
 
 
 
1719
 
1720
1720
/*
1721
1721
 *----------------------------------------------------------------------
1722
1722
 *
1726
1726
 *      a given tag (or all tags) in a given range of the text.  In the
1727
1727
 *      normal case the first index (*index1Ptr) is beyond the second
1728
1728
 *      index (*index2Ptr).
1729
 
 *      
 
1729
 *
1730
1730
 *
1731
1731
 * Results:
1732
1732
 *      None.
1793
1793
    }
1794
1794
    searchPtr->segPtr = NULL;
1795
1795
    searchPtr->nextPtr = TkTextIndexToSeg(&searchPtr->curIndex, &offset);
1796
 
    searchPtr->curIndex.charIndex -= offset;
 
1796
    searchPtr->curIndex.byteIndex -= offset;
1797
1797
 
1798
1798
    /*
1799
1799
     * Adjust the end of the search so it does find toggles that are right
1801
1801
     */
1802
1802
 
1803
1803
    if ((TkBTreeLineIndex(index2Ptr->linePtr) == 0) &&
1804
 
            (index2Ptr->charIndex == 0)) {
 
1804
            (index2Ptr->byteIndex == 0)) {
1805
1805
        backOne = *index2Ptr;
1806
1806
        searchPtr->lastPtr = NULL;      /* Signals special case for 1.0 */
1807
1807
    } else {
1819
1819
         * first.
1820
1820
         */
1821
1821
 
1822
 
        if (index1Ptr->charIndex <= backOne.charIndex) {
 
1822
        if (index1Ptr->byteIndex <= backOne.byteIndex) {
1823
1823
            searchPtr->linesLeft = 0;
1824
1824
        }
1825
1825
    }
1826
1826
}
1827
 
 
 
1827
 
1828
1828
/*
1829
1829
 *----------------------------------------------------------------------
1830
1830
 *
1889
1889
                searchPtr->tagPtr = segPtr->body.toggle.tagPtr;
1890
1890
                return 1;
1891
1891
            }
1892
 
            searchPtr->curIndex.charIndex += segPtr->size;
 
1892
            searchPtr->curIndex.byteIndex += segPtr->size;
1893
1893
        }
1894
 
    
 
1894
 
1895
1895
        /*
1896
1896
         * See if there are more lines associated with the current parent
1897
1897
         * node.  If so, go back to the top of the loop to search the next
1906
1906
        }
1907
1907
        if (searchPtr->curIndex.linePtr != NULL) {
1908
1908
            segPtr = searchPtr->curIndex.linePtr->segPtr;
1909
 
            searchPtr->curIndex.charIndex = 0;
 
1909
            searchPtr->curIndex.byteIndex = 0;
1910
1910
            continue;
1911
1911
        }
1912
1912
        if (nodePtr == searchPtr->tagPtr->tagRootPtr) {
1913
1913
            goto searchOver;
1914
1914
        }
1915
 
    
 
1915
 
1916
1916
        /*
1917
1917
         * Search across and up through the B-tree's node hierarchy looking
1918
1918
         * for the next node that has a relevant tag transition somewhere in
1919
1919
         * its subtree.  Be sure to update linesLeft as we skip over large
1920
1920
         * chunks of lines.
1921
1921
         */
1922
 
    
 
1922
 
1923
1923
        while (1) {
1924
1924
            while (nodePtr->nextPtr == NULL) {
1925
1925
                if (nodePtr->parentPtr == NULL ||
1938
1938
            }
1939
1939
            searchPtr->linesLeft -= nodePtr->numLines;
1940
1940
        }
1941
 
    
 
1941
 
1942
1942
        /*
1943
1943
         * At this point we've found a subtree that has a relevant tag
1944
1944
         * transition.  Now search down (and across) through that subtree
1945
1945
         * to find the first level-0 node that has a relevant tag transition.
1946
1946
         */
1947
 
    
 
1947
 
1948
1948
        gotNodeWithTag:
1949
1949
        while (nodePtr->level > 0) {
1950
1950
            for (nodePtr = nodePtr->children.nodePtr; ;
1964
1964
            nextChild:
1965
1965
            continue;
1966
1966
        }
1967
 
    
 
1967
 
1968
1968
        /*
1969
1969
         * Now we're down to a level-0 node that contains a line that contains
1970
1970
         * a relevant tag transition.  Set up line information and go back to
1972
1972
         */
1973
1973
 
1974
1974
        searchPtr->curIndex.linePtr = nodePtr->children.linePtr;
1975
 
        searchPtr->curIndex.charIndex = 0;
 
1975
        searchPtr->curIndex.byteIndex = 0;
1976
1976
        segPtr = searchPtr->curIndex.linePtr->segPtr;
1977
1977
        if (searchPtr->linesLeft <= 0) {
1978
1978
            goto searchOver;
1985
1985
    searchPtr->segPtr = NULL;
1986
1986
    return 0;
1987
1987
}
1988
 
 
 
1988
 
1989
1989
/*
1990
1990
 *----------------------------------------------------------------------
1991
1991
 *
2022
2022
    register TkTextLine *linePtr, *prevLinePtr;
2023
2023
    register Node *nodePtr, *node2Ptr, *prevNodePtr;
2024
2024
    register Summary *summaryPtr;
2025
 
    int charIndex;
 
2025
    int byteIndex;
2026
2026
    int pastLast;                       /* Saw last marker during scan */
2027
2027
    int linesSkipped;
2028
2028
 
2034
2034
     * The outermost loop iterates over lines that may potentially contain
2035
2035
     * a relevant tag transition, starting from the current segment in
2036
2036
     * the current line.  "nextPtr" is maintained as the last segment in
2037
 
     * a line that we can look at. 
 
2037
     * a line that we can look at.
2038
2038
     */
2039
2039
 
2040
2040
    while (1) {
2041
2041
        /*
2042
2042
         * Check for the last toggle before the current segment on this line.
2043
2043
         */
2044
 
        charIndex = 0;
 
2044
        byteIndex = 0;
2045
2045
        if (searchPtr->lastPtr == NULL) {
2046
 
            /* 
 
2046
            /*
2047
2047
             * Search back to the very beginning, so pastLast is irrelevent.
2048
2048
             */
2049
 
            pastLast = 1; 
 
2049
            pastLast = 1;
2050
2050
        } else {
2051
2051
            pastLast = 0;
2052
2052
        }
2058
2058
                    && (searchPtr->allTags
2059
2059
                    || (segPtr->body.toggle.tagPtr == searchPtr->tagPtr))) {
2060
2060
                prevPtr = segPtr;
2061
 
                searchPtr->curIndex.charIndex = charIndex;
 
2061
                searchPtr->curIndex.byteIndex = byteIndex;
2062
2062
            }
2063
2063
            if (segPtr == searchPtr->lastPtr) {
2064
2064
                prevPtr = NULL;   /* Segments earlier than last don't count */
2065
2065
                pastLast = 1;
2066
2066
            }
2067
 
            charIndex += segPtr->size;
 
2067
            byteIndex += segPtr->size;
2068
2068
        }
2069
2069
        if (prevPtr != NULL) {
2070
2070
            if (searchPtr->linesLeft == 1 && !pastLast) {
2079
2079
            searchPtr->tagPtr = prevPtr->body.toggle.tagPtr;
2080
2080
            return 1;
2081
2081
        }
2082
 
    
 
2082
 
2083
2083
        searchPtr->linesLeft--;
2084
2084
        if (searchPtr->linesLeft <= 0) {
2085
2085
            goto searchOver;
2105
2105
        if (nodePtr == searchPtr->tagPtr->tagRootPtr) {
2106
2106
            goto searchOver;
2107
2107
        }
2108
 
    
 
2108
 
2109
2109
        /*
2110
2110
         * Search across and up through the B-tree's node hierarchy looking
2111
2111
         * for the previous node that has a relevant tag transition somewhere in
2115
2115
         * one we find, if any, is recorded in prevNodePtr, and any nodes
2116
2116
         * past prevNodePtr that don't have tag state increment linesSkipped.
2117
2117
         */
2118
 
    
 
2118
 
2119
2119
        while (1) {
2120
2120
            for (prevNodePtr = NULL, linesSkipped = 0,
2121
2121
                    node2Ptr = nodePtr->parentPtr->children.nodePtr ;
2145
2145
                goto searchOver;
2146
2146
            }
2147
2147
        }
2148
 
    
 
2148
 
2149
2149
        /*
2150
2150
         * At this point we've found a subtree that has a relevant tag
2151
2151
         * transition.  Now search down (and across) through that subtree
2152
2152
         * to find the last level-0 node that has a relevant tag transition.
2153
2153
         */
2154
 
    
 
2154
 
2155
2155
        gotNodeWithTag:
2156
2156
        while (nodePtr->level > 0) {
2157
2157
            for (linesSkipped = 0, prevNodePtr = NULL,
2177
2177
            searchPtr->linesLeft -= linesSkipped;
2178
2178
            nodePtr = prevNodePtr;
2179
2179
        }
2180
 
    
 
2180
 
2181
2181
        /*
2182
2182
         * Now we're down to a level-0 node that contains a line that contains
2183
2183
         * a relevant tag transition.  Set up line information and go back to
2191
2191
            /* empty loop body */ ;
2192
2192
        }
2193
2193
        searchPtr->curIndex.linePtr = prevLinePtr;
2194
 
        searchPtr->curIndex.charIndex = 0;
 
2194
        searchPtr->curIndex.byteIndex = 0;
2195
2195
        if (searchPtr->linesLeft <= 0) {
2196
2196
            goto searchOver;
2197
2197
        }
2203
2203
    searchPtr->segPtr = NULL;
2204
2204
    return 0;
2205
2205
}
2206
 
 
 
2206
 
2207
2207
/*
2208
2208
 *----------------------------------------------------------------------
2209
2209
 *
2233
2233
    TkTextSegment *toggleSegPtr;
2234
2234
    int toggles, index;
2235
2235
 
2236
 
    /* 
 
2236
    /*
2237
2237
     * Check for toggles for the tag in indexPtr's line but before
2238
2238
     * indexPtr.  If there is one, its type indicates whether or
2239
2239
     * not the character is tagged.
2241
2241
 
2242
2242
    toggleSegPtr = NULL;
2243
2243
    for (index = 0, segPtr = indexPtr->linePtr->segPtr;
2244
 
            (index + segPtr->size) <= indexPtr->charIndex;
 
2244
            (index + segPtr->size) <= indexPtr->byteIndex;
2245
2245
            index += segPtr->size, segPtr = segPtr->nextPtr) {
2246
2246
        if (((segPtr->typePtr == &tkTextToggleOnType)
2247
2247
                || (segPtr->typePtr == &tkTextToggleOffType))
2287
2287
        register Node *siblingPtr;
2288
2288
        register Summary *summaryPtr;
2289
2289
 
2290
 
        for (siblingPtr = nodePtr->parentPtr->children.nodePtr; 
 
2290
        for (siblingPtr = nodePtr->parentPtr->children.nodePtr;
2291
2291
                siblingPtr != nodePtr; siblingPtr = siblingPtr->nextPtr) {
2292
2292
            for (summaryPtr = siblingPtr->summaryPtr; summaryPtr != NULL;
2293
2293
                    summaryPtr = summaryPtr->nextPtr) {
2308
2308
 
2309
2309
    return toggles & 1;
2310
2310
}
2311
 
 
 
2311
 
2312
2312
/*
2313
2313
 *----------------------------------------------------------------------
2314
2314
 *
2360
2360
     */
2361
2361
 
2362
2362
    for (index = 0, segPtr = indexPtr->linePtr->segPtr;
2363
 
            (index + segPtr->size) <= indexPtr->charIndex;
 
2363
            (index + segPtr->size) <= indexPtr->byteIndex;
2364
2364
            index += segPtr->size, segPtr = segPtr->nextPtr) {
2365
2365
        if ((segPtr->typePtr == &tkTextToggleOnType)
2366
2366
                || (segPtr->typePtr == &tkTextToggleOffType)) {
2395
2395
        register Node *siblingPtr;
2396
2396
        register Summary *summaryPtr;
2397
2397
 
2398
 
        for (siblingPtr = nodePtr->parentPtr->children.nodePtr; 
 
2398
        for (siblingPtr = nodePtr->parentPtr->children.nodePtr;
2399
2399
                siblingPtr != nodePtr; siblingPtr = siblingPtr->nextPtr) {
2400
2400
            for (summaryPtr = siblingPtr->summaryPtr; summaryPtr != NULL;
2401
2401
                    summaryPtr = summaryPtr->nextPtr) {
2428
2428
    return tagInfo.tagPtrs;
2429
2429
}
2430
2430
 
2431
 
 
2432
2431
/*
2433
 
   special case to just return information about elided attribute
2434
 
   specialized from TkBTreeGetTags(indexPtr, numTagsPtr) and GetStyle(textPtr, indexPtr)
2435
 
   just need to keep track of invisibility settings for each priority, pick highest one active at end
2436
 
*/
 
2432
 *----------------------------------------------------------------------
 
2433
 *
 
2434
 * TkTextIsElided --
 
2435
 *
 
2436
 *      Special case to just return information about elided attribute.
 
2437
 *      Specialized from TkBTreeGetTags(indexPtr, numTagsPtr)
 
2438
 *      and GetStyle(textPtr, indexPtr).
 
2439
 *      Just need to keep track of invisibility settings for each priority,
 
2440
 *      pick highest one active at end
 
2441
 *
 
2442
 * Results:
 
2443
 *      Returns whether this text should be elided or not.
 
2444
 *
 
2445
 * Side effects:
 
2446
 *      None.
 
2447
 *
 
2448
 *----------------------------------------------------------------------
 
2449
 */
 
2450
 
 
2451
        /* ARGSUSED */
2437
2452
int
2438
2453
TkTextIsElided(textPtr, indexPtr)
2439
2454
    TkText *textPtr;            /* Overall information about text widget. */
2441
2456
                                 * display information is wanted. */
2442
2457
{
2443
2458
#define LOTSA_TAGS 1000
2444
 
        int elide = 0;          /* if nobody says otherwise, it's visible */
 
2459
    int elide = 0;              /* if nobody says otherwise, it's visible */
2445
2460
 
2446
 
        int deftagCnts[LOTSA_TAGS];
2447
 
        int *tagCnts = deftagCnts;
2448
 
        TkTextTag *deftagPtrs[LOTSA_TAGS];
2449
 
        TkTextTag **tagPtrs = deftagPtrs;
2450
 
        int numTags = textPtr->numTags;
 
2461
    int deftagCnts[LOTSA_TAGS];
 
2462
    int *tagCnts = deftagCnts;
 
2463
    TkTextTag *deftagPtrs[LOTSA_TAGS];
 
2464
    TkTextTag **tagPtrs = deftagPtrs;
 
2465
    int numTags = textPtr->numTags;
2451
2466
    register Node *nodePtr;
2452
2467
    register TkTextLine *siblingLinePtr;
2453
2468
    register TkTextSegment *segPtr;
2455
2470
    register int i, index;
2456
2471
 
2457
2472
        /* almost always avoid malloc, so stay out of system calls */
2458
 
        if (LOTSA_TAGS < numTags) {
2459
 
            tagCnts = (int *)ckalloc((unsigned)sizeof(int) * numTags);
2460
 
            tagPtrs = (TkTextTag **)ckalloc((unsigned)sizeof(TkTextTag *) * numTags);
2461
 
        }
2462
 
 
2463
 
        for (i=0; i<numTags; i++) tagCnts[i]=0;
 
2473
    if (LOTSA_TAGS < numTags) {
 
2474
        tagCnts = (int *)ckalloc((unsigned)sizeof(int) * numTags);
 
2475
        tagPtrs = (TkTextTag **)ckalloc((unsigned)sizeof(TkTextTag *) * numTags);
 
2476
    }
2464
2477
 
 
2478
    for (i=0; i<numTags; i++) {
 
2479
        tagCnts[i] = 0;
 
2480
    }
2465
2481
 
2466
2482
    /*
2467
2483
     * Record tag toggles within the line of indexPtr but preceding
2469
2485
     */
2470
2486
 
2471
2487
    for (index = 0, segPtr = indexPtr->linePtr->segPtr;
2472
 
            (index + segPtr->size) <= indexPtr->charIndex;
2473
 
            index += segPtr->size, segPtr = segPtr->nextPtr) {
 
2488
         (index + segPtr->size) <= indexPtr->byteIndex;
 
2489
         index += segPtr->size, segPtr = segPtr->nextPtr) {
2474
2490
        if ((segPtr->typePtr == &tkTextToggleOnType)
2475
 
            || (segPtr->typePtr == &tkTextToggleOffType)) {
 
2491
                || (segPtr->typePtr == &tkTextToggleOffType)) {
2476
2492
            tagPtr = segPtr->body.toggle.tagPtr;
2477
 
            if (tagPtr->state != TK_STATE_NULL) {
2478
 
                   tagPtrs[tagPtr->priority] = tagPtr;
2479
 
                   tagCnts[tagPtr->priority]++;
 
2493
            if (tagPtr->elideString != NULL) {
 
2494
                tagPtrs[tagPtr->priority] = tagPtr;
 
2495
                tagCnts[tagPtr->priority]++;
2480
2496
            }
2481
2497
        }
2482
2498
    }
2487
2503
     */
2488
2504
 
2489
2505
    for (siblingLinePtr = indexPtr->linePtr->parentPtr->children.linePtr;
2490
 
            siblingLinePtr != indexPtr->linePtr;
2491
 
            siblingLinePtr = siblingLinePtr->nextPtr) {
 
2506
         siblingLinePtr != indexPtr->linePtr;
 
2507
         siblingLinePtr = siblingLinePtr->nextPtr) {
2492
2508
        for (segPtr = siblingLinePtr->segPtr; segPtr != NULL;
2493
 
                segPtr = segPtr->nextPtr) {
 
2509
             segPtr = segPtr->nextPtr) {
2494
2510
            if ((segPtr->typePtr == &tkTextToggleOnType)
2495
 
                   || (segPtr->typePtr == &tkTextToggleOffType)) {
2496
 
                   tagPtr = segPtr->body.toggle.tagPtr;
2497
 
                   if (tagPtr->state != TK_STATE_NULL) {
2498
 
                          tagPtrs[tagPtr->priority] = tagPtr;
2499
 
                          tagCnts[tagPtr->priority]++;
2500
 
                   }
 
2511
                    || (segPtr->typePtr == &tkTextToggleOffType)) {
 
2512
                tagPtr = segPtr->body.toggle.tagPtr;
 
2513
                if (tagPtr->elideString != NULL) {
 
2514
                    tagPtrs[tagPtr->priority] = tagPtr;
 
2515
                    tagCnts[tagPtr->priority]++;
 
2516
                }
2501
2517
            }
2502
2518
        }
2503
2519
    }
2508
2524
     */
2509
2525
 
2510
2526
    for (nodePtr = indexPtr->linePtr->parentPtr; nodePtr->parentPtr != NULL;
2511
 
            nodePtr = nodePtr->parentPtr) {
 
2527
         nodePtr = nodePtr->parentPtr) {
2512
2528
        register Node *siblingPtr;
2513
2529
        register Summary *summaryPtr;
2514
2530
 
2515
 
        for (siblingPtr = nodePtr->parentPtr->children.nodePtr; 
2516
 
                siblingPtr != nodePtr; siblingPtr = siblingPtr->nextPtr) {
 
2531
        for (siblingPtr = nodePtr->parentPtr->children.nodePtr;
 
2532
             siblingPtr != nodePtr; siblingPtr = siblingPtr->nextPtr) {
2517
2533
            for (summaryPtr = siblingPtr->summaryPtr; summaryPtr != NULL;
2518
 
                    summaryPtr = summaryPtr->nextPtr) {
 
2534
                 summaryPtr = summaryPtr->nextPtr) {
2519
2535
                if (summaryPtr->toggleCount & 1) {
2520
2536
                    tagPtr = summaryPtr->tagPtr;
2521
 
                    if (tagPtr->state != TK_STATE_NULL) {
2522
 
                           tagPtrs[tagPtr->priority] = tagPtr;
2523
 
                           tagCnts[tagPtr->priority] += summaryPtr->toggleCount;
 
2537
                    if (tagPtr->elideString != NULL) {
 
2538
                        tagPtrs[tagPtr->priority] = tagPtr;
 
2539
                        tagCnts[tagPtr->priority] += summaryPtr->toggleCount;
2524
2540
                    }
2525
2541
                }
2526
2542
            }
2527
2543
        }
2528
2544
    }
2529
2545
 
2530
 
 
2531
2546
    /*
2532
 
     * Now traverse from highest priority to lowest, 
 
2547
     * Now traverse from highest priority to lowest,
2533
2548
     * take elided value from first odd count (= on)
2534
2549
     */
2535
2550
 
2536
2551
    for (i = numTags-1; i >=0; i--) {
2537
 
           if (tagCnts[i] & 1) {
 
2552
        if (tagCnts[i] & 1) {
2538
2553
#ifndef ALWAYS_SHOW_SELECTION
2539
 
                  /* who would make the selection elided? */
2540
 
                  if ((tagPtr == textPtr->selTagPtr) && !(textPtr->flags & GOT_FOCUS)) {
2541
 
                         continue;
2542
 
                  }
 
2554
            /* who would make the selection elided? */
 
2555
            if ((tagPtr == textPtr->selTagPtr)
 
2556
                    && !(textPtr->flags & GOT_FOCUS)) {
 
2557
                continue;
 
2558
            }
2543
2559
#endif
2544
 
                  elide = (tagPtrs[i]->state == TK_STATE_HIDDEN);
2545
 
                  break;
2546
 
           }
 
2560
            elide = tagPtrs[i]->elide;
 
2561
            break;
 
2562
        }
2547
2563
    }
2548
2564
 
2549
2565
    if (LOTSA_TAGS < numTags) {
2550
 
           ckfree((char *) tagCnts);
2551
 
           ckfree((char *) tagPtrs);
 
2566
        ckfree((char *) tagCnts);
 
2567
        ckfree((char *) tagPtrs);
2552
2568
    }
2553
2569
 
2554
2570
    return elide;
2555
2571
}
2556
 
 
 
2572
 
2557
2573
/*
2558
2574
 *----------------------------------------------------------------------
2559
2575
 *
2620
2636
    tagInfoPtr->counts[tagInfoPtr->numTags] = inc;
2621
2637
    tagInfoPtr->numTags++;
2622
2638
}
2623
 
 
 
2639
 
2624
2640
/*
2625
2641
 *----------------------------------------------------------------------
2626
2642
 *
2761
2777
                segPtr->body.chars);
2762
2778
    }
2763
2779
}
2764
 
 
 
2780
 
2765
2781
/*
2766
2782
 *----------------------------------------------------------------------
2767
2783
 *
2923
2939
        }
2924
2940
    }
2925
2941
}
2926
 
 
 
2942
 
2927
2943
/*
2928
2944
 *----------------------------------------------------------------------
2929
2945
 *
2971
2987
                 * If the node being split is the root node, then make a
2972
2988
                 * new root node above it first.
2973
2989
                 */
2974
 
    
 
2990
 
2975
2991
                if (nodePtr->parentPtr == NULL) {
2976
2992
                    newPtr = (Node *) ckalloc(sizeof(Node));
2977
2993
                    newPtr->parentPtr = NULL;
3148
3164
        }
3149
3165
    }
3150
3166
}
3151
 
 
 
3167
 
3152
3168
/*
3153
3169
 *----------------------------------------------------------------------
3154
3170
 *
3267
3283
 
3268
3284
    summaryPtr2 = NULL;
3269
3285
    for (summaryPtr = nodePtr->summaryPtr; summaryPtr != NULL; ) {
3270
 
        if (summaryPtr->toggleCount > 0 && 
 
3286
        if (summaryPtr->toggleCount > 0 &&
3271
3287
                summaryPtr->toggleCount < summaryPtr->tagPtr->toggleCount) {
3272
3288
            if (nodePtr->level == summaryPtr->tagPtr->tagRootPtr->level) {
3273
3289
                /*
3298
3314
        }
3299
3315
    }
3300
3316
}
3301
 
 
 
3317
 
3302
3318
/*
3303
3319
 *----------------------------------------------------------------------
3304
3320
 *
3325
3341
    BTree *treePtr = (BTree *) tree;
3326
3342
    return treePtr->rootPtr->numLines - 1;
3327
3343
}
3328
 
 
 
3344
 
3329
3345
/*
3330
3346
 *--------------------------------------------------------------
3331
3347
 *
3367
3383
    ckfree((char*) segPtr);
3368
3384
    return newPtr1;
3369
3385
}
3370
 
 
 
3386
 
3371
3387
/*
3372
3388
 *--------------------------------------------------------------
3373
3389
 *
3411
3427
    ckfree((char*) segPtr2);
3412
3428
    return newPtr;
3413
3429
}
3414
 
 
 
3430
 
3415
3431
/*
3416
3432
 *--------------------------------------------------------------
3417
3433
 *
3440
3456
    ckfree((char*) segPtr);
3441
3457
    return 0;
3442
3458
}
3443
 
 
 
3459
 
3444
3460
/*
3445
3461
 *--------------------------------------------------------------
3446
3462
 *
3489
3505
        }
3490
3506
    }
3491
3507
}
3492
 
 
 
3508
 
3493
3509
/*
3494
3510
 *--------------------------------------------------------------
3495
3511
 *
3537
3553
    }
3538
3554
    return 1;
3539
3555
}
3540
 
 
 
3556
 
3541
3557
/*
3542
3558
 *--------------------------------------------------------------
3543
3559
 *
3607
3623
    }
3608
3624
    return segPtr;
3609
3625
}
3610
 
 
 
3626
 
3611
3627
/*
3612
3628
 *--------------------------------------------------------------
3613
3629
 *
3636
3652
        segPtr->body.toggle.inNodeCounts = 0;
3637
3653
    }
3638
3654
}
3639
 
 
 
3655
 
3640
3656
/*
3641
3657
 *--------------------------------------------------------------
3642
3658
 *
3686
3702
        }
3687
3703
    }
3688
3704
}
3689
 
 
 
3705
 
3690
3706
/*
3691
3707
 *----------------------------------------------------------------------
3692
3708
 *
3714
3730
 
3715
3731
    count = 0;
3716
3732
    for (segPtr = linePtr->segPtr; segPtr != NULL; segPtr = segPtr->nextPtr) {
 
3733
        if (segPtr->typePtr == &tkTextCharType) {
 
3734
            count += Tcl_NumUtfChars(segPtr->body.chars, segPtr->size);
 
3735
        } else {
 
3736
            count += segPtr->size;
 
3737
        }
 
3738
    }
 
3739
    return count;
 
3740
}
 
3741
 
 
3742
int
 
3743
TkBTreeBytesInLine(linePtr)
 
3744
    TkTextLine *linePtr;                /* Line whose characters should be
 
3745
                                         * counted. */
 
3746
{
 
3747
    TkTextSegment *segPtr;
 
3748
    int count;
 
3749
 
 
3750
    count = 0;
 
3751
    for (segPtr = linePtr->segPtr; segPtr != NULL; segPtr = segPtr->nextPtr) {
3717
3752
        count += segPtr->size;
3718
3753
    }
3719
3754
    return count;