Extend LSTB/LSTE to also handle LSTZ-style zero-terminated lists.

This commit is contained in:
Uli Kusterer 2003-08-17 00:48:19 +02:00
parent eb2527cf0f
commit 04e81cb47d
9 changed files with 90 additions and 14 deletions

View File

@ -2,6 +2,8 @@
// NuTemplateLSTBElement.h
// ResKnife (PB2)
//
// Implements LSTB and LSTZ fields.
//
// Created by Uli Kusterer on Tue Aug 05 2003.
// Copyright (c) 2003 M. Uli Kusterer. All rights reserved.
//

View File

@ -2,6 +2,8 @@
// NuTemplateLSTBElement.m
// ResKnife (PB2)
//
// Implements LSTB and LSTZ fields.
//
// Created by Uli Kusterer on Tue Aug 05 2003.
// Copyright (c) 2003 M. Uli Kusterer. All rights reserved.
//
@ -28,6 +30,8 @@
if( [[obj type] isEqualToString: @"LSTE"] )
{
endElement = [obj retain];
if( [type isEqualToString: @"LSTZ"] )
[endElement setWritesZeroByte:YES];
break;
}
[subElements addObject: obj];
@ -35,19 +39,38 @@
}
-(void) readDataFrom: (NuTemplateStream*)stream
-(void) readDataForElements: (NuTemplateStream*)stream
{
NSEnumerator *enny = [subElements objectEnumerator];
NuTemplateElement *el, *nextItem;
unsigned int bytesToGoAtStart = [stream bytesToGo];
NuTemplateElement *el;
/* Fill this first list element with data:
If there is no more data in the stream, the items will
fill themselves with default values. */
while( el = [enny nextObject] )
{
[el readDataFrom: stream];
}
}
-(void) readDataFrom: (NuTemplateStream*)stream
{
BOOL isZeroTerminated = [type isEqualToString: @"LSTZ"];
NSEnumerator *enny = [subElements objectEnumerator];
NuTemplateElement *el, *nextItem;
unsigned int bytesToGoAtStart = [stream bytesToGo];
char termByte = 0;
/* Fill this first list element with data:
If there is no more data in the stream, the items will
fill themselves with default values. */
if( isZeroTerminated )
{
termByte = 0;
[stream peekAmount:1 toBuffer:&termByte]; // "Peek" doesn't change the read offset.
if( termByte != 0 )
[self readDataForElements: stream];
}
else
[self readDataForElements: stream];
/* Read additional elements until we have enough items,
except if we're not the first item in our list. */
@ -55,6 +78,15 @@
{
while( [stream bytesToGo] > 0 )
{
if( isZeroTerminated ) // Is zero-terminated list? Check whether there is a termination byte.
{
termByte = 0;
[stream peekAmount:1 toBuffer:&termByte]; // "Peek" doesn't change the read offset.
if( termByte == 0 )
break; // No need to actually read the peeked byte, LSTE will do that.
}
// Actually read the item:
nextItem = [[self copy] autorelease]; // Make another list item just like this one.
[nextItem setContaining: nil]; // Make sure it doesn't get into this "if" clause.
[containing addObject: nextItem]; // Add it below ourselves.
@ -68,6 +100,7 @@
[containing addObject: tlee];
[tlee setContaining: containing];
[tlee setGroupElemTemplate: self];
[tlee readDataFrom: stream]; // If LSTE has data to read (e.g. if we're an LSTZ, the terminating byte), let it do that!
if( bytesToGoAtStart == 0 ) // It's an empty list. Delete this LSTB again, so we only have the empty LSTE.
{

View File

@ -13,10 +13,14 @@
@interface NuTemplateLSTEElement : NuTemplateGroupElement
{
NuTemplateGroupElement* groupElemTemplate; // The item of which we're to create a copy.
BOOL writesZeroByte; // Write a terminating zero-byte when writing out this item (used by LSTZ).
}
-(IBAction) showCreateResourceSheet: (id)sender;
-(void) setWritesZeroByte: (BOOL)n;
-(BOOL) writesZeroByte;
-(void) setGroupElemTemplate: (NuTemplateGroupElement*)e;
-(NuTemplateGroupElement*) groupElemTemplate;

View File

@ -40,12 +40,10 @@
-(void) readDataFrom: (NuTemplateStream*)stream
{
NSEnumerator* enny = [subElements objectEnumerator];
NuTemplateElement* el;
while( el = [enny nextObject] )
if( writesZeroByte )
{
[el readDataFrom: stream];
char termByte;
[stream readAmount:1 toBuffer: &termByte];
}
}
@ -53,12 +51,16 @@
// Doesn't write any sub-elements because this is simply a placeholder to allow for empty lists:
-(unsigned int) sizeOnDisk
{
return 0;
return writesZeroByte ? 1 : 0;
}
-(void) writeDataTo: (NuTemplateStream*)stream
{
if( writesZeroByte )
{
char fillByte = 0;
[stream writeAmount:sizeof(fillByte) fromBuffer: &fillByte];
}
}
@ -74,11 +76,23 @@
}
-(void) setWritesZeroByte: (BOOL)n
{
writesZeroByte = n;
}
-(BOOL) writesZeroByte
{
return writesZeroByte;
}
-(id) copyWithZone: (NSZone*)zone
{
NuTemplateLSTEElement* el = [super copyWithZone: zone];
[el setGroupElemTemplate: [self groupElemTemplate]];
[el setWritesZeroByte: [self writesZeroByte]];
return el;
}

View File

@ -31,6 +31,7 @@
-(NuTemplateElement*) readOneElement; // For parsing of 'TMPL' resource as template.
-(void) readAmount: (unsigned int)l toBuffer: (void*)buf; // For reading data from the resource.
-(void) peekAmount: (unsigned int)l toBuffer: (void*)buf; // For examining data w/o advancing the read/write mark.
-(void) writeAmount: (unsigned int)l fromBuffer: (void*)buf; // For writing data back to the resource.

View File

@ -108,6 +108,16 @@
}
-(void) peekAmount: (unsigned int)l toBuffer: (void*)buf
{
if( l > bytesToGo )
l = bytesToGo;
if( l > 0 )
memmove( buf, data, l );
}
-(void) writeAmount: (unsigned int)l fromBuffer: (void*)buf
{
if( l > bytesToGo )

View File

@ -53,6 +53,7 @@
-(IBAction) copy: (id)sender;
-(IBAction) paste: (id)sender;
-(IBAction) clear: (id)sender;
-(IBAction) saveDocument: (id)sender;
@end

View File

@ -193,6 +193,7 @@
if( [fieldReg count] == 0 )
{
[fieldReg setObject: [NuTemplateLSTBElement class] forKey: @"LSTB"];
[fieldReg setObject: [NuTemplateLSTBElement class] forKey: @"LSTZ"];
[fieldReg setObject: [NuTemplateLSTEElement class] forKey: @"LSTE"];
[fieldReg setObject: [NuTemplateTNAMElement class] forKey: @"TNAM"];
[fieldReg setObject: [NuTemplatePSTRElement class] forKey: @"PSTR"];
@ -328,6 +329,8 @@
return( [selElement validateMenuItem: item] );
else if( [item action] == @selector(clear:) )
return( selElement != nil && [selElement respondsToSelector: @selector(clear:)] );
else if( [item action] == @selector(saveDocument:) )
return YES;
else return NO;
}
@ -342,6 +345,12 @@
}
-(IBAction) saveDocument: (id)sender
{
[self writeResData];
}
-(BOOL) windowShouldClose: (id)sender // Window delegate.
{
[self writeResData]; // Save resource.

View File

@ -1,3 +1,5 @@
-> "Open as Hex" displays "(null)" as the document name. Why?
-> Changing the type/creator of a file isn't written to disk by ResourceDocument.
-> Create small versions of the doc icons in Photoshop instead of letting IconComposer use its cheap scaling on them.
-> Create small versions of the doc icons in Photoshop instead of letting IconComposer use its cheap scaling on them.
-> Auto-uncollapse list items in template editor when they are created and when a resource is opened.
-> Template editor should maintain "dirty" flag for resource.