Search code examples
objective-ccore-text

Determine when CTLine is result of a line break


I'm trying to determine if a CTLineRef is the result of a line break. I'm using CTFramesetterCreateFrame to handle all of the line breaking logic (I'm not manually creating the line breaks). I have an idea of how I can do this, but I'm hoping there's some type of meta-data on the CTLineRef that says specifically if it is the result of a new line break.

Example:

Original:

This is a really long line that goes on for a while.

After CTFramesetterCreateFrame applies line breaking:

This is a really long line that
goes on for a while.

So I want to determine if the 'goes on for a while' is the result of a line break.


Solution

  • I ended up using CTLineGetStringRange(CTLineRef). Just for clarity; This will return the location within your backing string that the CTLineRef represents. After that it was a simple comparison between the CFRange.location, returned by CTLineGetStringRange, to my line's location. YMMV depending on how you get a particular line's location. I have a specialized class I use to get this information (more below).

    Here's some code:

    NSUInteger totalLines = 100; // Total number of lines in document.
    NSUInteger numVisibleLines = 30; // Number of lines that can fit in the view port.
    NSUInteger fromLineNumber = 0; // 0 indexed line number. Add + 1 to get the actual line number
    
    NSUInteger numFormatChars = [[NSString stringWithFormat:@"%d", totalLines] length];
    NSString *numFormat = [NSString stringWithFormat:@"%%%dd\n", numFormatChars];
    NSMutableString *string = [NSMutableString string];
    NSArray *lines = (NSArray *)CTFrameGetLines(textFrame);
    
    for (NSUInteger i = 0; i < numVisibleLines; ++i)
    {
        CTLineRef lineRef = (CTLineRef)[lines objectAtIndex:i];
        CFRange range = CTLineGetStringRange(lineRef);
    
        // This is the object I was referring to that provides me with a line's
        // meta-data. The _document is an instance of a specialized class I use to store
        // meta-data about the document which includes where keywords, variables,
        // numbers, etc. are located within the document. (fyi, this is for a text editor)
        NSUInteger lineLocation = [_document indexOfLineNumber:fromLineNumber];
    
        // Append the line number.
        if (lineLocation == range.location)
        {
            [string appendFormat:numFormat, actualLineNumber];
            actualLineNumber++;
            fromLine++;
        }
        // This is a continuation of a previous line (wrapped line).
        else
        {
            [string appendString:@"\n"];
        }
    }
    

    FYI, I didn't up any of the answers because I already knew the CTLineGetStringRange API call existed. I was hoping there was an API call that provided me with a boolean value or something that would indicate that a particular CTLineRef was a continuation of a previous line or not.