Thread: [Pyobjc-dev] problem saving as rtfd
Brought to you by:
ronaldoussoren
From: chris <por...@ya...> - 2003-05-12 03:46:37
|
Hello all, First of all I'd like to thank you for such a great tool. Now on to my problem I'm having a problem saving a file as rtfd. everything goes fine but when I open the result in TextEdit it is unformatted, the formatting information being clearly visible as if it where part of the text. Does anyone know what's going on here? Thank you in advance. Chris file infomation set in targets: Name: rtfd Role: Editor OS Type: rtfd extensions: rtfd signature: rtfd the saving function: def dataRepresentationOfType_(self, aType): # return an NSData containing the document's data represented as # the type identified by aType. passphrase = self.keyString.string() cypherChoise = self.cypherOptions.titleOfSelectedItem() plaintext = "" cyphertext = NSData.alloc() #if the plaintext was manually encrypted then it needs no further encryption #in fact further encryption could be harmful if self.encrypted == NO and self.saveSwitch.state() == 1: #edited out as this code isn't running #at this time. else: length = len(self.text.string()) cyphertext.initWithBytes_length(self.text.RTFDFromRange_((0,length)),length) #output the cyphertext to a file return cyphertext sample output for bold "hello world" copied from TextEdit: rtfd __________________________________ Do you Yahoo!? The New Yahoo! Search - Faster. Easier. Bingo. http://search.yahoo.com |
From: Marcel W. <ma...@me...> - 2003-05-12 06:43:53
|
> plaintext = "" > cyphertext = NSData.alloc() Minor nit: you shouldn't really have a partly initialized instance flying around. > #if the plaintext was manually encrypted then > it needs no further encryption > #in fact further encryption could be harmful > if self.encrypted == NO and > self.saveSwitch.state() == 1: > #edited out as this code isn't running > #at this time. > else: > length = len(self.text.string()) > > cyphertext.initWithBytes_length(self.text.RTFDFromRange_((0,length)),le > ngth) That's the problem right here: 1. RTFDFromRange already returns an NSData, and what you are doing is initializing a second NSData object with the pointer of the NSData *object*. 2. RTFDFromRange is "an RTFD stream corresponding to the characters and attributes within aRange". This is a pasteboard representation an not something you can directly/usefully save as a file. So, what you need is -RTFDFileWrapperFromRange:documentAttributes: , which returns a file-wrapper object that you can save. More can be found in the fine documentation: NSAttributedString class reference + some concept docs "RTF Files and Attributed Strings", referenced from the NSAttributedString class reference. Marcel -- Marcel Weiher Metaobject Software Technologies ma...@me... www.metaobject.com Metaprogramming for the Graphic Arts. HOM, IDEAs, MetaAd etc. |
From: chris <por...@ya...> - 2003-05-12 09:06:44
|
Now I am getting this on the console and a complete app crash: *** -[NSFileWrapper writeToFile:atomically:]: selector not recognized Traceback (most recent call last): File "/Users/c/SecretText/build/SecretText.app/Contents/Resources/__main__.py", line 20, in ? sys.exit(AppKit.NSApplicationMain(sys.argv)) ValueError: NSInvalidArgumentException - *** -[NSFileWrapper writeToFile:atomically:]: selector not recognized Stepping through the code in the terminal the NSFileWrapper comes back fine but it looks like it has "writeToFile_atomically_updateFilenames_" rather than "writeToFile_atomically_" hence the collapse. This is the current code: else: length = len(self.text.string()) store = self.text.textStorage() cyphertext = store.RTFDFileWrapperFromRange_documentAttributes_((0,length),None) #output the cyphertext to a file return cyphertext Chris --- Marcel Weiher <ma...@me...> wrote: > > > plaintext = "" > > cyphertext = NSData.alloc() > > Minor nit: you shouldn't really have a partly > initialized instance > flying around. > > > #if the plaintext was manually encrypted > then > > it needs no further encryption > > #in fact further encryption could be > harmful > > if self.encrypted == NO and > > self.saveSwitch.state() == 1: > > #edited out as this code isn't running > > #at this time. > > else: > > length = len(self.text.string()) > > > > > cyphertext.initWithBytes_length(self.text.RTFDFromRange_((0,length)),le > > > ngth) > > That's the problem right here: > > > 1. RTFDFromRange already returns an NSData, and what > you are doing is > initializing a second NSData object with the pointer > of the NSData > *object*. > > 2. RTFDFromRange is "an RTFD stream corresponding to > the characters and > attributes within aRange". This is a pasteboard > representation an not > something you can directly/usefully save as a file. > > > So, what you need is > -RTFDFileWrapperFromRange:documentAttributes: , > which returns a file-wrapper object that you can > save. > > More can be found in the fine documentation: > NSAttributedString > class reference + some concept docs "RTF Files and > Attributed Strings", > referenced from the NSAttributedString class > reference. > > Marcel > > -- > Marcel Weiher Metaobject Software Technologies > ma...@me... www.metaobject.com > Metaprogramming for the Graphic Arts. HOM, IDEAs, > MetaAd etc. > __________________________________ Do you Yahoo!? The New Yahoo! Search - Faster. Easier. Bingo. http://search.yahoo.com |
From: Marcel W. <ma...@me...> - 2003-05-12 09:17:54
|
On Monday, May 12, 2003, at 11:06 Uhr, chris wrote: > > "writeToFile_atomically_updateFilenames_" > rather than > "writeToFile_atomically_" > > hence the collapse. This is the current code: Yes. The NSFileWrapper is not an NSData, so you need to use a different method. What happens when you use the different method? Marcel -- Marcel Weiher Metaobject Software Technologies ma...@me... www.metaobject.com Metaprogramming for the Graphic Arts. HOM, IDEAs, MetaAd etc. |
From: Ronald O. <ous...@ci...> - 2003-05-12 17:52:26
|
On Monday, May 12, 2003, at 08:43 Europe/Amsterdam, Marcel Weiher wrote: > >> plaintext = "" >> cyphertext = NSData.alloc() > > Minor nit: you shouldn't really have a partly initialized instance > flying around. This is *not* a minor issue. Some Cocoa classes will cause crashes if you do anything with them before calling init, and that includes releasing them. PyObjC tries to protect you from this, but this is still bad form. > >> #if the plaintext was manually encrypted then >> it needs no further encryption >> #in fact further encryption could be harmful >> if self.encrypted == NO and >> self.saveSwitch.state() == 1: >> #edited out as this code isn't running >> #at this time. >> else: >> length = len(self.text.string()) >> >> cyphertext.initWithBytes_length(self.text.RTFDFromRange_((0,length)),l >> ength) > > That's the problem right here: > > > 1. RTFDFromRange already returns an NSData, and what you are doing is > initializing a second NSData object with the pointer of the NSData > *object*. > > 2. RTFDFromRange is "an RTFD stream corresponding to the characters > and attributes within aRange". This is a pasteboard representation an > not something you can directly/usefully save as a file. 3. you ignore the result of an initializer. You should always use the value returned by the initalizer and no longer use the value returned by alloc. Ronald |
From: Marcel W. <ma...@me...> - 2003-05-12 21:21:20
|
On Monday, May 12, 2003, at 07:51 Uhr, Ronald Oussoren wrote: > > On Monday, May 12, 2003, at 08:43 Europe/Amsterdam, Marcel Weiher > wrote: > >> >>> plaintext = "" >>> cyphertext = NSData.alloc() >> >> Minor nit: you shouldn't really have a partly initialized instance >> flying around. > > This is *not* a minor issue. Some Cocoa classes will cause crashes if > you do anything with them before calling init, and that includes > releasing them. PyObjC tries to protect you from this, but this is > still bad form. Yes, actually doing anything with the object other than sending some sort of init message *would* be bad. However, the original poster didn't do that, and for the object in question, it actually makes no difference whatsoever, since only the sequencing matters (unless the code is seriously messed up). It cannot tell what if anything happened between the alloc and the init. It can be the very next thing, it can be a million years later. id object = [[NSObject alloc] init]; and id obj = [NSObject alloc]; sleep( 365 * 24 * 3600 ); obj=[obj init]; are completely equivalent as far as the object is concerned. Of course, the latter is definitely odd looking, and there is no good reason for not initializing it immediately, whereas there are very good reasons *for* doing the initialization immediately, which is why I did bring it up. Of course, with a bridge involved, you may have to be more careful because the bridge might have reasons for touching the object that aren't obvious from the code. Marcel -- Marcel Weiher Metaobject Software Technologies ma...@me... www.metaobject.com Metaprogramming for the Graphic Arts. HOM, IDEAs, MetaAd etc. |