Fixed: circular import with CPText

Previously CPText was in CPTextView.j, now it is in CPText.j.
It fixes some other circular import as well, fixes some global var to import.
Fixed some code style.
This commit is contained in:
Alexandre Wilhelm
2014-07-12 14:03:32 +02:00
committed by daboe01
parent 81a8e91180
commit 39eeaea7e7
10 changed files with 519 additions and 371 deletions
+10
View File
@@ -467,6 +467,16 @@ var cachedBlackColor,
return [[CPColor alloc] _initWithCSSString: aString];
}
+ (CPColor)selectedTextBackgroundColor
{
return [CPColor colorWithHexString:"99CCFF"];
}
+ (CPColor)selectedTextBackgroundColorUnfocussed
{
return [CPColor colorWithHexString:"CCCCCC"];
}
/* @ignore */
- (id)_initWithCSSString:(CPString)aString
{
+10
View File
@@ -42,6 +42,16 @@
@end
@global CPCancelTextMovement
@global CPLeftTextMovement
@global CPRightTextMovement
@global CPUpTextMovement
@global CPDownTextMovement
@global CPReturnTextMovement
@global CPBacktabTextMovement
@global CPTabTextMovement
@global CPOtherTextMovement
CPLeftTextAlignment = 0;
CPRightTextAlignment = 1;
CPCenterTextAlignment = 2;
+3 -1
View File
@@ -28,11 +28,13 @@
@import "CPCompatibility.j"
@import "CGGeometry.j"
@import "CPText.j"
@class CPTextField
@global CPApp
@global CPNewlineCharacter
@global CPCarriageReturnCharacter
@global CPEnterCharacter
var _CPEventPeriodicEventPeriod = 0,
_CPEventPeriodicEventTimer = nil,
+210
View File
@@ -27,6 +27,16 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/Foundation.j>
@import "CPPasteboard.j"
@import "CPView.j"
@import "_CPRTFParser.j"
@import "_CPRTFProducer.j"
@global CPStringPboardType
@class CPAttributedString
@protocol CPTextDelegate <CPObject>
- (BOOL)textShouldBeginEditing:(CPText)aTextObject;
@@ -86,3 +96,203 @@ CPBaselineOffsetAttributeName = @"CPBaselineOffsetAttributeName";
CPAttachmentAttributeName = @"CPAttachmentAttributeName";
CPLigatureAttributeName = @"CPLigatureAttributeName";
CPKernAttributeName = @"CPKernAttributeName";
@implementation CPText : CPView
{
int _previousSelectionGranularity;
}
- (void)changeFont:(id)sender
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (void)copy:(id)sender
{
var selectedRange = [self selectedRange];
if (selectedRange.length < 1)
return;
var pasteboard = [CPPasteboard generalPasteboard],
stringForPasting = [[self stringValue] substringWithRange:selectedRange];
[pasteboard declareTypes:[CPStringPboardType] owner:nil];
if ([self isRichText])
{
// crude hack to make rich pasting possible in chrome and firefox. this requires a RTF roundtrip, unfortunately
var richData = [_CPRTFProducer produceRTF:[[self textStorage] attributedSubstringFromRange:selectedRange] documentAttributes:@{}];
[pasteboard setString:richData forType:CPStringPboardType];
}
else
{
[pasteboard setString:stringForPasting forType:CPStringPboardType];
}
}
- (void)paste:(id)sender
{
var pasteboard = [CPPasteboard generalPasteboard],
// dataForPasting = [pasteboard dataForType:CPRichStringPboardType],
stringForPasting = [pasteboard stringForType:CPStringPboardType];
if ([stringForPasting hasPrefix:"{\\rtf1\\ansi"])
stringForPasting = [[_CPRTFParser new] parseRTF:stringForPasting];
if (![self isRichText] && [stringForPasting isKindOfClass:[CPAttributedString class]])
stringForPasting = stringForPasting._string;
if (_previousSelectionGranularity > 0)
{
// FIXME: handle smart pasting
}
if (stringForPasting)
[self insertText:stringForPasting];
}
- (void)copyFont:(id)sender
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (void)delete:(id)sender
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (CPFont)font:(CPFont)aFont
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
return nil;
}
- (BOOL)isHorizontallyResizable
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
return NO;
}
- (BOOL)isRichText
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
return NO;
}
- (BOOL)isRulerVisible
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
return NO;
}
- (BOOL)isVerticallyResizable
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
return NO;
}
- (CGSize)maxSize
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
return CGSizeMake(0,0);
}
- (CGSize)minSize
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
return CGSizeMake(0,0);
}
- (void)pasteFont:(id)sender
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (void)replaceCharactersInRange:(CPRange)aRange withString:(CPString)aString
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (void)scrollRangeToVisible:(CPRange)aRange
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (void)selectedAll:(id)sender
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (CPRange)selectedRange
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
return CPMakeRange(CPNotFound, 0);
}
- (void)setFont:(CPFont)aFont
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (void)setFont:(CPFont)aFont rang:(CPRange)aRange
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (void)setHorizontallyResizable:(BOOL)flag
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (void)setMaxSize:(CGSize)aSize
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (void)setMinSize:(CGSize)aSize
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (void)setString:(CPString)aString
{
[self replaceCharactersInRange:CPMakeRange(0, [[self string] length]) withString:aString];
}
- (void)setUsesFontPanel:(BOOL)flag
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (void)setVerticallyResizable:(BOOL)flag
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (CPString)string
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
return nil;
}
- (void)underline:(id)sender
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (BOOL)usesFontPanel
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
return NO;
}
@end
+50 -29
View File
@@ -25,7 +25,6 @@
*/
@import <Foundation/CPObject.j>
@import "CPControl.j"
var _sharedDefaultParagraphStyle,
_defaultTabStopArray;
@@ -42,8 +41,8 @@ CPParagraphStyleAttributeName = @"CPParagraphStyleAttributeName";
@implementation CPTextTab : CPObject
{
int _type @accessors(property=tabStopType);
double _location @accessors(property=location);
int _type @accessors(property = tabStopType);
double _location @accessors(property = location);
}
- (id)initWithType:(CPTabStopType) aType location:(double) aLocation
@@ -57,6 +56,10 @@ CPParagraphStyleAttributeName = @"CPParagraphStyleAttributeName";
return self;
}
#pragma mark -
#pragma mark Coding methods
- (id)initWithCoder:(id)aCoder
{
self = [self init];
@@ -78,25 +81,30 @@ CPParagraphStyleAttributeName = @"CPParagraphStyleAttributeName";
@end
@implementation CPParagraphStyle : CPObject
{
CPArray _tabStops @accessors(property = tabStops);
CPTextAlignment _alignment @accessors(property = alignment);
unsigned _firstLineHeadIndent @accessors(property = firstLineHeadIndent);
unsigned _headIndent @accessors(property = headIndent);
unsigned _tailIndent @accessors(property = tailIndent);
unsigned _paragraphSpacing @accessors(property = paragraphSpacing);
unsigned _minimumLineHeight @accessors(property = minimumLineHeight);
unsigned _maximumLineHeight @accessors(property = maximumLineHeight);
unsigned _lineSpacing @accessors(property = lineSpacing);
CPArray _tabStops @accessors(property = tabStops);
CPTextAlignment _alignment @accessors(property = alignment);
unsigned _firstLineHeadIndent @accessors(property = firstLineHeadIndent);
unsigned _headIndent @accessors(property = headIndent);
unsigned _tailIndent @accessors(property = tailIndent);
unsigned _paragraphSpacing @accessors(property = paragraphSpacing);
unsigned _minimumLineHeight @accessors(property = minimumLineHeight);
unsigned _maximumLineHeight @accessors(property = maximumLineHeight);
unsigned _lineSpacing @accessors(property = lineSpacing);
}
#pragma mark -
#pragma mark Class methods
+ (CPParagraphStyle)defaultParagraphStyle
{
if (!_sharedDefaultParagraphStyle)
if (!_sharedDefaultParagraphStyle)
_sharedDefaultParagraphStyle = [self new];
return _sharedDefaultParagraphStyle;
return _sharedDefaultParagraphStyle;
}
+ (CPArray)_defaultTabStops
@@ -112,18 +120,13 @@ CPParagraphStyleAttributeName = @"CPParagraphStyleAttributeName";
_defaultTabStopArray.push([[CPTextTab alloc] initWithType:CPLeftTabStopType location:i * 28]);
}
}
return _defaultTabStopArray;
}
- (void)addTabStop:(CPTextTab)aStop
{
_tabStops.push(aStop);
return _defaultTabStopArray;
}
- (void)_initWithDefaults
{
_alignment = CPLeftTextAlignment;
_tabStops = [[[self class] _defaultTabStops] copy];
}
#pragma mark -
#pragma mark Init methods
- (id)init
{
@@ -131,11 +134,7 @@ CPParagraphStyleAttributeName = @"CPParagraphStyleAttributeName";
return self;
}
- (id)copy
{
var other = [[self class] alloc];
return [other initWithParagraphStyle:self];
}
- (CPParagraphStyle)initWithParagraphStyle:(CPParagraphStyle)other
{
other._tabStops = [_tabStops copy];
@@ -151,6 +150,28 @@ CPParagraphStyleAttributeName = @"CPParagraphStyleAttributeName";
return self;
}
- (void)_initWithDefaults
{
_alignment = CPLeftTextAlignment;
_tabStops = [[[self class] _defaultTabStops] copy];
}
- (void)addTabStop:(CPTextTab)aStop
{
_tabStops.push(aStop);
}
- (id)copy
{
var other = [[self class] alloc];
return [other initWithParagraphStyle:self];
}
#pragma mark -
#pragma mark Code methods
- (id)initWithCoder:(id)aCoder
{
self = [self init];
-1
View File
@@ -27,7 +27,6 @@
@class CPLayoutManager;
CPTextStorageEditedAttributes = 1;
CPTextStorageEditedCharacters = 2;
+5 -212
View File
@@ -24,12 +24,12 @@
*/
@import "CPText.j"
@import "CPTextStorage.j"
@import "CPTextContainer.j"
@import "CPFontManager.j"
@import "CPLayoutManager.j"
@import "CPPasteboard.j"
@import "CPColorPanel.j"
@import "CPFontManager.j"
@import "CPTextStorage.j"
@import "CPTextContainer.j"
@import "CPLayoutManager.j"
@class _CPRTFProducer;
@class _CPRTFParser;
@@ -57,22 +57,6 @@ _MidRange = function(a1)
return Math.floor((CPMaxRange(a1) + a1.location) / 2);
};
// FIXME: move to CPColor, and use attribut theme for the color
@implementation CPColor (CPTextViewExtensions)
+ (CPColor)selectedTextBackgroundColor
{
return [CPColor colorWithHexString:"99CCFF"];
}
+ (CPColor)selectedTextBackgroundColorUnfocussed
{
return [CPColor colorWithHexString:"CCCCCC"];
}
@end
/*
CPSelectionGranularity
*/
@@ -87,197 +71,6 @@ var kDelegateRespondsTo_textShouldBeginEditing
kDelegateRespondsTo_textView_shouldChangeTextInRange_replacementString = 0x0008,
kDelegateRespondsTo_textView_shouldChangeTypingAttributes_toAttributes = 0x0010;
@implementation CPText : CPView
{
int _previousSelectionGranularity;
}
- (void)changeFont:(id)sender
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (void)copy:(id)sender
{
var selectedRange = [self selectedRange];
if (selectedRange.length < 1)
return;
var pasteboard = [CPPasteboard generalPasteboard],
stringForPasting = [[self stringValue] substringWithRange:selectedRange];
[pasteboard declareTypes:[CPStringPboardType] owner:nil];
if ([self isRichText])
{
// crude hack to make rich pasting possible in chrome and firefox. this requires a RTF roundtrip, unfortunately
var richData = [_CPRTFProducer produceRTF:[[self textStorage] attributedSubstringFromRange:selectedRange] documentAttributes:@{}];
[pasteboard setString:richData forType:CPStringPboardType];
}
else
[pasteboard setString:stringForPasting forType:CPStringPboardType];
}
- (void)paste:(id)sender
{
var pasteboard = [CPPasteboard generalPasteboard],
// dataForPasting = [pasteboard dataForType:CPRichStringPboardType],
stringForPasting = [pasteboard stringForType:CPStringPboardType];
if ([stringForPasting hasPrefix:"{\\rtf1\\ansi"])
stringForPasting = [[_CPRTFParser new] parseRTF:stringForPasting];
if (![self isRichText] && [stringForPasting isKindOfClass:[CPAttributedString class]])
stringForPasting = stringForPasting._string;
if (_previousSelectionGranularity > 0)
{
// FIXME: handle smart pasting
}
if (stringForPasting)
[self insertText:stringForPasting];
}
- (void)copyFont:(id)sender
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (void)delete:(id)sender
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (CPFont)font:(CPFont)aFont
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
return nil;
}
- (BOOL)isHorizontallyResizable
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
return NO;
}
- (BOOL)isRichText
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
return NO;
}
- (BOOL)isRulerVisible
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
return NO;
}
- (BOOL)isVerticallyResizable
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
return NO;
}
- (CGSize)maxSize
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
return CPMakeSize(0,0);
}
- (CGSize)minSize
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
return CPMakeSize(0,0);
}
- (void)pasteFont:(id)sender
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (void)replaceCharactersInRange:(CPRange)aRange withString:(CPString)aString
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (void)scrollRangeToVisible:(CPRange)aRange
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (void)selectedAll:(id)sender
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (CPRange)selectedRange
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
return CPMakeRange(CPNotFound, 0);
}
- (void)setFont:(CPFont)aFont
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (void)setFont:(CPFont)aFont rang:(CPRange)aRange
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (void)setHorizontallyResizable:(BOOL)flag
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (void)setMaxSize:(CGSize)aSize
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (void)setMinSize:(CGSize)aSize
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (void)setString:(CPString)aString
{
[self replaceCharactersInRange:CPMakeRange(0, [[self string] length]) withString:aString];
}
- (void)setUsesFontPanel:(BOOL)flag
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (void)setVerticallyResizable:(BOOL)flag
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (CPString)string
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
return nil;
}
- (void)underline:(id)sender
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
- (BOOL)usesFontPanel
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
return NO;
}
@end
/*!
@ingroup appkit
@class CPTextView
@@ -694,7 +487,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
- (void)insertText:(CPString)aString
{
var isAttributed = [aString isKindOfClass:CPAttributedString],
string = (isAttributed)?[aString string]:aString;
string = isAttributed ? [aString string]:aString;
if (![self shouldChangeTextInRange:CPMakeRangeCopy(_selectionRange) replacementString:string])
return;
+8 -2
View File
@@ -50,6 +50,7 @@ function _widthOfStringForFont(aString, aFont)
{
if (!_measuringContext)
_measuringContext = CGBitmapGraphicsContextCreate();
if (!_didTestCanvasSizingValid && CPFeatureIsCompatible(CPHTMLCanvasFeature))
{
var teststring = "0123456879abcdefghiklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,.-()";
@@ -57,20 +58,24 @@ function _widthOfStringForFont(aString, aFont)
_measuringContext.font = [aFont cssString];
_isCanvasSizingInvalid = [teststring sizeWithFont:aFont].width != _measuringContext.measureText(teststring).width;
}
if (!CPFeatureIsCompatible(CPHTMLCanvasFeature) || _isCanvasSizingInvalid) // measuring with canvas is _much_ faster on chrome
return [aString sizeWithFont:aFont];
if (_measuringContextFont !== aFont)
{
_measuringContextFont = aFont;
_measuringContext.font = [aFont cssString];
}
return _measuringContext.measureText(aString);
}
var CPSystemTypesetterFactory = Nil;
var CPSystemTypesetterFactory = nil;
@implementation CPTypesetter : CPObject
{
}
+ (id)sharedSystemTypesetter
@@ -118,9 +123,10 @@ var CPSystemTypesetterFactory = Nil;
@end
var _sharedSimpleTypesetter = nil;
@implementation CPSimpleTypesetter:CPTypesetter
@implementation CPSimpleTypesetter : CPTypesetter
{
CPLayoutManager _layoutManager;
CPTextContainer _currentTextContainer;
+153 -85
View File
@@ -27,27 +27,29 @@ e.g. using zaach/jison on github
@import <Foundation/CPAttributedString.j>
@import <Foundation/CPGeometry.j>
@import "CPFontManager.j"
@import "CPText.j"
@import "CPParagraphStyle.j"
@global CPFontAttributeName
@global CPForegroundColorAttributeName
var hexTable = [];
// Hold the attributes of the current run
@implementation _RTFAttribute : CPObject
{
CPRange _range;
CPParagraphStyle paragraph;
CPColor fgColour;
CPColor bgColour;
CPColor ulColour;
CPString fontName;
unsigned fontSize;
BOOL bold;
BOOL italic;
BOOL underline;
BOOL strikethrough;
BOOL script;
BOOL _tabChanged;
CPRange _range;
CPParagraphStyle paragraph;
CPColor fgColour;
CPColor bgColour;
CPColor ulColour;
CPString fontName;
unsigned fontSize;
BOOL bold;
BOOL italic;
BOOL underline;
BOOL strikethrough;
BOOL script;
BOOL _tabChanged;
}
- (id)init
@@ -94,7 +96,6 @@ var hexTable = [];
if (font == nil)
{
/* Last resort, default font. :-( */
font = [CPFont systemFontOfSize:fontSize];
}
@@ -288,6 +289,7 @@ var kRgsymRtf = {
_freename = "";
_parsingFontTable = NO;
}
return self;
}
@@ -301,12 +303,14 @@ var kRgsymRtf = {
case 1:
console.log("skipped : " + sym[4]);
return '';
return '';
default:
if (sym && sym[4])
return sym[4];
}
}
- (BOOL)pushState
{
_states.push["group"];
@@ -319,112 +323,139 @@ var kRgsymRtf = {
if (_curState > 0)
_curState--;
return YES;
}
- (CPString)_parseSpec:(CPArray)sym parameter:(CPString)v
{
var ch = '';
switch (sym[4])
{
case "ipfnDestSkip":
_curState++;
return '';
_curState++;
return '';
case "ipfnHex":
ch = _rtf.charAt(++_currentParseIndex);
var hex = '';
while (/[a-fA-F0-9\']/.test(ch))
{
if (ch == "'")
{
_currentParseIndex++;
continue;
}
hex += (ch + '');
ch = _rtf.charAt(++_currentParseIndex);
}
//ch = parseInt(ch, 16);
console.log("hex : " + hex);
_hexreturn = YES;
_currentParseIndex--;
if (_curState !== 0)
return '';
else return hex;
break;
ch = _rtf.charAt(++_currentParseIndex);
var hex = '';
while (/[a-fA-F0-9\']/.test(ch))
{
if (ch == "'")
{
_currentParseIndex++;
continue;
}
hex += (ch + '');
ch = _rtf.charAt(++_currentParseIndex);
}
//ch = parseInt(ch, 16);
//console.log("hex : " + hex);
_hexreturn = YES;
_currentParseIndex--;
if (_curState !== 0)
return '';
else
return hex;
break;
case "codePage":
ch = _rtf.charAt(++_currentParseIndex);
var code = '';
while (/[0-9]/.test(ch))
{
code += (ch + '');
ch = _rtf.charAt(++_currentParseIndex);
}
_codePage = code;
_currentParseIndex--;
break;
break;
}
return '';
}
- (void)_flushCurrentRun
{
var newOffset = 0;
if (_currentRun)
{
if ([_result length] == _currentRun._range.location)
return;
_currentRun._range.length = [_result length] - _currentRun._range.location;
newOffset = CPMaxRange(_currentRun._range);
var dict = [_currentRun dictionary];
[_result setAttributes:dict range:_currentRun._range]; // flush previous run
}
_currentRun = [_RTFAttribute new];
_currentRun._range = CPMakeRange(newOffset, 0); // open a new one
}
- (CPString)_applyPropChange:sym parameter:param
{
console.log("prop : " + sym[0] + " / param : " + param+ ' ');
//console.log("prop : " + sym[0] + " / param : " + param+ ' ');
switch (sym[0])
{
case "pard":
[self _flushCurrentRun];
break;
break;
case "b": // bold
if (param === 0)
{
if (_currentRun && _currentRun.bold)
[self _flushCurrentRun];
_currentRun.bold = NO
} else
}
else
{
if (_currentRun && !_currentRun.bold)
[self _flushCurrentRun]
_currentRun.bold = YES;
}
break;
break;
case "i": // italic
if (param === 0)
{
if (_currentRun && _currentRun.italic)
[self _flushCurrentRun];
_currentRun.italic = NO
} else
}
else
{
if (_currentRun && !_currentRun.italic)
[self _flushCurrentRun]
_currentRun.italic = YES;
}
break;
break;
case "qc": // paragraph center
[_currentRun.paragraph setAlignment:CPCenterTextAlignment];
break;
break;
case "paperw":
_paper.width = param;
break;
break;
case "paperh":
_paper.height = param;
break;
break;
}
return '';
@@ -437,17 +468,19 @@ var kRgsymRtf = {
{
case "colortbl":
_colorArray.push([CPColor blackColor]);
break;
break;
case "fonttbl":
_parsingFontTable = YES;
break;
break;
}
if (sym[4] == "destSkip")
{
console.log("Dest skip start : [" + sym[0] + "]");
_curState++;
}
return '';
}
@@ -456,6 +489,7 @@ var kRgsymRtf = {
if (kRgsymRtf[keyword] !== undefined)
{
var sym = kRgsymRtf[keyword];
switch (sym[3])
{
case kRTFParserType_prop:
@@ -464,17 +498,21 @@ var kRgsymRtf = {
param = sym[1];
}
return [self _applyPropChange:sym parameter:param];
case kRTFParserType_char:
return [self _checkChar:sym parameter:param];
case kRTFParserType_dest:
return [self _changeDest:sym];
case kRTFParserType_spec:
return [self _parseSpec:sym parameter:param];
default:
return '';
break;
}
} else
}
else
{
switch (keyword)
{
@@ -482,50 +520,66 @@ var kRgsymRtf = {
var oldColor = [_colorArray lastObject],
green = [oldColor greenComponent],
blue = [oldColor blueComponent];
_colorArray.pop();
_colorArray.push([CPColor colorWithRed: parseInt(param) / 255 green:green blue:blue alpha:1.0]);
break;
break;
case "green":
var oldColor = [_colorArray lastObject],
red = [oldColor redComponent],
blue = [oldColor blueComponent];
_colorArray.pop();
_colorArray.push([CPColor colorWithRed: red green: parseInt(param) / 255 blue:blue alpha:1.0]);
break;
break;
case "blue":
var oldColor = [_colorArray lastObject],
green = [oldColor greenComponent],
red = [oldColor redComponent];
_colorArray.pop();
_colorArray.push([CPColor colorWithRed: red green:green blue:parseInt(param) / 255 alpha:1.0]);
break;
break;
case "cf": // change foreground color
var fontIndex = parseInt(param) - 1;
if (_currentRun && fontIndex >= 0)
_currentRun.fgColour = _colorArray[fontIndex];
break;
break;
case "f": // change font
var fontIndex = parseInt(param);
if (_currentRun && fontIndex >= 0 && fontIndex < _fontArray.length)
_currentRun.fontName = _fontArray[fontIndex];
break;
break;
case "fs": // change font size
_currentRun.fontSize = parseInt(param) / 2;
break;
break;
case "tx": // tabstop
var location = parseInt(param) / 20;
if (_currentRun)
{
[_currentRun addTab:location type:CPLeftTabStopType];
}
break;
break;
default:
console.log("skip : " + keyword + " param: " + param);
}
if (_states.length > 0)
_curState = 1;
return '';
}
}
@@ -537,16 +591,16 @@ var kRgsymRtf = {
fNeg = false,
keyword = '',
param = '';
_rtf = rtf;
if (++_currentParseIndex >= len)
return len;
ch = rtf.charAt(_currentParseIndex);
if (!/[a-zA-Z]/.test(ch))
{
return [self _translateKeyword:ch parameter:nil fParameter:fParam];
}
while (/[a-zA-Z]/.test(ch))
{
@@ -559,6 +613,7 @@ var kRgsymRtf = {
fNeg = true;
ch = rtf.charAt(++_currentParseIndex);
}
fParam = true;
while (/[0-9]/.test(ch))
@@ -566,6 +621,7 @@ var kRgsymRtf = {
param += (ch + '');
ch = rtf.charAt(++_currentParseIndex);
}
_currentParseIndex--;
param = parseInt(param);
@@ -574,6 +630,7 @@ var kRgsymRtf = {
return [self _translateKeyword:keyword parameter:param fParameter:fParam];
}
- (void)_appendPlainString:(CPString) aString
{
[_result replaceCharactersInRange:CPMakeRange([_result length], 0) withString:aString];
@@ -587,6 +644,7 @@ var kRgsymRtf = {
return '';
}
_currentParseIndex = -1;
var len = rtf.length,
tmp = '',
ch = '',
@@ -602,6 +660,7 @@ var kRgsymRtf = {
[self _appendPlainString: String.fromCharCode(parseInt((hex), 16))];
hex = '';
}
switch (tmp)
{
case " ":
@@ -613,17 +672,18 @@ var kRgsymRtf = {
_freename += tmp;
[self _appendPlainString:tmp];
}
break;
break;
case "{":
if ([self pushState])
{
console.log("push");
}
break;
break;
case "}":
if ([self popState])
{
console.log("pop");
}
if (_freename)
@@ -637,17 +697,17 @@ var kRgsymRtf = {
_freename = "";
}
[self _flushCurrentRun]
break;
break;
case "\\":
_freename = '';
ch = [self _parseKeyword:rtf length:len];
if (!_hexreturn && ch.length == 0)
{
lastchar = 1;
} else
{
else
lastchar = 0;
}
if (_hexreturn)
{
if (ch.length > 0)
@@ -655,7 +715,8 @@ var kRgsymRtf = {
if (parseInt(ch, 16) & 0x80)
{
hex += ch.toUpperCase();
} else
}
else
{
[self _appendPlainString: String.fromCharCode(parseInt((hex + ch), 16))];
hex = '';
@@ -664,42 +725,49 @@ var kRgsymRtf = {
if (hex.length == 4)
{
var temp = parseInt(hex, 16);
if (hexTable && hexTable[hex.toUpperCase()] !== undefined)
{
temp = parseInt(hexTable[hex.toUpperCase()], 16);
}
[self _appendPlainString: String.fromCharCode(temp)]
hex = '';
}
} else
}
else
{
console.log("hex skipped");
}
_hexreturn = NO;
} else
if (ch !== undefined && _curState === 0)
{
[self _appendPlainString:ch];
}
break;
_hexreturn = NO;
}
else if (ch !== undefined && _curState === 0)
{
[self _appendPlainString:ch];
}
break;
case 0x0d:
case 0x0a:
case '\n':
case '\r':
break;
break;
default:
lastchar = 0;
if (_curState == 0)
{
[self _appendPlainString:tmp];
} else if (tmp !== ';')
{
else if (tmp !== ';')
_freename += tmp;
}
break;
break;
}
}
return _result;
}
+70 -41
View File
@@ -1,12 +1,12 @@
/*
RTFProducer.j
Serialize CPAttributedString to a RTF String
Serialize CPAttributedString to a RTF String
Copyright (C) 2014 Daniel Boehringer
This file is based on the RTFProducer from GNUStep
(which i co-authored with Fred Kiefer in 1999)
* 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
@@ -20,15 +20,23 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
*/
@import <Foundation/CPAttributedString.j>
@import "CPParagraphStyle.j"
@import "CPColor.j"
@import "CPGraphics.j"
@import "CPText.j"
@import "CPFontManager.j"
@global CPFontAttributeName
@global CPForegroundColorAttributeName
@global CPBackgroundColorAttributeName
@global CPUnderlineStyleAttributeName
@global CPSuperscriptAttributeName
@global CPBaselineOffsetAttributeName
@global CPAttachmentAttributeName
@global CPLigatureAttributeName
@global CPKernAttributeName
var PAPERSIZE = @"PaperSize",
LEFTMARGIN = @"LeftMargin",
@@ -95,8 +103,8 @@ function _points2twips(a) { return (a) * 20.0; }
keyArray = [fontDict allKeys];
keyArray = [keyArray sortedArrayUsingSelector:@selector(compare:)];
fontEnum = [keyArray objectEnumerator];
while ((currFont = [fontEnum nextObject]) !== nil)
{
var fontFamily,
@@ -118,6 +126,7 @@ function _points2twips(a) { return (a) * 20.0; }
[fontDict objectForKey:currFont], fontFamily, currFont];
fontlistString += detail;
}
return [CPString stringWithFormat:@"{\\fonttbl%@}\n", fontlistString];
}
else
@@ -139,14 +148,17 @@ function _points2twips(a) { return (a) * 20.0; }
while ((next = [keyEnum nextObject]) != nil)
{
var cn = [colorDict objectForKey:next];
[list insertObject:next atIndex:[cn intValue] - 1];
}
result = [CPString stringWithString:@"{\\colortbl;"];
for (i = 0; i < count; i++)
{
var color = [[list objectAtIndex:i]
colorUsingColorSpaceName:CPCalibratedRGBColorSpace];
result += [CPString stringWithFormat:
@"\\red%d\\green%d\\blue%d;",
([color redComponent] * 255),
@@ -155,6 +167,7 @@ function _points2twips(a) { return (a) * 20.0; }
}
result += @"}\n";
return result;
}
else
@@ -173,45 +186,55 @@ function _points2twips(a) { return (a) * 20.0; }
result = [CPString string];
val = [docDict objectForKey:PAPERSIZE];
if (val != nil)
{
var size = [val sizeValue];
detail = [CPString stringWithFormat:@"\\paperw%d \\paperh%d",
_points2twips(size.width),
_points2twips(size.height)];
result += detail;
}
num = [docDict objectForKey:LEFTMARGIN];
if (num != nil)
{
var f = [num floatValue];
detail = [CPString stringWithFormat:@"\\margl%d",
_points2twips(f)];
detail = [CPString stringWithFormat:@"\\margl%d", _points2twips(f)];
result+= detail;
}
num = [docDict objectForKey:RIGHTMARGIN];
if (num != nil)
{
var f = [num floatValue];
detail = [CPString stringWithFormat:@"\\margr%d",
_points2twips(f)];
detail = [CPString stringWithFormat:@"\\margr%d", _points2twips(f)];
result += detail;
}
num = [docDict objectForKey:TOPMARGIN];
if (num != nil)
{
var f = [num floatValue];
detail = [CPString stringWithFormat:@"\\margt%d",
_points2twips(f)];
detail = [CPString stringWithFormat:@"\\margt%d", _points2twips(f)];
result += detail;
}
num = [docDict objectForKey:BUTTOMMARGIN];
if (num != nil)
{
var f = [num floatValue];
detail = [CPString stringWithFormat:@"\\margb%d",
_points2twips(f)];
detail = [CPString stringWithFormat:@"\\margb%d", _points2twips(f)];
result += detail;
}
@@ -263,9 +286,9 @@ function _points2twips(a) { return (a) * 20.0; }
{
cn = [colorDict count] + 1;
[colorDict setObject:[CPNumber numberWithInt:cn]
forKey:color];
[colorDict setObject:[CPNumber numberWithInt:cn] forKey:color];
}
var cn = [num intValue];
return cn + 1;
@@ -283,52 +306,56 @@ function _points2twips(a) { return (a) * 20.0; }
{
case CPRightTextAlignment:
headerString += @"\\qr";
break;
break;
case CPCenterTextAlignment:
headerString += @"\\qc";
break;
break;
case CPLeftTextAlignment:
headerString += @"\\ql";
break;
break;
case CPJustifiedTextAlignment:
headerString += @"\\qj";
break;
break;
default:
headerString += @"\\ql";
break;
break;
}
// write first line indent and left indent
var twips = _points2twips([paraStyle firstLineHeadIndent]);
if (twips != 0.0)
{
headerString += [CPString stringWithFormat:@"\\fi%d", twips];
}
twips = _points2twips([paraStyle headIndent]);
if (twips != 0.0)
{
headerString += [CPString stringWithFormat:@"\\li%d", twips];
}
twips = _points2twips([paraStyle tailIndent]);
if (twips != 0.0)
{
headerString += [CPString stringWithFormat:@"\\ri%d", twips];
}
twips = _points2twips([paraStyle paragraphSpacing]);
if (twips != 0.0)
{
headerString += [CPString stringWithFormat:@"\\sa%d", twips];
}
twips = _points2twips([paraStyle minimumLineHeight]);
if (twips != 0.0)
{
headerString += [CPString stringWithFormat:@"\\sl%d", twips];
}
twips = _points2twips([paraStyle maximumLineHeight]);
if (twips != 0.0)
{
headerString += [CPString stringWithFormat:@"\\sl-%d", twips];
}
// tabs
if (1)
{
@@ -383,11 +410,12 @@ function _points2twips(a) { return (a) * 20.0; }
* analyze attributes of current run
*
* FIXME: All the character attributes should be output relative to the font
* attributes of the paragraph. So if the paragraph has underline on it should
* still be possible to switch it off for some characters, which currently is
* attributes of the paragraph. So if the paragraph has underline on it should
* still be possible to switch it off for some characters, which currently is
* not possible.
*/
attribEnum = [attributes keyEnumerator];
while ((currAttrib = [attribEnum nextObject]) != nil)
{
if ([currAttrib isEqualToString:CPFontAttributeName])
@@ -406,16 +434,14 @@ function _points2twips(a) { return (a) * 20.0; }
/*
* font name
*/
if (currentFont == nil ||
![fontName isEqualToString:[currentFont familyName]])
if (currentFont == nil || ![fontName isEqualToString:[currentFont familyName]])
{
headerString += [self fontToken:fontName];
}
/*
* font size
*/
if (currentFont == nil ||
[font size] != [currentFont size])
if (currentFont == nil || [font size] != [currentFont size])
{
var points = [font size] * 2,
pString;
@@ -443,6 +469,7 @@ function _points2twips(a) { return (a) * 20.0; }
else if ([currAttrib isEqualToString:CPForegroundColorAttributeName])
{
var color = [attributes objectForKey:CPForegroundColorAttributeName];
if (![color isEqual:fgColor])
{
headerString += [CPString stringWithFormat:@"\\cf%d", [self numberForColor:color]];
@@ -452,6 +479,7 @@ function _points2twips(a) { return (a) * 20.0; }
else if ([currAttrib isEqualToString:CPBackgroundColorAttributeName])
{
var color = [attributes objectForKey:CPBackgroundColorAttributeName];
if (![color isEqual:bgColor])
{
headerString += [CPString stringWithFormat:@"\\cb%d", [self numberForColor:color]];
@@ -545,9 +573,8 @@ function _points2twips(a) { return (a) * 20.0; }
var string = [text string],
result = "",
loc = 0,
length = [string length];
var currRange = CPMakeRange(loc, 0),
length = [string length],
currRange = CPMakeRange(loc, 0),
completeRange = CPMakeRange(0, length),
first = YES;
@@ -566,9 +593,11 @@ function _points2twips(a) { return (a) * 20.0; }
runString = [self runStringForString:substring
attributes:attributes
paragraphStart:YES];
result += runString;
first = NO;
}
return result;
}