improved: rtf roundtrip

This commit is contained in:
daboe01
2026-06-15 19:42:53 +02:00
parent 1b23bb8a67
commit 2a0cebb851
3 changed files with 39 additions and 17 deletions
+18 -1
View File
@@ -178,7 +178,15 @@ var cp1252Map = {
- (void)addTab:(float)location type:(CPTextTabType)type
{
var tab = [[CPTextTab alloc] initWithType:type
var alignment = CPLeftTextAlignment;
if (type === CPCenterTabStopType || type === CPCenterTextAlignment)
alignment = CPCenterTextAlignment;
else if (type === CPRightTabStopType || type === CPRightTextAlignment)
alignment = CPRightTextAlignment;
else if (type === CPDecimalTabStopType)
alignment = CPRightTextAlignment; // Fallback alignment for decimal tab
var tab = [[CPTextTab alloc] initWithType:alignment
location:location];
if (!_tabChanged)
@@ -512,6 +520,9 @@ var kRgsymRtf = {
{
if (_tableRows && [_tableRows count] > 0)
{
// Flush active character styling runs before appending table layout changes
[self _flushCurrentRun];
var headers = [_tableRows objectAtIndex:0];
var rows = [CPMutableArray array];
for (var idx = 1; idx < [_tableRows count]; idx++)
@@ -536,6 +547,12 @@ var kRgsymRtf = {
[_result appendAttributedString:tableAttrStr];
// Update range offset of active attributes tracker
if (_currentRun)
{
_currentRun._range = CPMakeRange([_result length], 0);
}
_tableRows = nil;
_currentRow = nil;
_currentCellText = "";
+16 -2
View File
@@ -357,14 +357,21 @@ function _points2twips(a) { return (a) * 20.0; }
while ((tab = [enumerator nextObject]))
{
switch ([tab tabStopType])
var tabType = [tab respondsToSelector:@selector(tabStopType)] ? [tab tabStopType] : nil;
if (tabType === nil && [tab respondsToSelector:@selector(alignment)])
tabType = [tab alignment];
switch (tabType)
{
case CPLeftTabStopType:
case CPLeftTextAlignment:
break;
case CPRightTabStopType:
case CPRightTextAlignment:
headerString += @"\\tqr";
break;
case CPCenterTabStopType:
case CPCenterTextAlignment:
headerString += @"\\tqc";
break;
case CPDecimalTabStopType:
@@ -384,6 +391,13 @@ function _points2twips(a) { return (a) * 20.0; }
{
var unwrap = function(obj) {
if (!obj) return null;
// If the object contains the table structures, bypass unwrapping
if ((typeof obj.respondsToSelector === "function" && ([obj respondsToSelector:@selector(headers)] || [obj respondsToSelector:@selector(rows)])) ||
obj.headers || obj._headers || obj.rows || obj._rows) {
return obj;
}
var unwrapped = null;
if (typeof obj.respondsToSelector === "function") {
if ([obj respondsToSelector:@selector(attachmentCell)]) {
@@ -679,7 +693,7 @@ function _points2twips(a) { return (a) * 20.0; }
substring = substring.replace(/\\/g, '\\\\');
substring = substring.replace(/\n/g, '\\par\n');
substring = substring.replace(/\t/g, '\\tab');
substring = substring.replace(/\t/g, '\\tab ');
substring = substring.replace(/{/g, '\\{');
substring = substring.replace(/}/g, '\\}');
+5 -14
View File
@@ -406,20 +406,11 @@
var parser = [[_CPRTFParser alloc] init];
var roundTrippedString = [parser parseRTF:generatedRTF];
// 5. Replace the editor's text storage with the round-tripped version
var editorStorage = [_textView textStorage];
if (editorStorage && [editorStorage respondsToSelector:@selector(setAttributedString:)])
{
[editorStorage setAttributedString:roundTrippedString];
}
else
{
// Safe fallback sequence
[_textView setEditable:YES];
[_textView setString:@""];
[_textView insertText:roundTrippedString];
[_textView setEditable:NO];
}
// Safe fallback sequence
[_textView setEditable:YES];
[_textView setString:@""];
[_textView insertText:roundTrippedString];
[_textView setEditable:NO];
// 6. Force a layout pass and render update
[_textView setNeedsDisplay:YES];