Cocoa: pasting formatted text in the current font?
When I put formatted text into the pasteboard (NSRTFPboardType), it pastes with all formatting preserved. But what I'd really like is to discard the font face and size information, while preserving the weight, color, etc.
According to the docs, an NSAttributedString with no font information will default to Helvetica 12, so that seems like a dead end.
I can also generate the text on demand, so if I could find out the font in the current UI element, I could modify the text before it goes into the pasteboard. I was hoping the accessibility API could help with this, but none o开发者_StackOverflow中文版f the attributes I can find in the UIElementInspector seem to deal with formatting.
Any ideas?
Here's a test case. It pastes in Helvetica 12 even though the only attribute is a green color:
// Create the string with no attributes, and strip the font just in case.
NSMutableAttributedString *s = [[[NSMutableAttributedString alloc] initWithString:@"Hello green world!"] autorelease];
[s removeAttribute:NSFontAttributeName range:NSMakeRange(0, [s length])];
// Add a test attribute
[s addAttribute:NSForegroundColorAttributeName value:[NSColor greenColor] range:NSMakeRange(6, 5)];
// Generate RTF data
NSData *rtf = [s RTFFromRange:NSMakeRange(0, [s length]) documentAttributes:nil];
// Copy to pasteboard
NSPasteboard *pb = [NSPasteboard generalPasteboard];
[pb declareTypes:[NSArray arrayWithObject:NSRTFPboardType] owner:nil];
[pb setData:rtf forType:NSRTFPboardType];
Here's something interesting. If I try and generate the plainest raw RTF data I can, with absolutely no font information, it still pastes in Helvetica 12!
char *rawrtf = "{\\rtf1\\ansi\\ansicpg1252\n"
"Hello world.}";
NSData *rtf = [NSData dataWithBytes:rawrtf length:strlen(rawrtf)];
So if this is possible at all, I think it's only possible by querying the currently running application about the current font.
There is no system-wide or even application-wide notion of the "current font". The closest you can get is the typing attributes of a currently active NSTextView
; if none is active, then there is nothing like a current font.
With that said, you could promise the RTF data to the pasteboard, and when it requests it, send the currently active application a copy AppleEvent command, wait for a response, pull any rich text off the pasteboard, and grab its font attributes. If no rich text is available, stick with your current font and size. I have no idea how well this heuristic works in practice, but I can't think of any better approach.
If I try and generate the plainest raw RTF data I can, with absolutely no font information, it still pastes in Helvetica 12!
The font defaults to Helvetica-12 when no font information is supplied because all text being drawn has to be in some font at some size. Helvetica-12 must have seemed as readable and sufficiently inoffensive to be chosen as the default. (Sure beats Comic Sans-72!)
NSAttributedString is immutable. I think perhaps what you need is an NSMutableAttributedString. This guide has an example of how to change things. You should be able to create a new NSMutableAttributedString as a copy of the NSAttributedString, and then make your modifications to it before passing it on to the pasteboard.
EDIT:
I'm not quite sure of what you what to do. You are saying that you want to preserve some formatting, and remove other formatting, and it seems like you understand how to manipulate the NSMutableAttributedString attributes, so what's the problem? Create a new attributed string, interrogate the old one, and apply whatever attributes you want to the new one, if you don't like the default font, change it. I'm not understanding where the problem is in this.
EDIT2:
Using initWithAttributedString:
should copy the font properties over, but if it doesn't you should be able to use enumerateAttributesInRange:options:usingBlock:
to interrogate your original NSAttributedString
EDIT3:
NSAttributedString *attrStr;
NSRange limitRange;
NSRange effectiveRange;
id attributeValue;
limitRange = NSMakeRange(0, [attrStr length]);
while (limitRange.length > 0) {
attributeValue = [attrStr attribute:NSFontAttributeName
atIndex:limitRange.location longestEffectiveRange:&effectiveRange
inRange:limitRange];
// apply attributeValue to the other mutable attributed string range here
limitRange = NSMakeRange(NSMaxRange(effectiveRange),
NSMaxRange(limitRange) - NSMaxRange(effectiveRange));
}
changing copied text so it'll be different from what the user had copied would go against the idea of copy and paste, no?
精彩评论