improved: rtf parser

This commit is contained in:
daboe01
2026-05-30 09:40:25 +02:00
parent 5c7215c455
commit 291be04dc3
+107 -18
View File
@@ -4,11 +4,6 @@
Copyright (C) 2014 Daniel Boehringer
FIXME: this class should be redone using a 'real' parser
* all paragraph spacing information is currently not parsed
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -37,6 +32,13 @@ FIXME: this class should be redone using a 'real' parser
@global CPFontAttributeName
@global CPForegroundColorAttributeName
@global CPBackgroundColorAttributeName
@global CPParagraphStyleAttributeName
@global CPLeftTabStopType
@global CPRightTabStopType
@global CPCenterTabStopType
@global CPDecimalTabStopType
var hexTable = [];
@@ -65,6 +67,7 @@ var cp1252Map = {
BOOL strikethrough;
BOOL script;
BOOL _tabChanged;
CPTabStopType _nextTabType;
}
- (id)init
@@ -74,6 +77,7 @@ var cp1252Map = {
[self resetFont];
[self resetParagraphStyle];
_range = CPMakeRange(0, 0);
_nextTabType = CPLeftTabStopType;
}
return self;
@@ -83,11 +87,19 @@ var cp1252Map = {
{
var mynew = [_RTFAttribute new];
mynew.paragraph = [paragraph copy];
mynew.paragraph = [paragraph mutableCopy];
mynew.fontName = fontName;
mynew.fontSize = fontSize;
mynew.bold = bold;
mynew.italic = italic;
mynew.underline = underline;
mynew.strikethrough = strikethrough;
mynew.script = script;
mynew.fgColour = fgColour;
mynew.bgColour = bgColour;
mynew.ulColour = ulColour;
mynew._tabChanged = _tabChanged;
mynew._nextTabType = _nextTabType;
return mynew;
}
@@ -143,7 +155,9 @@ var cp1252Map = {
- (void)resetParagraphStyle
{
paragraph = [[CPParagraphStyle defaultParagraphStyle] copy];
paragraph = [[CPParagraphStyle defaultParagraphStyle] mutableCopy];
_tabChanged = NO;
_nextTabType = CPLeftTabStopType;
}
- (void)resetFont
@@ -161,7 +175,7 @@ var cp1252Map = {
- (void)addTab:(float)location type:(CPTextTabType)type
{
var tab = [[CPTextTab alloc] initWithType:CPLeftTabStopType
var tab = [[CPTextTab alloc] initWithType:type
location:location];
if (!_tabChanged)
@@ -173,6 +187,8 @@ var cp1252Map = {
{
[paragraph addTabStop: tab];
}
_nextTabType = CPLeftTabStopType;
}
- (CPDictionary)dictionary
@@ -184,6 +200,9 @@ var cp1252Map = {
if (fgColour)
[ret setObject:fgColour forKey:CPForegroundColorAttributeName];
if (bgColour)
[ret setObject:bgColour forKey:CPBackgroundColorAttributeName];
return ret;
}
@end
@@ -202,7 +221,7 @@ var kRgsymRtf = {
"b" : [ "b", 1, false, kRTFParserType_prop, "propBold"],
"ul" : [ "ul", 1, false, kRTFParserType_prop, "propUnderline"],
"i" : [ "i", 1, false, kRTFParserType_prop, "propItalic"],
"li" : [ "li", 0, false, kRTFParserType_prop, "propPgnFormat"],
// "li" : [ "li", 0, false, kRTFParserType_prop, "propPgnFormat"],
"pgnucltr" : [ "pgnucltr", "pgULtr", true, kRTFParserType_prop, "propPgnFormat"],
"pgnlcltr" : [ "pgnlcltr", "pgLLtr", true, kRTFParserType_prop, "propPgnFormat"],
"qc" : [ "qc", "justC", true, kRTFParserType_prop, "propJust"],
@@ -330,7 +349,11 @@ var kRgsymRtf = {
- (BOOL)pushState
{
_states.push(_curState);
// Push stack as an object containing scoping context
_states.push({
curState: _curState,
run: [_currentRun copy]
});
return YES;
}
@@ -338,7 +361,12 @@ var kRgsymRtf = {
{
if (_states.length > 0)
{
_curState = _states.pop();
var state = _states.pop();
_curState = state.curState;
[self _flushCurrentRun];
_currentRun = state.run;
_currentRun._range = CPMakeRange([_result length], 0);
}
return YES;
}
@@ -412,10 +440,14 @@ var kRgsymRtf = {
var dict = [_currentRun dictionary];
[_result setAttributes:dict range:_currentRun._range]; // flush previous run
_currentRun.fgColour = [CPColor blackColor];
// Deep copy the current run style for the next sequence of characters
_currentRun = [_currentRun copy];
}
else
{
_currentRun = [_RTFAttribute new];
}
_currentRun._range = CPMakeRange(newOffset, 0); // open a new one
}
@@ -428,6 +460,7 @@ var kRgsymRtf = {
{
case "pard":
[self _flushCurrentRun];
[_currentRun resetParagraphStyle];
break;
case "b": // bold
@@ -436,7 +469,7 @@ var kRgsymRtf = {
if (_currentRun && _currentRun.bold)
[self _flushCurrentRun];
_currentRun.bold = NO
_currentRun.bold = NO;
}
else
{
@@ -454,7 +487,7 @@ var kRgsymRtf = {
if (_currentRun && _currentRun.italic)
[self _flushCurrentRun];
_currentRun.italic = NO
_currentRun.italic = NO;
}
else
{
@@ -470,6 +503,18 @@ var kRgsymRtf = {
[_currentRun.paragraph setAlignment:CPCenterTextAlignment];
break;
case "ql": // paragraph left
[_currentRun.paragraph setAlignment:CPLeftTextAlignment];
break;
case "qr": // paragraph right
[_currentRun.paragraph setAlignment:CPRightTextAlignment];
break;
case "qj": // paragraph justified
[_currentRun.paragraph setAlignment:CPJustifiedTextAlignment];
break;
case "paperw":
_paper.width = param;
break;
@@ -576,6 +621,20 @@ var kRgsymRtf = {
break;
case "cb": // change background color
case "highlight":
[self _flushCurrentRun];
var colorIndex = parseInt(param) - 1;
if (_currentRun)
{
if (colorIndex >= 0 && colorIndex < _colorArray.length)
_currentRun.bgColour = _colorArray[colorIndex];
else
_currentRun.bgColour = nil;
}
break;
case "f": // change font
[self _flushCurrentRun];
var fontIndex = parseInt(param);
@@ -589,11 +648,41 @@ var kRgsymRtf = {
_currentRun.fontSize = parseInt(param) / 2;
break;
case "tx": // tabstop
case "fi": // first line indent
if (_currentRun)
[_currentRun.paragraph setFirstLineHeadIndent:parseInt(param) / 20.0];
break;
case "li": // left indent / head indent
if (_currentRun)
[_currentRun.paragraph setHeadIndent:parseInt(param) / 20.0];
break;
case "ri": // right indent / tail indent
if (_currentRun)
[_currentRun.paragraph setTailIndent:parseInt(param) / 20.0];
break;
case "tqc": // center tab stop style flag
if (_currentRun)
_currentRun._nextTabType = CPCenterTabStopType;
break;
case "tqr": // right tab stop style flag
if (_currentRun)
_currentRun._nextTabType = CPRightTabStopType;
break;
case "tqdec": // decimal tab stop style flag
if (_currentRun)
_currentRun._nextTabType = CPDecimalTabStopType;
break;
case "tx": // tabstop location definition
var location = parseInt(param) / 20;
if (_currentRun)
[_currentRun addTab:location type:CPLeftTabStopType];
[_currentRun addTab:location type:_currentRun._nextTabType];
break;
@@ -739,12 +828,12 @@ var kRgsymRtf = {
{
var byteVal = parseInt(ch, 16);
var unicodeVal = byteVal;
// Windows-1252 Mapping für den Bereich 0x80 - 0x9F anwenden
if (byteVal >= 0x80 && byteVal <= 0x9F) {
unicodeVal = cp1252Map[byteVal] || byteVal;
}
[self _appendPlainString: String.fromCharCode(unicodeVal)];
}
_hexreturn = NO;