From 36902cbc6ccf32fe522d4a5f60c2db93b37dc9a7 Mon Sep 17 00:00:00 2001 From: Allan Odgaard Date: Fri, 14 Dec 2012 20:16:52 +0100 Subject: [PATCH] =?UTF-8?q?Factor=20out=20ng::range=5Ft=20=E2=87=94=20NSRa?= =?UTF-8?q?nge=20methods?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Frameworks/OakTextView/src/OakTextView.mm | 48 +++++++++++++++-------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/Frameworks/OakTextView/src/OakTextView.mm b/Frameworks/OakTextView/src/OakTextView.mm index 7a74cf54..45aed3cb 100644 --- a/Frameworks/OakTextView/src/OakTextView.mm +++ b/Frameworks/OakTextView/src/OakTextView.mm @@ -57,6 +57,8 @@ NSString* const kUserDefaultsDisableAntiAliasKey = @"disableAntiAlias"; - (void)recordSelector:(SEL)aSelector withArgument:(id)anArgument; - (NSImage*)imageForRanges:(ng::ranges_t const&)ranges imageRect:(NSRect*)outRect; - (void)highlightRanges:(ng::ranges_t const&)ranges; +- (NSRange)nsRangeForRange:(ng::range_t const&)range; +- (ng::range_t const&)rangeForNSRange:(NSRange)nsRange; @property (nonatomic, readonly) ng::ranges_t const& markedRanges; @property (nonatomic, retain) NSDate* optionDownDate; @property (nonatomic, retain) OakTimer* initiateDragTimer; @@ -633,6 +635,29 @@ static std::string shell_quote (std::vector paths) // = Accented input = // ================== +- (NSRange)nsRangeForRange:(ng::range_t const&)range +{ + //TODO this and the next method could use some optimization using an interval tree + // similar to basic_tree_t for conversion between UTF-8 and UTF-16 indexes. + // Currently poor performance for large documents (O(N)) would then get to O(log(N)) + // Also currently copy of whole text is created here, which is not optimal + std::string const text = document->buffer().substr(0, range.max().index); + char const* base = text.data(); + NSUInteger location = utf16::distance(base, base + range.min().index); + NSUInteger length = utf16::distance(base + range.min().index, base + range.max().index); + return NSMakeRange(location, length); +} + +- (ng::range_t const&)rangeForNSRange:(NSRange)nsRange +{ + std::string const text = editor->as_string(); + char const* base = text.data(); + ng::index_t from = utf16::advance(base, nsRange.location, base + text.size()) - base; + ng::index_t to = utf16::advance(base + from.index, nsRange.length, base + text.size()) - base; + static ng::range_t res; + return res = ng::range_t(from, to); +} + - (void)setMarkedText:(id)aString selectedRange:(NSRange)aRange { D(DBF_OakTextView_TextInput, bug("ā€˜%s’ %s\n", to_s([aString description]).c_str(), [NSStringFromRange(aRange) UTF8String]);); @@ -670,9 +695,7 @@ static std::string shell_quote (std::vector paths) - (NSRange)selectedRange { - std::string const text = editor->as_string(); - ng::range_t const r = editor->ranges().last(); - NSRange res = NSMakeRange(utf16::distance(text.data(), text.data() + r.min().index), utf16::distance(text.data() + r.min().index, text.data() + r.max().index)); + NSRange res = [self nsRangeForRange:editor->ranges().last()]; D(DBF_OakTextView_TextInput, bug("%s\n", [NSStringFromRange(res) UTF8String]);); return res; } @@ -682,10 +705,7 @@ static std::string shell_quote (std::vector paths) D(DBF_OakTextView_TextInput, bug("%s\n", to_s(markedRanges).c_str());); if(markedRanges.empty()) return NSMakeRange(NSNotFound, 0); - - ng::range_t const r = markedRanges.last(); - std::string const text = document->buffer().substr(0, r.max().index); - return NSMakeRange(utf16::distance(text.data(), text.data() + r.min().index), utf16::distance(text.data() + r.min().index, text.data() + r.max().index)); + return [self nsRangeForRange:markedRanges.last()]; } - (void)unmarkText @@ -737,10 +757,8 @@ static std::string shell_quote (std::vector paths) - (NSAttributedString*)attributedSubstringFromRange:(NSRange)theRange { - std::string const text = editor->as_string(); - char const* const base = text.data(); - size_t from = utf16::advance(base, theRange.location, base + text.size()) - base; - size_t to = utf16::advance(base + from, theRange.length, base + text.size()) - base; + ng::range_t const& r = [self rangeForNSRange:theRange]; + size_t from = r.min().index, to = r.max().index; CFMutableAttributedStringRef res = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0); std::map scopes = document->buffer().scopes(from, to); @@ -752,7 +770,7 @@ static std::string shell_quote (std::vector paths) size_t j = ++pair != scopes.end() ? from + pair->first : to; CFMutableAttributedStringRef str = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0); - CFAttributedStringReplaceString(str, CFRangeMake(0, 0), cf::wrap(text.substr(i, j - i))); + CFAttributedStringReplaceString(str, CFRangeMake(0, 0), cf::wrap(document->buffer().substr(i, j))); CFAttributedStringSetAttribute(str, CFRangeMake(0, CFAttributedStringGetLength(str)), kCTFontAttributeName, styles.font()); CFAttributedStringSetAttribute(str, CFRangeMake(0, CFAttributedStringGetLength(str)), kCTForegroundColorAttributeName, styles.foreground()); if(styles.underlined()) @@ -766,10 +784,8 @@ static std::string shell_quote (std::vector paths) - (NSRect)firstRectForCharacterRange:(NSRange)theRange { - std::string const text = editor->as_string(); - - size_t index = utf16::advance(text.data(), theRange.location, text.data() + text.size()) - text.data(); - NSRect rect = [self convertRect:layout->rect_at_index(index) toView:nil]; + ng::range_t const& r = [self rangeForNSRange:theRange]; + NSRect rect = [self convertRect:layout->rect_at_index(r.min()) toView:nil]; rect.origin = [[self window] convertBaseToScreen:rect.origin]; D(DBF_OakTextView_TextInput, bug("%s → %s\n", [NSStringFromRange(theRange) UTF8String], [NSStringFromRect(rect) UTF8String]);); return rect;