home *** CD-ROM | disk | FTP | other *** search
- //
- // MiscStringNEXTSTEP.m
- // Written by Don Yacktman Copyright (c) 1993 by Don Yacktman.
- // Version 1.95 All rights reserved.
- // This notice may not be removed from this source code.
- //
- // This object is included in the MiscKit by permission from the author
- // and its use is governed by the MiscKit license, found in the file
- // "LICENSE.rtf" in the MiscKit distribution. Please refer to that file
- // for a list of all applicable permissions and restrictions.
- //
-
- #import <misckit/MiscString.h>
- #import <mach/mach_error.h>
-
- @implementation MiscString(NEXTSTEP)
-
- // This category includes methods to support various NEXTSTEP features,
- // such as InterfaceBuilder (palettes), Distributed Objects (NXTransport),
- // and object archiving.
-
- - read:(NXTypedStream *)stream
- {
- int tempLength; char *tBuf;
- [super read:stream];
-
- // find out how much space we will need
- NXReadType(stream, "i", &tempLength);
-
- // note that -allocateBuffer:fromZone: will set _length for
- // us -- it is important to not smash _length since it tracks
- // the actual size of the current buffer! (See the notes for
- // -allocateBuffer:fromZone: for more info on why no smashing.)
- // Note that -allocateBuffer:fromZone: increments the buffer
- // size by one, so we must pass it decremented so that we unarchive
- // with a buffer of the same length as the original object.
- [self allocateBuffer:(tempLength-1) fromZone:[self zone]]; // make sure
- // we have a buffer and it is big enough.
-
- // Get the string off the stream and into the buffer
- NXReadType(stream, "*", &tBuf);
- if (tBuf) strcpy(buffer, tBuf);
- if (!tBuf && buffer) buffer[0] = '\0'; // NULL string?
-
- // now make sure that we have the right length for the string stored.
- if (buffer) length = strlen(buffer);
- else length = 0;
-
- // clean up and blow this joint
- if (tBuf) free(tBuf);
- return self;
- }
-
- - write:(NXTypedStream *)stream
- {
- [super write:stream];
- // put the string and it's length on the stream. The length is sort
- // of redundant, but this assures that the string really is like the
- // one that was archived -- if the stored instance had an oversize
- // buffer, then read will restore an oversize buffer. Of course,
- // crud after the string won't be the same, so the new instance isn't
- // quite the same, but...
- NXWriteType(stream, "i", &_length);
- NXWriteType(stream, "*", &buffer);
- return self;
- }
-
- // NXTransport protocol implementation (next three methods):
- - encodeUsing:(id <NXEncoding>)portal
- {
- [portal encodeData:&_length ofType:"i"]; // no longer used, remains for compatability reasons
- [portal encodeData:&length ofType:"i"];
- [portal encodeData:&buffer ofType:"*"];
- return self;
- }
-
- - decodeUsing:(id <NXDecoding>)portal
- {
- int newLen;
- [self freeString];
- [portal decodeData:&newLen ofType:"i"]; // no longer used, remains for compatability reasons
- // This is not necessary and causes a leak: [self allocateBuffer:newLen];
- [portal decodeData:&length ofType:"i"];
- [portal decodeData:&buffer ofType:"*"];
- // Yes, I know I'm not supposed to fool with _length, but....
- _length = length + 1; // it needs to be set properly and this ought to
- // do the trick. Note that the bycopy object doesn't necessarily have
- // a buffer as large as the original. We don't really care since they
- // grow dynamically anyway and most strings passed through DO will end
- // up being treated as constants anyway, so the trimming down is OK.
- return self;
- }
-
- - encodeRemotelyFor:(NXConnection *)connection
- freeAfterEncoding:(BOOL *)flagp isBycopy:(BOOL)isByCopy
- {
- if (isByCopy) {
- *flagp = NO; // object will not be freed (ie, copy, not move)
- return self; //encode object (copy it)
- }
- *flagp = NO;
- // super will encode the proxy otherwise
- return [super encodeRemotelyFor:connection
- freeAfterEncoding:flagp isBycopy:isByCopy];
- }
-
- // RTF support
- - (BOOL)isRTFText
- {
- if (![self cmp:"{\\rtf0" n:6]) return YES; //} rtf header/magic num
- if (![self cmp:"{\\\\rtf0" n:7]) return YES; //} happens in .address files
- return NO;
- }
-
- - (MiscString *)plainTextForRTF
- { // Donated by Darcy Brockbank and untested. Let's hope it works!
- id text = [[Text alloc] init];
- // text may have to go into a dummy window, or we could
- // make a major hack and ask for the [[NXApp mainMenu] getFieldEditor...
- vm_size_t allocSize = (strlen(buffer)+1) * sizeof(char);
- char * tmp;
- NXStream * stream;
- MiscString * other = nil;
- kern_return_t ret;
-
- if (![self isRTFText]) return [self copy];
- [text setText:""];
- ret = (vm_allocate(task_self(), (vm_address_t *)&tmp, allocSize, TRUE));
- if (ret != KERN_SUCCESS) {
- mach_error("vm_allocate returned value of ", ret);
- printf("Exiting with error.\n");
- exit(-1);
- }
- strcpy(tmp,buffer);
- stream = NXOpenMemory(tmp,allocSize,NX_READONLY);
- [text readRichText:stream];
- NXCloseMemory(stream,NX_TRUNCATEBUFFER);
- ret = vm_deallocate(task_self(), (vm_address_t)tmp, allocSize);
- if (ret != KERN_SUCCESS) {
- mach_error("vm_deallocate returned value of ",ret);
- printf("Exiting with error.\n");
- exit(-1);
- }
- if ([text textLength]) {
- int len = [text textLength];
- char otherBuf[len + 1];
- [text getSubstring:otherBuf start:0 length:len];
- otherBuf[len]='\0';
- other = [[MiscString alloc] initString:otherBuf];
- }
- [text free];
- return other; // nil if we were unsuccessful
- }
-
- // Interface Builder support
- - (const char *)getInspectorClassName { return "MiscStringInspector"; }
- - (NXImage *)getIBImage { return [NXImage findImageNamed:"MiscStringObj"]; }
-
- - writeToStream:(NXStream *)aStream
- {
- NXPrintf(aStream,"%s", [self stringValue]);
- return self;
- }
-
- @end
-