#include "TemplateWindow.h" /*** CREATOR ***/ TemplateWindow::TemplateWindow( WindowRef newWindow ) { // clear all instance bytes BlockZero( this, sizeof(TemplateWindow) ); // set the window to the one just created window = newWindow; } /*** DESTRUCTOR ***/ TemplateWindow::~TemplateWindow( void ) { ReadControls(); } /*** USE TEMPLATE ***/ OSStatus TemplateWindow::UseTemplate( Handle newTmpl ) { tmpl = newTmpl; return noErr; } /*** PARSE DATA ***/ OSStatus TemplateWindow::ParseData( Handle data ) { #pragma unused( data ) OSStatus error = noErr; error = ParseTemplate(); error = CreateControls(); return error; } /*** PARSE TEMPLATE ***/ OSStatus TemplateWindow::ParseTemplate( void ) { SInt32 size = GetHandleSize( tmpl ); SInt8 state = HGetState( tmpl ); HLock( tmpl ); ElementPtr current = elements = new Element; elementCount++; unsigned long position = 0; // start parsing at offset zero (unsurprisingly) while( position < size ) { // fill in element data short labelSize = *(*tmpl + position); BlockMoveData( *tmpl + position, ¤t->label, labelSize +1 ); position += labelSize +1; // don't forget length byte! BlockMoveData( *tmpl + position, ¤t->type, sizeof(ResType) ); position += sizeof(ResType); // but restype is always 4 bytes :) // create new element if( position < size ) { elementCount++; current->next = new Element; current = current->next; } } // clean up HSetState( tmpl, state ); return noErr; } /*** CREATE CONTROLS ***/ OSStatus TemplateWindow::CreateControls( void ) { OSStatus error = noErr; ControlRef root, label, secondaryLabel, group, radio, checkbox, edit, listcount; CreateRootControl( window, &root ); Rect windowBounds, rect, secondaryLabelRect; GetWindowPortBounds( window, &windowBounds ); // get resource data (the really tedious way - I ought to make this easier) Plug_WindowRef plugWindow = Host_GetPlugWindowFromWindowRef( window ); if( plugWindow == null ) DebugStr("\pplugWindow == null"); Plug_ResourceRef resource = Host_GetTargetResource( plugWindow ); if( resource == null ) DebugStr("\presource == null"); Handle data = Host_GetResourceData( resource ); SInt32 size = GetHandleSize( data ); SInt8 state = HGetState( data ); HLock( data ); // set control font style ControlID id; ControlFontStyleRec fontStyle, rectLabelStyle; fontStyle.flags = kControlUseFontMask + kControlUseJustMask; fontStyle.font = kControlFontSmallSystemFont; fontStyle.just = teJustLeft; rectLabelStyle.flags = kControlUseFontMask + kControlUseJustMask; rectLabelStyle.font = kControlFontSmallSystemFont; rectLabelStyle.just = teJustRight; // set up bounds for first control bounds.top = bounds.bottom = windowBounds.top; // bounds.top is ignored, bounds.bottom is the bottom of the previous control bounds.left = windowBounds.left +110 + 8; // bounds.left and .right are the sides of the controls excluding the label bounds.right = windowBounds.right - 8; // declare variables CFStringRef text = null; signed long position = 0; // offset of data currently being processed unsigned char boolBit = 0; ElementPtr current = elements; ElementPtr recursionOrigin = null; // bug: only handles one level of recursion signed long recursionTotal = 0; unsigned long recursionIndex = 0, recursionCount = 0; unsigned long m = 0, n = 0; // counters, one is always unique, the other is an element index for( ; m < elementCount; m++ ) { n++; // advance unique counter // create controls switch( current->type ) { case 'BOOL': // BOOL is two bytes long, false == 0x0000, true == 0x0100 { Boolean valid = false; if( size > position ) valid = (Boolean) ((unsigned short) *(*data + position)) > 0; SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom + 2*16 +12 ); CreateRadioGroupControl( window, &rect, &group ); SetRect( &rect, rect.left, rect.top, rect.right, rect.top +16 ); error = CreateRadioButtonControl( window, &rect, CFSTR("False"), !valid, true, &radio ); // false is embedded at index zreo error = EmbedControl( radio, group ); OffsetRect( &rect, 0, 16 +4 ); error = CreateRadioButtonControl( window, &rect, CFSTR("True"), valid, true, &radio ); // true is embedded at index one error = EmbedControl( radio, group ); SetControlValue( group, valid +1 ); SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom + 2*16 +12 ); rect.bottom += 4; position += 2; // set control ID id.id = n; id.signature = kBooleanGroupSignature; SetControlID( group, &id ); } break; case 'BBIT': case 'FBIT': if( boolBit == 0 ) { // greate group box SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom + 20*8 +32 ); CreateGroupBoxControl( window, &rect, CFSTR("Some bits to click"), true, &group ); bounds.bottom += 24; // set control ID id.id = n; id.signature = kBooleanGroupSignature; SetControlID( group, &id ); } else { id.id = n - boolBit; id.signature = kBooleanGroupSignature; GetControlByID( window, &id, &group ); } // create checkbox { SInt32 content = 0x00000000; if( size > position && current->type == 'BBIT' ) content = ((*(char*)(*data + position) << boolBit) & 0x80)? 1:0; SetRect( &rect, bounds.left +8, bounds.bottom +4, bounds.right -8, bounds.bottom +20 ); text = CFStringCreateWithPascalString( CFAllocatorGetDefault(), current->label, kCFStringEncodingMacRoman ); CreateCheckBoxControl( window, &rect, text, content, true, &checkbox ); EmbedControl( checkbox, group ); // checkboxes are embedded from 0 to 7, in direct bit order if( current->type == 'FBIT' ) HiliteControl( checkbox, kControlDisabledPart ); // kControlInactivePart might work too // DisableControl( checkbox ); // DeactivateControl( checkbox ); // HideControl( checkbox ); // advance BBIT counter boolBit += 1; if( boolBit == 8 ) { boolBit = 0; position += 1; rect.bottom += 12; } } break; case 'DBYT': { Str255 number; SInt8 content = 0x00; if( size > position ) content = *((char*)(*data + position)); NumToString( (long) content, number ); text = CFStringCreateWithPascalString( CFAllocatorGetDefault(), number, kCFStringEncodingMacRoman ); SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom +22 ); CreateEditTextControl( window, &rect, text, false, true, &fontStyle, &edit ); rect.bottom += 4; position += 1; // set control ID id.id = n; id.signature = kEditFieldSignature; SetControlID( edit, &id ); } break; case 'DWRD': { Str255 number; SInt16 content = 0x0000; if( size > position +1 ) content = *((short*)(*data + position)); NumToString( (long) content, number ); text = CFStringCreateWithPascalString( CFAllocatorGetDefault(), number, kCFStringEncodingMacRoman ); SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom +22 ); CreateEditTextControl( window, &rect, text, false, true, &fontStyle, &edit ); rect.bottom += 4; position += 2; // set control ID id.id = n; id.signature = kEditFieldSignature; SetControlID( edit, &id ); } break; case 'DLNG': { Str255 number; SInt32 content = 0x00000000; if( size > position +3 ) content = *((long*)(*data + position)); NumToString( (long) content, number ); text = CFStringCreateWithPascalString( CFAllocatorGetDefault(), number, kCFStringEncodingMacRoman ); SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom +22 ); CreateEditTextControl( window, &rect, text, false, true, &fontStyle, &edit ); rect.bottom += 4; position += 4; // set control ID id.id = n; id.signature = kEditFieldSignature; SetControlID( edit, &id ); } break; case 'HBYT': { Str255 number; SInt8 content = 0x00; if( size > position ) content = *((char*)(*data + position)); NumToString( (long) content, number ); // convert to hex here text = CFStringCreateWithPascalString( CFAllocatorGetDefault(), number, kCFStringEncodingMacRoman ); SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom +22 ); CreateEditTextControl( window, &rect, text, false, true, &fontStyle, &edit ); rect.bottom += 4; position += 1; // set control ID id.id = n; id.signature = kEditFieldSignature; SetControlID( edit, &id ); // add dollar denoting hex SetRect( &secondaryLabelRect, bounds.left -24, bounds.bottom +9, bounds.left -6, bounds.bottom +22 ); CreateStaticTextControl( window, &secondaryLabelRect, CFSTR("$"), &rectLabelStyle, &secondaryLabel ); } break; case 'HWRD': { Str255 number; SInt16 content = 0x0000; if( size > position +1 ) content = *((short*)(*data + position)); NumToString( (long) content, number ); // convert to hex here text = CFStringCreateWithPascalString( CFAllocatorGetDefault(), number, kCFStringEncodingMacRoman ); SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom +21 ); CreateEditTextControl( window, &rect, text, false, true, &fontStyle, &edit ); rect.bottom += 4; position += 2; // set control ID id.id = n; id.signature = kEditFieldSignature; SetControlID( edit, &id ); // add dollar denoting hex SetRect( &secondaryLabelRect, bounds.left -24, bounds.bottom +9, bounds.left -6, bounds.bottom +22 ); CreateStaticTextControl( window, &secondaryLabelRect, CFSTR("$"), &rectLabelStyle, &secondaryLabel ); } break; case 'HLNG': { Str255 number; SInt32 content = 0x00000000; if( size > position +3 ) content = *((long*)(*data + position)); NumToString( (long) content, number ); // convert to hex here text = CFStringCreateWithPascalString( CFAllocatorGetDefault(), number, kCFStringEncodingMacRoman ); SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom +21 ); CreateEditTextControl( window, &rect, text, false, true, &fontStyle, &edit ); rect.bottom += 4; position += 4; // set control ID id.id = n; id.signature = kEditFieldSignature; SetControlID( edit, &id ); // add dollar denoting hex SetRect( &secondaryLabelRect, bounds.left -24, bounds.bottom +9, bounds.left -6, bounds.bottom +22 ); CreateStaticTextControl( window, &secondaryLabelRect, CFSTR("$"), &rectLabelStyle, &secondaryLabel ); } break; case 'FBYT': position += 1; break; case 'FWRD': position += 2; break; case 'FLNG': position += 4; break; case 'AWRD': position += position % 2; break; case 'ALNG': position += position % 4; break; case 'CHAR': // one byte { UInt8 content = 0x00; if( size > position ) content = *((unsigned char*)(*data + position)); text = CFStringCreateWithBytes( CFAllocatorGetDefault(), (unsigned char *) &content, 1, kCFStringEncodingMacRoman, false ); SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom +22 ); CreateEditTextControl( window, &rect, text, false, true, &fontStyle, &edit ); rect.bottom += 4; position += 1; // set control ID id.id = n; id.signature = kEditFieldSignature; SetControlID( edit, &id ); } break; case 'TNAM': // four bytes { UInt32 content = 0x00000000; if( size > position +3 ) content = *((unsigned long*)(*data + position)); text = CFStringCreateWithBytes( CFAllocatorGetDefault(), (unsigned char *) &content, 4, kCFStringEncodingMacRoman, false ); SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom +22 ); CreateEditTextControl( window, &rect, text, false, true, &fontStyle, &edit ); rect.bottom += 4; position += 4; // set control ID id.id = n; id.signature = kEditFieldSignature; SetControlID( edit, &id ); } break; case 'CSTR': // one to 32,768 bytes? { SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom +22 ); if( size > position ) // bug: if the bytes do not end in a 0x00, the function just keeps on reading! text = CFStringCreateWithCString( CFAllocatorGetDefault(), (char *) (*data + position), kCFStringEncodingMacRoman ); else text = CFSTR(""); CreateEditTextControl( window, &rect, text, false, true, &fontStyle, &edit ); position += CFStringGetLength(text) +1; rect.bottom += 4; // set control ID id.id = n; id.signature = kEditFieldSignature; SetControlID( edit, &id ); } break; case 'ECST': // one to 32,768 bytes? { SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom +22 ); if( size > position ) text = CFStringCreateWithCString( CFAllocatorGetDefault(), (char *) (*data + position), kCFStringEncodingMacRoman ); else text = CFSTR(""); CreateEditTextControl( window, &rect, text, false, true, &fontStyle, &edit ); position += CFStringGetLength(text) +1; // null byte position += (CFStringGetLength(text) % 2 == 0)? 1:0; // to pad or not to pad? rect.bottom += 4; // set control ID id.id = n; id.signature = kEditFieldSignature; SetControlID( edit, &id ); } break; case 'OCST': // one to 32,768 bytes? { SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom +22 ); if( size > position ) text = CFStringCreateWithCString( CFAllocatorGetDefault(), (char *) (*data + position), kCFStringEncodingMacRoman ); else text = CFSTR(""); CreateEditTextControl( window, &rect, text, false, true, &fontStyle, &edit ); position += CFStringGetLength(text) +1; // null byte position += (CFStringGetLength(text) % 2 == 1)? 1:0; // to pad or not to pad? rect.bottom += 4; // set control ID id.id = n; id.signature = kEditFieldSignature; SetControlID( edit, &id ); } break; case 'PSTR': // one to 256 bytes { unsigned char length = 0; if( size > position ) length = *(*data + position); SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom +22 ); if( size > position ) text = CFStringCreateWithPascalString( CFAllocatorGetDefault(), (unsigned char *) (*data + position), kCFStringEncodingMacRoman ); else text = CFSTR(""); CreateEditTextControl( window, &rect, text, false, true, &fontStyle, &edit ); position += length +1; rect.bottom += 4; // set control ID id.id = n; id.signature = kEditFieldSignature; SetControlID( edit, &id ); } break; case 'ESTR': // one to 256 bytes { unsigned char length = 0; if( size > position ) length = *(*data + position); SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom +22 ); if( size > position ) text = CFStringCreateWithPascalString( CFAllocatorGetDefault(), (unsigned char *) (*data + position), kCFStringEncodingMacRoman ); else text = CFSTR(""); CreateEditTextControl( window, &rect, text, false, true, &fontStyle, &edit ); position += length +1; position += (length % 2 == 0)? 1:0; rect.bottom += 4; // set control ID id.id = n; id.signature = kEditFieldSignature; SetControlID( edit, &id ); } break; case 'OSTR': // one to 256 bytes { unsigned char length = 0; if( size > position ) length = *(*data + position); SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom +22 ); if( size > position ) text = CFStringCreateWithPascalString( CFAllocatorGetDefault(), (unsigned char *) (*data + position), kCFStringEncodingMacRoman ); else text = CFSTR(""); CreateEditTextControl( window, &rect, text, false, true, &fontStyle, &edit ); position += length +1; position += (length % 2 == 1)? 1:0; rect.bottom += 4; // set control ID id.id = n; id.signature = kEditFieldSignature; SetControlID( edit, &id ); } break; case 'WSTR': // one to 65,536 bytes { unsigned short length = 0; if( size > position +1 ) BlockMoveData( *data + position, &length, 2 ); // length = *((unsigned short*) *data + position); SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom +22 ); if( size > position +1 ) text = CFStringCreateWithBytes( CFAllocatorGetDefault(), (unsigned char *) (*data + position +2), (CFIndex) length, kCFStringEncodingMacRoman, false ); else text = CFSTR(""); CreateEditTextControl( window, &rect, text, false, true, &fontStyle, &edit ); position += length +2; rect.bottom += 4; // set control ID id.id = n; id.signature = kEditFieldSignature; SetControlID( edit, &id ); } break; case 'LSTR': // one to 4,294,967,296 bytes { unsigned long length = 0; if( size > position +3 ) BlockMoveData( *data + position, &length, 4 ); // length = *((unsigned long*) *data + position); SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom +22 ); if( size > position +3 ) text = CFStringCreateWithBytes( CFAllocatorGetDefault(), (unsigned char *) (*data + position +4), (CFIndex) length, kCFStringEncodingMacRoman, false ); else text = CFSTR(""); CreateEditTextControl( window, &rect, text, false, true, &fontStyle, &edit ); position += length +4; rect.bottom += 4; // set control ID id.id = n; id.signature = kEditFieldSignature; SetControlID( edit, &id ); } break; case 'HEXD': // bug: should display in hex - wait until hex is implemented :-) // infinetly long (limited only by CFString) { SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom +22 ); if( size > position ) text = CFStringCreateWithBytes( CFAllocatorGetDefault(), (unsigned char *) (*data + position), size - position, kCFStringEncodingMacRoman, false ); else text = CFSTR(""); CreateEditTextControl( window, &rect, text, false, true, &fontStyle, &edit ); rect.bottom += 4; position = size; // bug: should ensure termination of parsing // set control ID id.id = n; id.signature = kHexDumpSignature; SetControlID( edit, &id ); } break; case 'RECT': // four SInt16s: top, left, bottom, right { // greate group box SInt16 menuID = 2001; // bug: make into a constant SInt16 titleWidth = 0; SInt16 titleJustification = teJustLeft; Style titleStyle = normal; SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom + 26*4 +40 ); error = CreatePopupGroupBoxControl( window, &rect, CFSTR("A Rectangle"), true, menuID, true, titleWidth, titleJustification, titleStyle, &group ); // set control ID id.id = n; id.signature = kRectGroupSignature; SetControlID( group, &id ); // create top { Str255 number; SInt16 content = 0x0000; if( size > position +1 ) content = *((short*)(*data + position)); NumToString( (long) content, number ); text = CFStringCreateWithPascalString( CFAllocatorGetDefault(), number, kCFStringEncodingMacRoman ); SetRect( &rect, bounds.left + (bounds.right - bounds.left -32) /2 +8, bounds.bottom +40, bounds.right -12, bounds.bottom +54 ); CreateEditTextControl( window, &rect, text, false, true, &fontStyle, &edit ); EmbedControl( edit, group ); // embed order: top, label, left, label, bottom, label, right, label SetRect( &secondaryLabelRect, bounds.left +12, bounds.bottom +40, bounds.left + (bounds.right - bounds.left -32) /2 -8, bounds.bottom +54 ); text = CFStringCreateWithPascalString( CFAllocatorGetDefault(), "\pTop", kCFStringEncodingMacRoman ); CreateStaticTextControl( window, &secondaryLabelRect, text, &rectLabelStyle, &secondaryLabel ); EmbedControl( secondaryLabel, group ); } position += 2; // create left { Str255 number; SInt16 content = 0x0000; if( size > position +1 ) content = *((short*)(*data + position)); NumToString( (long) content, number ); text = CFStringCreateWithPascalString( CFAllocatorGetDefault(), number, kCFStringEncodingMacRoman ); OffsetRect( &rect, 0, 26 ); CreateEditTextControl( window, &rect, text, false, true, &fontStyle, &edit ); EmbedControl( edit, group ); // embed order: top, label, left, label, bottom, label, right, label OffsetRect( &secondaryLabelRect, 0, 26 ); text = CFStringCreateWithPascalString( CFAllocatorGetDefault(), "\pLeft", kCFStringEncodingMacRoman ); CreateStaticTextControl( window, &secondaryLabelRect, text, &rectLabelStyle, &secondaryLabel ); EmbedControl( secondaryLabel, group ); } position += 2; // create bottom { Str255 number; SInt16 content = 0x0000; if( size > position +1 ) content = *((short*)(*data + position)); NumToString( (long) content, number ); text = CFStringCreateWithPascalString( CFAllocatorGetDefault(), number, kCFStringEncodingMacRoman ); OffsetRect( &rect, 0, 26 ); CreateEditTextControl( window, &rect, text, false, true, &fontStyle, &edit ); EmbedControl( edit, group ); // embed order: top, label, left, label, bottom, label, right, label OffsetRect( &secondaryLabelRect, 0, 26 ); text = CFStringCreateWithPascalString( CFAllocatorGetDefault(), "\pBottom", kCFStringEncodingMacRoman ); CreateStaticTextControl( window, &secondaryLabelRect, text, &rectLabelStyle, &secondaryLabel ); EmbedControl( secondaryLabel, group ); } position += 2; // create right { Str255 number; SInt16 content = 0x0000; if( size > position +1 ) content = *((short*)(*data + position)); NumToString( (long) content, number ); text = CFStringCreateWithPascalString( CFAllocatorGetDefault(), number, kCFStringEncodingMacRoman ); OffsetRect( &rect, 0, 26 ); CreateEditTextControl( window, &rect, text, false, true, &fontStyle, &edit ); EmbedControl( edit, group ); // embed order: top, label, left, label, bottom, label, right, label OffsetRect( &secondaryLabelRect, 0, 26 ); text = CFStringCreateWithPascalString( CFAllocatorGetDefault(), "\pRight", kCFStringEncodingMacRoman ); CreateStaticTextControl( window, &secondaryLabelRect, text, &rectLabelStyle, &secondaryLabel ); EmbedControl( secondaryLabel, group ); } position += 2; rect.top = bounds.bottom +14; rect.bottom += 18; } break; case 'ZCNT': { Str255 number; SInt16 content = 0x0000; if( size > position +1 ) content = *((short*)(*data + position)) +1; // add one for zero-based count NumToString( (long) content, number ); text = CFStringCreateWithPascalString( CFAllocatorGetDefault(), number, kCFStringEncodingMacRoman ); SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom +22 ); CreateStaticTextControl( window, &rect, text, &fontStyle, &listcount ); rect.bottom += 4; position += 2; // set recursion total (number of times to repeat) recursionTotal = content; // set control ID id.id = n; id.signature = kListCountSignature; SetControlID( edit, &id ); } break; case 'OCNT': { Str255 number; SInt16 content = 0x0000; if( size > position +1 ) content = *((short*)(*data + position)); NumToString( (long) content, number ); text = CFStringCreateWithPascalString( CFAllocatorGetDefault(), number, kCFStringEncodingMacRoman ); SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom +22 ); CreateStaticTextControl( window, &rect, text, &fontStyle, &listcount ); rect.bottom += 4; position += 2; // set recursion total (number of times to repeat) recursionTotal = content; // set control ID id.id = n; id.signature = kListCountSignature; SetControlID( edit, &id ); } break; case 'LSTB': // repeats to end of resource { recursionTotal = -1; recursionIndex = m; recursionOrigin = current; SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom +22 ); rect.bottom += 4; } break; case 'LSTC': // repeats recursionTotal times { recursionIndex = m; recursionOrigin = current; SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom +22 ); rect.bottom += 4; } break; case 'LSTZ': // repeats until 0x00 is encountered as first byte of next block { recursionTotal = -2; recursionIndex = m; recursionOrigin = current; SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom +22 ); rect.bottom += 4; } break; case 'LSTE': { recursionCount++; if( recursionTotal == -2 ) { UInt8 content = 0x00; if( size > position ) content = *((unsigned char*)(*data + position)); if( content != 0x00 ) { // set current parser back to where recursion began from m = recursionIndex; current = recursionOrigin; } } else if( recursionTotal == -1 ) { if( size > position ) { // set current parser back to where recursion began from m = recursionIndex; current = recursionOrigin; } } else if( recursionCount < recursionTotal ) { // set current parser back to where recursion began from m = recursionIndex; current = recursionOrigin; } SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom +22 ); rect.bottom += 4; } break; /* default: SetRect( &rect, bounds.left, bounds.bottom +8, bounds.right, bounds.bottom +22 ); if( current->type & 0xFF000000 == 'P' << 24 ) { // do Pxxx string SInt32 length; Str255 number; number[0] = 3; number[1] = (char) current->type << 8; number[2] = (char) current->type << 16; number[3] = (char) current->type << 24; StringToNum( number, &length ); if( size > position ) text = CFStringCreateWithPascalString( CFAllocatorGetDefault(), (unsigned char *) (*data + position), kCFStringEncodingMacRoman ); else text = CFSTR(""); CreateStaticTextControl( window, &rect, text, &fontStyle, &edit ); position += length + 1; // set control ID id.id = n; id.signature = kEditFieldSignature; SetControlID( edit, &id ); } else if( current->type & 0xFF000000 == 'C' << 24 ) { // do Cxxx string SInt32 length; Str255 number; number[0] = 3; number[1] = (char) current->type << 8; number[2] = (char) current->type << 16; number[3] = (char) current->type << 24; StringToNum( number, &length ); if( size > position ) text = CFStringCreateWithCString( CFAllocatorGetDefault(), *data + position, kCFStringEncodingMacRoman ); else text = CFSTR(""); CreateStaticTextControl( window, &rect, text, &fontStyle, &edit ); position += length + 1; // set control ID id.id = n; id.signature = kEditFieldSignature; SetControlID( edit, &id ); } else if( current->type & 0xFF000000 == 'H' << 24 ) { // do Hxxx string } // else I don't know what it is. rect.bottom += 4; break; */ } // create label if( (current->type != 'AWRD') && (current->type != 'ALNG') && ((current->type & 0xFF000000) != ('F' << 24)) ) // skip aligns and fillers { SetRect( &rect, windowBounds.left +8, rect.top, windowBounds.left +100, rect.bottom ); text = CFStringCreateWithPascalString( CFAllocatorGetDefault(), current->label, kCFStringEncodingMacRoman ); // Host_DebugError( current->label, rect.top ); CreateStaticTextControl( window, &rect, text, &fontStyle, &label ); id.id = n; id.signature = kLabelSignature; SetControlID( label, &id ); } // save rect for next element to use bounds.top = bounds.bottom = rect.bottom; // advance current element current = current->next; } if( current != null ) Host_DebugError( "\pLast elementÕs 'next' parameter != 0", (long) current ); // last element should have null as it's "next" param HSetState( data, state ); return error; } /*** READ CONTROLS ***/ OSStatus TemplateWindow::ReadControls( void ) { OSStatus error = noErr; // get resource ref Plug_WindowRef plugWindow = Host_GetPlugWindowFromWindowRef( window ); if( plugWindow == null ) DebugStr("\pplugWindow == null"); Plug_ResourceRef resource = Host_GetTargetResource( plugWindow ); if( resource == null ) DebugStr("\presource == null"); // create blank resource UInt32 size = 0; Handle data = NewHandle(0); // cycle through each element of the template ControlID id; ControlRef control, group; ElementPtr current = elements; ElementPtr recursionOrigin = null; // bug: only handles one level of recursion signed long recursionTotal = 0; unsigned long recursionIndex = 0, recursionCount = 0; unsigned long m = 0, n = 0; // counters, one is always unique, the other is an element index for( ; m < elementCount; m++ ) { n++; // advance unique counter // read controls switch( current->type ) { case 'BOOL': // BOOL is two bytes long, false == 0x0000, true == 0x0100 { UInt16 value = 0; // get control value id.id = n; id.signature = kBooleanGroupSignature; error = GetControlByID( window, &id, &control ); if( !error ) value = GetControlValue( control ) -1; // false gives 1, true gives 2 value <<= 8; // append correct data to handle SInt8 state = HGetState( data ); SetHandleSize( data, size +2 ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size BlockMoveData( &value, *data + size, 2 ); HSetState( data, state ); } size += 2; } break; case 'BBIT': case 'FBIT': { // read all eight bits in simultaneously // nb. re. filler bits - the control exists but is disabled/hidden. reading it gives value of 0 id.id = n; id.signature = kBooleanGroupSignature; error = GetControlByID( window, &id, &group ); if( !error ) { // read checkboxs UInt8 value = 0x00; GetIndexedSubControl( group, 1, &control ); value += (GetControlValue( control ) & 0x01) << 7; GetIndexedSubControl( group, 2, &control ); value += (GetControlValue( control ) & 0x01) << 6; GetIndexedSubControl( group, 3, &control ); value += (GetControlValue( control ) & 0x01) << 5; GetIndexedSubControl( group, 4, &control ); value += (GetControlValue( control ) & 0x01) << 4; GetIndexedSubControl( group, 5, &control ); value += (GetControlValue( control ) & 0x01) << 3; GetIndexedSubControl( group, 6, &control ); value += (GetControlValue( control ) & 0x01) << 2; GetIndexedSubControl( group, 7, &control ); value += (GetControlValue( control ) & 0x01) << 1; GetIndexedSubControl( group, 8, &control ); value += (GetControlValue( control ) & 0x01) << 0; // append correct data to handle SInt8 state = HGetState( data ); SetHandleSize( data, size +1 ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size BlockMoveData( &value, *data + size, 1 ); HSetState( data, state ); } } // update size & advance element counter size += 1; n += 7; } break; case 'DBYT': { id.id = n; id.signature = kEditFieldSignature; error = GetControlByID( window, &id, &control ); if( !error ) { // find out how much text has been typed Size bufferSize, actualSize; error = GetControlDataSize( control, kControlEditTextPart, kControlEditTextTextTag, &bufferSize ); if( !error ) { // allocate buffer and read data Ptr buffer = NewPtrClear( bufferSize ); error = GetControlData( control, kControlEditTextPart, kControlEditTextTextTag, bufferSize, buffer, &actualSize ); if( !error ) { // convert buffer into desired format SInt8 value; SInt32 number; Str255 string; string[0] = actualSize; BlockMoveData( buffer, &string[1], actualSize ); StringToNum( string, &number ); value = (char) number; // append correct data to handle SInt8 state = HGetState( data ); SetHandleSize( data, size +1 ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size BlockMoveData( &value, *data + size, 1 ); HSetState( data, state ); } size += 1; } DisposePtr( buffer ); } } } break; case 'DWRD': { id.id = n; id.signature = kEditFieldSignature; error = GetControlByID( window, &id, &control ); if( !error ) { // find out how much text has been typed Size bufferSize, actualSize; error = GetControlDataSize( control, kControlEditTextPart, kControlEditTextTextTag, &bufferSize ); if( !error ) { // allocate buffer and read data Ptr buffer = NewPtrClear( bufferSize ); error = GetControlData( control, kControlEditTextPart, kControlEditTextTextTag, bufferSize, buffer, &actualSize ); if( !error ) { // convert buffer into desired format SInt16 value; SInt32 number; Str255 string; string[0] = actualSize; BlockMoveData( buffer, &string[1], actualSize ); StringToNum( string, &number ); value = (short) number; // append correct data to handle SInt8 state = HGetState( data ); SetHandleSize( data, size +2 ); error = MemError(); if( !error ) { HLock( data ); // lock handle after increasing it's size BlockMoveData( &value, *data + size, 2 ); Host_DebugError( "\pvalue", value ); HSetState( data, state ); } else Host_DebugError( "\pMemError() occoured", error ); size += 2; } else Host_DebugError( "\pGetControlData() failed", error ); DisposePtr( buffer ); } else Host_DebugError( "\pGetControlDataSize() failed", error ); } else Host_DebugError( "\pCould not get EditText control", error ); } break; case 'DLNG': { id.id = n; id.signature = kEditFieldSignature; error = GetControlByID( window, &id, &control ); if( !error ) { // find out how much text has been typed Size bufferSize, actualSize; error = GetControlDataSize( control, kControlEditTextPart, kControlEditTextTextTag, &bufferSize ); if( !error ) { // allocate buffer and read data Ptr buffer = NewPtrClear( bufferSize ); error = GetControlData( control, kControlEditTextPart, kControlEditTextTextTag, bufferSize, buffer, &actualSize ); if( !error ) { // convert buffer into desired format SInt32 value; Str255 string; string[0] = actualSize; BlockMoveData( buffer, &string[1], actualSize ); StringToNum( string, &value ); // append correct data to handle SInt8 state = HGetState( data ); SetHandleSize( data, size +4 ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size BlockMoveData( &value, *data + size, 4 ); HSetState( data, state ); } size += 4; } DisposePtr( buffer ); } } } break; case 'HBYT': { id.id = n; id.signature = kEditFieldSignature; error = GetControlByID( window, &id, &control ); if( !error ) { // find out how much text has been typed Size bufferSize, actualSize; error = GetControlDataSize( control, kControlEditTextPart, kControlEditTextTextTag, &bufferSize ); if( !error ) { // allocate buffer and read data Ptr buffer = NewPtrClear( bufferSize ); error = GetControlData( control, kControlEditTextPart, kControlEditTextTextTag, bufferSize, buffer, &actualSize ); if( !error ) { // convert buffer into desired format SInt8 value; SInt32 number; Str255 string; string[0] = actualSize; BlockMoveData( buffer, &string[1], actualSize ); StringToNum( string, &number ); value = (char) number; // append correct data to handle SInt8 state = HGetState( data ); SetHandleSize( data, size +1 ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size BlockMoveData( &value, *data + size, 1 ); HSetState( data, state ); } size += 1; } DisposePtr( buffer ); } } } break; case 'HWRD': { id.id = n; id.signature = kEditFieldSignature; error = GetControlByID( window, &id, &control ); if( !error ) { // find out how much text has been typed Size bufferSize, actualSize; error = GetControlDataSize( control, kControlEditTextPart, kControlEditTextTextTag, &bufferSize ); if( !error ) { // allocate buffer and read data Ptr buffer = NewPtrClear( bufferSize ); error = GetControlData( control, kControlEditTextPart, kControlEditTextTextTag, bufferSize, buffer, &actualSize ); if( !error ) { // convert buffer into desired format SInt16 value; SInt32 number; Str255 string; string[0] = actualSize; BlockMoveData( buffer, &string[1], actualSize ); StringToNum( string, &number ); value = (short) number; // append correct data to handle SInt8 state = HGetState( data ); SetHandleSize( data, size +2 ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size BlockMoveData( &value, *data + size, 2 ); HSetState( data, state ); } size += 2; } DisposePtr( buffer ); } } } break; case 'HLNG': { id.id = n; id.signature = kEditFieldSignature; error = GetControlByID( window, &id, &control ); if( !error ) { // find out how much text has been typed Size bufferSize, actualSize; error = GetControlDataSize( control, kControlEditTextPart, kControlEditTextTextTag, &bufferSize ); if( !error ) { // allocate buffer and read data Ptr buffer = NewPtrClear( bufferSize ); error = GetControlData( control, kControlEditTextPart, kControlEditTextTextTag, bufferSize, buffer, &actualSize ); if( !error ) { // convert buffer into desired format SInt32 value; Str255 string; string[0] = actualSize; BlockMoveData( buffer, &string[1], actualSize ); StringToNum( string, &value ); // append correct data to handle SInt8 state = HGetState( data ); SetHandleSize( data, size +4 ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size BlockMoveData( &value, *data + size, 4 ); HSetState( data, state ); } size += 4; } DisposePtr( buffer ); } } } break; case 'FBYT': { SInt8 state = HGetState( data ); SetHandleSize( data, size +1 ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size *((char *) *data + size) = 0x00; HSetState( data, state ); } size += 1; } break; case 'FWRD': { SInt16 value = 0; SInt8 state = HGetState( data ); SetHandleSize( data, size +2 ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size BlockMoveData( &value, *data + size, 2 ); // *((short *) *data + size) = 0x0000; HSetState( data, state ); } size += 2; } break; case 'FLNG': { SInt32 value = 0; SInt8 state = HGetState( data ); SetHandleSize( data, size +4 ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size BlockMoveData( &value, *data + size, 4 ); // *((long *) *data + size) = 0x00000000; HSetState( data, state ); } size += 4; } break; case 'AWRD': { SInt8 state = HGetState( data ); SetHandleSize( data, size + size % 2 ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size while( size % 2 ) { *((char *) *data + size) = 0x00; size++; } HSetState( data, state ); } } break; case 'ALNG': { SInt8 state = HGetState( data ); SetHandleSize( data, size + size % 4 ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size while( size % 4 ) { *((char *) *data + size) = 0x00; size++; } HSetState( data, state ); } } break; case 'CHAR': // one byte { id.id = n; id.signature = kEditFieldSignature; error = GetControlByID( window, &id, &control ); if( !error ) { // find out how much text has been typed Size bufferSize, actualSize; error = GetControlDataSize( control, kControlEditTextPart, kControlEditTextTextTag, &bufferSize ); if( !error ) { // allocate buffer and read data Ptr buffer = NewPtrClear( (bufferSize > 1)? bufferSize:1 ); // ensures minimum buffer of one byte error = GetControlData( control, kControlEditTextPart, kControlEditTextTextTag, bufferSize, buffer, &actualSize ); if( !error ) { // put zero into buffer if actualSize == 0 if( actualSize < 1 ) *((char *) buffer) = 0x00; // append correct data to handle SInt8 state = HGetState( data ); SetHandleSize( data, size +1 ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size BlockMoveData( buffer, *data + size, 1 ); HSetState( data, state ); } size += 1; } DisposePtr( buffer ); } } } break; case 'TNAM': // four bytes { id.id = n; id.signature = kEditFieldSignature; error = GetControlByID( window, &id, &control ); if( !error ) { // find out how much text has been typed Size bufferSize, actualSize; error = GetControlDataSize( control, kControlEditTextPart, kControlEditTextTextTag, &bufferSize ); if( !error ) { // allocate buffer and read data Ptr buffer = NewPtrClear( (bufferSize > 4)? bufferSize:4 ); // ensures minimum buffer of four bytes error = GetControlData( control, kControlEditTextPart, kControlEditTextTextTag, bufferSize, buffer, &actualSize ); Str255 text; text[0] = 4; BlockMoveData( buffer, &text[1], 4 ); Host_DebugError( text, bufferSize ); if( !error ) { // put zero into buffer if actualSize == 0 if( actualSize < 4 ) *((long *) buffer) = 0x00000000; // append correct data to handle SInt8 state = HGetState( data ); SetHandleSize( data, size +4 ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size BlockMoveData( buffer, *data + size, 4 ); HSetState( data, state ); } size += 4; } DisposePtr( buffer ); } } } break; case 'CSTR': { id.id = n; id.signature = kEditFieldSignature; error = GetControlByID( window, &id, &control ); if( !error ) { // find out how much text has been typed Size bufferSize, actualSize; error = GetControlDataSize( control, kControlEditTextPart, kControlEditTextTextTag, &bufferSize ); if( !error ) { // allocate buffer and read data Ptr buffer = NewPtrClear( bufferSize ); error = GetControlData( control, kControlEditTextPart, kControlEditTextTextTag, bufferSize, buffer, &actualSize ); if( !error ) { // append correct data to handle SInt8 state = HGetState( data ); SetHandleSize( data, size + actualSize +1 ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size BlockMoveData( buffer, *data + size, actualSize ); *((char *)(*data + size + actualSize)) = 0x00; // add zero byte HSetState( data, state ); } size += actualSize +1; } DisposePtr( buffer ); } } } break; case 'ECST': { id.id = n; id.signature = kEditFieldSignature; error = GetControlByID( window, &id, &control ); if( !error ) { // find out how much text has been typed Size bufferSize, actualSize; error = GetControlDataSize( control, kControlEditTextPart, kControlEditTextTextTag, &bufferSize ); if( !error ) { // allocate buffer and read data Ptr buffer = NewPtrClear( bufferSize ); error = GetControlData( control, kControlEditTextPart, kControlEditTextTextTag, bufferSize, buffer, &actualSize ); if( !error ) { // decide if I need a padding byte or not Boolean pad = (actualSize % 2 == 0)? true:false; // append correct data to handle SInt8 state = HGetState( data ); SetHandleSize( data, size + actualSize + (pad? 1:0) +1 ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size BlockMoveData( buffer, *data + size, actualSize ); *((char *)(*data + size + actualSize)) = 0x00; // add zero byte if( pad ) *((char *)(*data + size + actualSize +1)) = 0x00; // add pad byte HSetState( data, state ); } size += actualSize + (pad? 1:0) +1; } DisposePtr( buffer ); } } } break; case 'OCST': { id.id = n; id.signature = kEditFieldSignature; error = GetControlByID( window, &id, &control ); if( !error ) { // find out how much text has been typed Size bufferSize, actualSize; error = GetControlDataSize( control, kControlEditTextPart, kControlEditTextTextTag, &bufferSize ); if( !error ) { // allocate buffer and read data Ptr buffer = NewPtrClear( bufferSize ); error = GetControlData( control, kControlEditTextPart, kControlEditTextTextTag, bufferSize, buffer, &actualSize ); if( !error ) { // decide if I need a padding byte or not Boolean pad = (actualSize % 2 == 1)? true:false; // append correct data to handle SInt8 state = HGetState( data ); SetHandleSize( data, size + actualSize + (pad? 1:0) +1 ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size BlockMoveData( buffer, *data + size, actualSize ); *((char *)(*data + size + actualSize)) = 0x00; // add zero byte if( pad ) *((char *)(*data + size + actualSize +1)) = 0x00; // add pad byte HSetState( data, state ); } size += actualSize + (pad? 1:0) +1; } DisposePtr( buffer ); } } } break; case 'PSTR': { id.id = n; id.signature = kEditFieldSignature; error = GetControlByID( window, &id, &control ); if( !error ) { // find out how much text has been typed Size bufferSize, actualSize; error = GetControlDataSize( control, kControlEditTextPart, kControlEditTextTextTag, &bufferSize ); if( !error ) { // allocate buffer and read data Ptr buffer = NewPtrClear( bufferSize ); error = GetControlData( control, kControlEditTextPart, kControlEditTextTextTag, bufferSize, buffer, &actualSize ); if( !error ) { // append correct data to handle SInt8 state = HGetState( data ); SetHandleSize( data, size + actualSize +1 ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size *((char *)(*data + size)) = (char) actualSize; // add length byte BlockMoveData( buffer, *data + size +1, actualSize ); HSetState( data, state ); } size += actualSize +1; } DisposePtr( buffer ); } } } break; case 'ESTR': { id.id = n; id.signature = kEditFieldSignature; error = GetControlByID( window, &id, &control ); if( !error ) { // find out how much text has been typed Size bufferSize, actualSize; error = GetControlDataSize( control, kControlEditTextPart, kControlEditTextTextTag, &bufferSize ); if( !error ) { // allocate buffer and read data Ptr buffer = NewPtrClear( bufferSize ); error = GetControlData( control, kControlEditTextPart, kControlEditTextTextTag, bufferSize, buffer, &actualSize ); if( !error ) { // decide if I need a padding byte or not Boolean pad = (actualSize % 2 == 0)? true:false; // append correct data to handle SInt8 state = HGetState( data ); SetHandleSize( data, size + actualSize + (pad? 1:0) +1 ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size *((char *)(*data + size)) = (char) actualSize; // add length byte BlockMoveData( buffer, *data + size +1, actualSize ); if( pad ) *((char *)(*data + size + actualSize +1)) = 0x00; // add pad byte HSetState( data, state ); } size += actualSize + (pad? 1:0) +1; } DisposePtr( buffer ); } } } break; case 'OSTR': { id.id = n; id.signature = kEditFieldSignature; error = GetControlByID( window, &id, &control ); if( !error ) { // find out how much text has been typed Size bufferSize, actualSize; error = GetControlDataSize( control, kControlEditTextPart, kControlEditTextTextTag, &bufferSize ); if( !error ) { // allocate buffer and read data Ptr buffer = NewPtrClear( bufferSize ); error = GetControlData( control, kControlEditTextPart, kControlEditTextTextTag, bufferSize, buffer, &actualSize ); if( !error ) { // decide if I need a padding byte or not Boolean pad = (actualSize % 2 == 1)? true:false; // append correct data to handle SInt8 state = HGetState( data ); SetHandleSize( data, size + actualSize + (pad? 1:0) +1 ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size *((char *)(*data + size)) = (char) actualSize; // add length byte BlockMoveData( buffer, *data + size +1, actualSize ); if( pad ) *((char *)(*data + size + actualSize +1)) = 0x00; // add pad byte HSetState( data, state ); } size += actualSize + (pad? 1:0) +1; } DisposePtr( buffer ); } } } break; case 'WSTR': { id.id = n; id.signature = kEditFieldSignature; error = GetControlByID( window, &id, &control ); if( !error ) { // find out how much text has been typed Size bufferSize, actualSize; error = GetControlDataSize( control, kControlEditTextPart, kControlEditTextTextTag, &bufferSize ); if( !error ) { // allocate buffer and read data Ptr buffer = NewPtrClear( bufferSize ); error = GetControlData( control, kControlEditTextPart, kControlEditTextTextTag, bufferSize, buffer, &actualSize ); if( !error ) { // append correct data to handle SInt8 state = HGetState( data ); SetHandleSize( data, size + actualSize +2 ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size *((short *)(*data + size)) = (short) actualSize; // add length bytes BlockMoveData( buffer, *data + size +2, actualSize ); HSetState( data, state ); } size += actualSize +2; } DisposePtr( buffer ); } } } break; case 'LSTR': { id.id = n; id.signature = kEditFieldSignature; error = GetControlByID( window, &id, &control ); if( !error ) { // find out how much text has been typed Size bufferSize, actualSize; error = GetControlDataSize( control, kControlEditTextPart, kControlEditTextTextTag, &bufferSize ); if( !error ) { // allocate buffer and read data Ptr buffer = NewPtrClear( bufferSize ); error = GetControlData( control, kControlEditTextPart, kControlEditTextTextTag, bufferSize, buffer, &actualSize ); if( !error ) { // append correct data to handle SInt8 state = HGetState( data ); SetHandleSize( data, size + actualSize +4 ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size *((long *)(*data + size)) = (long) actualSize; // add length bytes BlockMoveData( buffer, *data + size +4, actualSize ); HSetState( data, state ); } size += actualSize +4; } DisposePtr( buffer ); } } } break; case 'HEXD': { id.id = n; id.signature = kEditFieldSignature; error = GetControlByID( window, &id, &control ); if( !error ) { // find out how much text has been typed Size bufferSize, actualSize; error = GetControlDataSize( control, kControlEditTextPart, kControlEditTextTextTag, &bufferSize ); if( !error ) { // allocate buffer and read data Ptr buffer = NewPtrClear( bufferSize ); error = GetControlData( control, kControlEditTextPart, kControlEditTextTextTag, bufferSize, buffer, &actualSize ); if( !error ) { // append correct data to handle SInt8 state = HGetState( data ); SetHandleSize( data, size + actualSize ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size BlockMoveData( buffer, *data + size, actualSize ); HSetState( data, state ); } size += actualSize; } DisposePtr( buffer ); } } } break; case 'RECT': { id.id = n; id.signature = kRectGroupSignature; error = GetControlByID( window, &id, &group ); if( !error ) { // read checkboxs Rect value; error = GetIndexedSubControl( group, 2, &control ); if( !error ) { // find out how much text has been typed Size bufferSize, actualSize; error = GetControlDataSize( control, kControlEditTextPart, kControlEditTextTextTag, &bufferSize ); if( !error ) { // allocate buffer and read data Ptr buffer = NewPtrClear( bufferSize ); error = GetControlData( control, kControlEditTextPart, kControlEditTextTextTag, bufferSize, buffer, &actualSize ); if( !error ) { // convert buffer into desired format SInt32 number; Str255 string; string[0] = actualSize; BlockMoveData( buffer, &string[1], actualSize ); StringToNum( string, &number ); value.top = (short) number; } DisposePtr( buffer ); } } else value.top = 0; error = GetIndexedSubControl( group, 4, &control ); if( !error ) { // find out how much text has been typed Size bufferSize, actualSize; error = GetControlDataSize( control, kControlEditTextPart, kControlEditTextTextTag, &bufferSize ); if( !error ) { // allocate buffer and read data Ptr buffer = NewPtrClear( bufferSize ); error = GetControlData( control, kControlEditTextPart, kControlEditTextTextTag, bufferSize, buffer, &actualSize ); if( !error ) { // convert buffer into desired format SInt32 number; Str255 string; string[0] = actualSize; BlockMoveData( buffer, &string[1], actualSize ); StringToNum( string, &number ); value.left = (short) number; } DisposePtr( buffer ); } } else value.left = 0; error = GetIndexedSubControl( group, 6, &control ); if( !error ) { // find out how much text has been typed Size bufferSize, actualSize; error = GetControlDataSize( control, kControlEditTextPart, kControlEditTextTextTag, &bufferSize ); if( !error ) { // allocate buffer and read data Ptr buffer = NewPtrClear( bufferSize ); error = GetControlData( control, kControlEditTextPart, kControlEditTextTextTag, bufferSize, buffer, &actualSize ); if( !error ) { // convert buffer into desired format SInt32 number; Str255 string; string[0] = actualSize; BlockMoveData( buffer, &string[1], actualSize ); StringToNum( string, &number ); value.bottom = (short) number; } DisposePtr( buffer ); } } else value.bottom = 0; error = GetIndexedSubControl( group, 8, &control ); if( !error ) { // find out how much text has been typed Size bufferSize, actualSize; error = GetControlDataSize( control, kControlEditTextPart, kControlEditTextTextTag, &bufferSize ); if( !error ) { // allocate buffer and read data Ptr buffer = NewPtrClear( bufferSize ); error = GetControlData( control, kControlEditTextPart, kControlEditTextTextTag, bufferSize, buffer, &actualSize ); if( !error ) { // convert buffer into desired format SInt32 number; Str255 string; string[0] = actualSize; BlockMoveData( buffer, &string[1], actualSize ); StringToNum( string, &number ); value.right = (short) number; } DisposePtr( buffer ); } } else value.right = 0; // append correct data to handle SInt8 state = HGetState( data ); SetHandleSize( data, size +8 ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size BlockMoveData( &value, *data + size, 8 ); HSetState( data, state ); } size += 8; } } break; case 'ZCNT': case 'OCNT': { id.id = n; id.signature = kListCountSignature; error = GetControlByID( window, &id, &control ); if( !error ) { // find out how much text has been typed Size bufferSize, actualSize; error = GetControlDataSize( control, kControlLabelPart, kControlStaticTextTextTag, &bufferSize ); if( !error ) { // allocate buffer and read data Ptr buffer = NewPtrClear( bufferSize ); error = GetControlData( control, kControlLabelPart, kControlStaticTextTextTag, bufferSize, buffer, &actualSize ); if( !error ) { // convert buffer into desired format SInt16 value; SInt32 number; Str255 string; string[0] = actualSize; BlockMoveData( buffer, &string[1], actualSize ); StringToNum( string, &number ); value = (short) number; // set recursion total (number of times to repeat) recursionTotal = value; // actually, this value is ignored :) -- I count occourences of LSTE instead // append correct data to handle SInt8 state = HGetState( data ); SetHandleSize( data, size +2 ); if( !MemError() ) { HLock( data ); // lock handle after increasing it's size BlockMoveData( &value, *data + size, 2 ); HSetState( data, state ); } size += 2; } DisposePtr( buffer ); } } } break; case 'LSTB': // repeats to end of resource { recursionTotal = -1; recursionIndex = m; recursionOrigin = current; } break; case 'LSTC': // repeats recursionTotal times { recursionIndex = m; recursionOrigin = current; } break; case 'LSTZ': // repeats until 0x00 is encountered as first byte of next block { recursionTotal = -2; recursionIndex = m; recursionOrigin = current; } break; case 'LSTE': { recursionCount++; /* if( recursionTotal == -2 ) { UInt8 content = 0x00; if( size > position ) content = *((unsigned char*)(*data + position)); if( content != 0x00 ) { // set current parser back to where recursion began from m = recursionIndex; current = recursionOrigin; } } else if( recursionTotal == -1 ) { if( size > position ) { // set current parser back to where recursion began from m = recursionIndex; current = recursionOrigin; } } else if( recursionCount < recursionTotal ) { // set current parser back to where recursion began from m = recursionIndex; current = recursionOrigin; } */ } break; default: break; } // advance current element current = current->next; } // save any changes if( !error ) { Handle original = Host_GetResourceData( resource ); Host_DebugError( "\ptesting if handles matchÉ", 0 ); if( !HandlesMatch( original, data ) ) // only save if data changed { Host_DebugError( "\pthey don't, saving changesÉ", 0 ); SInt8 state = HGetState( original ); HLock( original ); SetHandleSize( original, size ); BlockMoveData( *data, *original, size ); HSetState( original, state ); Host_SetResourceDirty( resource, true ); } else Host_DebugError( "\pthey do match, don't save changes", 0 ); Host_ReleaseResourceData( resource ); } else Host_DebugError( "\pan error occoured somewhere, don't save any changes", error ); // clean up and leave DisposeHandle( data ); return error; } /*** HANDLES MATCH ***/ Boolean HandlesMatch( const Handle one, const Handle two ) { Size sizeOne = GetHandleSize( one ); Size sizeTwo = GetHandleSize( two ); if( sizeOne != sizeTwo ) return false; else { SInt8 stateOne = HGetState( one ); SInt8 stateTwo = HGetState( two ); HLock( one ); HLock( two ); char *a = *one; char *b = *two; for( unsigned short i = 0; i < sizeOne; i++ ) if( *a++ != *b++ ) return false; HSetState( one, stateOne ); HSetState( two, stateTwo ); return true; } }