From d75c0ac452b0b7bfa18c4f0355fa6890fe66986a Mon Sep 17 00:00:00 2001 From: daboe01 Date: Tue, 16 Jun 2026 17:28:03 +0200 Subject: [PATCH] improved: tab management --- AppKit/CPTextView/CPLayoutManager.j | 75 +++++++++++++++++++++++++++-- AppKit/CPTextView/CPTextView.j | 4 ++ 2 files changed, 74 insertions(+), 5 deletions(-) diff --git a/AppKit/CPTextView/CPLayoutManager.j b/AppKit/CPTextView/CPLayoutManager.j index 22fb6ba19..32810373b 100644 --- a/AppKit/CPTextView/CPLayoutManager.j +++ b/AppKit/CPTextView/CPLayoutManager.j @@ -1132,6 +1132,10 @@ var _objectsInRange = function(aList, aRange) - (id)createDOMElementWithText:(CPString)aString andFont:(CPFont)aFont andColor:(CPColor)fgColor andBackgroundColor:(CPColor)bgColor andUnderline:(CPUnderlineStyle)aUnderline { + + if (!aString || aString.length === 0) + return nil; + #if PLATFORM(DOM) var style, span = document.createElement("span"); @@ -1212,7 +1216,8 @@ var _objectsInRange = function(aList, aRange) effectiveRange = attributes ? CPIntersectionRange(aRange, effectiveRange) : aRange; var string = [textStorage._string substringWithRange:effectiveRange], - underline = [attributes objectForKey:CPUnderlineStyleAttributeName] || CPUnderlineStyleNone; + underline = [attributes objectForKey:CPUnderlineStyleAttributeName] || CPUnderlineStyleNone, + paragraphStyle = [attributes objectForKey:CPParagraphStyleAttributeName] || [CPParagraphStyle defaultParagraphStyle]; // this is an attachment -> create a run for it if (string === _CPAttachmentCharacterAsString) @@ -1220,17 +1225,71 @@ var _objectsInRange = function(aList, aRange) if (![attributes objectForKey:_CPAttachmentInvisible]) { var view = [attributes objectForKey:_CPAttachmentView]; - var run = {_range:CPMakeRangeCopy(effectiveRange), color:nil, font:nil, elem:nil, string:nil, view:view}; } + var run = {_range:CPMakeRangeCopy(effectiveRange), color:nil, font:nil, elem:nil, string:nil, view:view, paragraphStyle:paragraphStyle}; _runs.push(run); + } } else { var color = [attributes objectForKey:CPForegroundColorAttributeName], bgcolor = [attributes objectForKey:CPBackgroundColorAttributeName], - font = [attributes objectForKey:CPFontAttributeName] || [textStorage font] || [CPFont systemFontOfSize:12.0], - run = {_range:CPMakeRangeCopy(effectiveRange), color:color, font:font, elem:nil, string:string, bgcolor:bgcolor}; + font = [attributes objectForKey:CPFontAttributeName] || [textStorage font] || [CPFont systemFontOfSize:12.0]; - _runs.push(run); + var currentLoc = effectiveRange.location, + strLen = string.length, + startIdx = 0; + + for (var i = 0; i < strLen; i++) + { + if (string.charCodeAt(i) === 9) // Tabulator-Zeichen '\t' + { + if (i > startIdx) + { + var subString = string.substring(startIdx, i), + subRange = CPMakeRange(currentLoc + startIdx, i - startIdx), + run = { + _range: subRange, + color: color, + font: font, + elem: nil, + string: subString, + bgcolor: bgcolor, + paragraphStyle: paragraphStyle + }; + _runs.push(run); + } + + var tabRange = CPMakeRange(currentLoc + i, 1), + tabRun = { + _range: tabRange, + color: nil, + font: nil, + elem: nil, + string: nil, + bgcolor: nil, + paragraphStyle: paragraphStyle + }; + _runs.push(tabRun); + + startIdx = i + 1; + } + } + + if (startIdx < strLen) + { + var subString = string.substring(startIdx, strLen), + subRange = CPMakeRange(currentLoc + startIdx, strLen - startIdx), + run = { + _range: subRange, + color: color, + font: font, + elem: nil, + string: subString, + bgcolor: bgcolor, + paragraphStyle: paragraphStyle + }; + _runs.push(run); + } } if (!CPMaxRange(effectiveRange)) @@ -1401,6 +1460,12 @@ var _objectsInRange = function(aList, aRange) if (newFragmentRuns[i].color !== oldFragmentRuns[i].color || newFragmentRuns[i].bgcolor !== oldFragmentRuns[i].bgcolor || newFragmentRuns[i].font !== oldFragmentRuns[i].font) return NO; + + var oldStyle = oldFragmentRuns[i].paragraphStyle || [CPParagraphStyle defaultParagraphStyle], + newStyle = newFragmentRuns[i].paragraphStyle || [CPParagraphStyle defaultParagraphStyle]; + + if (![oldStyle isEqual:newStyle]) + return NO; } return YES; diff --git a/AppKit/CPTextView/CPTextView.j b/AppKit/CPTextView/CPTextView.j index fa6db4378..ddba66801 100644 --- a/AppKit/CPTextView/CPTextView.j +++ b/AppKit/CPTextView/CPTextView.j @@ -2648,6 +2648,10 @@ var compareTabStops = function(obj1, obj2, context) { [_typingAttributes setObject:mutableStyle forKey:CPParagraphStyleAttributeName]; [[CPNotificationCenter defaultCenter] postNotificationName:CPTextViewDidChangeTypingAttributesNotification object:self]; } + + [_layoutManager _validateLayoutAndGlyphs]; + [self sizeToFit]; + [self setNeedsDisplay:YES]; } - (void)rulerView:(CPRulerView)rulerView didRemoveMarker:(CPRulerMarker)marker