sources/QTSSampleCodeUtils.c

/*
    File:       QTSSampleCodeUtils.c
 
    Copyright:  © 2000-2001 by Apple Computer, Inc., all rights reserved.
 
 
*/
 
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
 
#include <NumberFormatting.h>
#include <StringCompare.h>
#include <ControlDefinitions.h>
#include <TextUtils.h>
 
#include <QuickTimeStreaming.h>
 
 
 
#include "QTSSampleCodeUtils.h"
 
// ---------------------------------------------------------------------------
//      D E F I N I T I O N S
// ---------------------------------------------------------------------------
 
#define kMaxPStringLength       255
 
// ---------------------------------------------------------------------------
//      P R O T O T Y P E S
// ---------------------------------------------------------------------------
 
static void FindThisApplication(FSSpec *outSpec);
 
// ---------------------------------------------------------------------------
//      SafeHandToHand
// ---------------------------------------------------------------------------
 
OSErr SafeHandToHand(Handle inOrigHandle, Handle *outNewHandle)
{
    OSErr       err = noErr;
    SInt32      handleSize;
    
    if (inOrigHandle == NULL)  {
        *outNewHandle = NULL;
    }  else  {
        handleSize = GetHandleSize(inOrigHandle);
        *outNewHandle = QTSNewHandle(handleSize, 0L, NULL);
        EXITIFERR( err = MemError() );
        BlockMoveData(*inOrigHandle, **outNewHandle, handleSize);
    }
exit:
    return err;
}
 
#pragma mark -
 
// ---------------------------------------------------------------------------
//      QTSCopyMediaParams
// ---------------------------------------------------------------------------
 
OSErr QTSCopyMediaParams(QTSMediaParams *inSourceMediaParams, QTSMediaParams *outDestMediaParams)
{
    OSErr   err = noErr;
 
    if ((outDestMediaParams != nil) && (inSourceMediaParams != nil)) {
        *outDestMediaParams = *inSourceMediaParams;
        outDestMediaParams->v.clip = nil;
        outDestMediaParams->a.frequencyBands = nil;
        
        err = CopyRgnUtil(inSourceMediaParams->v.clip, &(outDestMediaParams->v.clip));
        if ((err == noErr) && (inSourceMediaParams->a.frequencyBandsCount > 0)) {
            long    frequencyBandsPtrSize;
            
            frequencyBandsPtrSize = inSourceMediaParams->a.frequencyBandsCount * sizeof(UnsignedFixed);
            
            outDestMediaParams->a.frequencyBands = (void*)QTSNewPtr(frequencyBandsPtrSize, 0L, 0L);
            if ((err = MemError()) == noErr) {
                BlockMoveData(inSourceMediaParams->a.frequencyBands,
                                outDestMediaParams->a.frequencyBands,
                                frequencyBandsPtrSize);
            }
        }
    } else {
        err = paramErr;
    }
    
    return err;
}
 
// ---------------------------------------------------------------------------
//      QTSDisposeMediaParams
// ---------------------------------------------------------------------------
 
void QTSDisposeMediaParams(QTSMediaParams *inMediaParams)
{
    if (inMediaParams != nil) {
        DISPOSEIFRGN(inMediaParams->v.clip);
        DisposePtr((Ptr)inMediaParams->a.frequencyBands);
    }
}
 
// ---------------------------------------------------------------------------
//      CopyRgnUtil
// ---------------------------------------------------------------------------
 
OSErr CopyRgnUtil(RgnHandle inRgn, RgnHandle *ioRgn)
{
    // make ioRgn look like inRgn
    OSErr       err = noErr;
 
    if (inRgn == NULL)  {
        DISPOSEIFRGN(*ioRgn);
    }  else  {
        if (*ioRgn == NULL)  {
            *ioRgn = NewRgn();
            if (*ioRgn == NULL)  {
                err = memFullErr;
                goto exit;
            }   
        }   
        MacCopyRgn(inRgn, *ioRgn);
        err = MemError();
    }
exit:   
    if (err != noErr)  {
        DISPOSEIFRGN(*ioRgn);       
    }
    return err;
}
 
#pragma mark -
 
// ---------------------------------------------------------------------------
//      QTSGetTimeBaseTime
// ---------------------------------------------------------------------------
 
UInt32 QTSGetTimeBaseTime(TimeBase inTimeBase, TimeScale inTimeScale)
{
    TimeRecord      timeRecord;
    
    timeRecord.value.lo = 0;
    timeRecord.value.hi = 0;
    timeRecord.scale = inTimeScale;
    timeRecord.base = inTimeBase;
    GetTimeBaseStatus(inTimeBase, &timeRecord);
    ConvertTimeScale(&timeRecord, inTimeScale);
    return timeRecord.value.lo;
}
 
// ---------------------------------------------------------------------------
//      QTSGetTimeBaseTime64
// ---------------------------------------------------------------------------
 
void QTSGetTimeBaseTime64(TimeBase inTimeBase, TimeScale inTimeScale, TimeValue64 *outTime)
{
    TimeRecord      timeRecord;
    
    timeRecord.value.lo = 0;
    timeRecord.value.hi = 0;
    timeRecord.scale = inTimeScale;
    timeRecord.base = inTimeBase;
    GetTimeBaseStatus(inTimeBase, &timeRecord);
    ConvertTimeScale(&timeRecord, inTimeScale);
    *outTime = *((TimeValue64*)&timeRecord.value);
}
 
// ---------------------------------------------------------------------------
//      QTSConvertDuration
// ---------------------------------------------------------------------------
 
UInt32 QTSConvertDuration(UInt32 inOriginalDuration,
            TimeScale inOriginalTimeScale, TimeScale inNewTimeScale)
{
    TimeRecord      timeRecord;
    
    if (inNewTimeScale != 0 && inOriginalTimeScale != 0)  {
        timeRecord.value.lo = inOriginalDuration;
        timeRecord.value.hi = 0;
        timeRecord.scale = inOriginalTimeScale;
        timeRecord.base = NULL;
        ConvertTimeScale(&timeRecord, inNewTimeScale);
    }  else {
        //DEBUGF(("QTSConvertDuration - 0 timescale, dur %ld, origtimescale %ld, newtimescale %ld",
        //                  inOriginalDuration, inOriginalTimeScale, inNewTimeScale));
        timeRecord.value.lo = 0;
    }
    return timeRecord.value.lo;
}
 
// ---------------------------------------------------------------------------
//      QTSConvertDuration64
// ---------------------------------------------------------------------------
 
void QTSConvertDuration64(const TimeValue64 *inOriginalDuration,
            TimeScale inOriginalTimeScale, TimeScale inNewTimeScale,
            TimeValue64 *outConvertedDuration)
{
    TimeRecord      timeRecord;
    
    if (inNewTimeScale != 0 && inOriginalTimeScale != 0)  {
        timeRecord.value = *((wide*)inOriginalDuration);
        timeRecord.scale = inOriginalTimeScale;
        timeRecord.base = NULL;
        ConvertTimeScale(&timeRecord, inNewTimeScale);
        *outConvertedDuration = *((TimeValue64*)&timeRecord.value);
    }  else  {
        //DEBUGF(("QTSConvertDuration64 - 0 timescale, dur %0.8x %0.8x, origtimescale %ld, newtimescale %ld",
        //                  QTSInt64Hi32(*inOriginalDuration), QTSInt64Lo32(*inOriginalDuration), inOriginalTimeScale, inNewTimeScale));
        *outConvertedDuration = 0;
    }
}
 
// ---------------------------------------------------------------------------
//      DateTimeRecToString
// ---------------------------------------------------------------------------
 
void DateTimeRecToString(const DateTimeRec *inRec, char *outString)
{
    sprintf((char*)outString, "%0.2u:%0.2u:%0.2u:%0.2u", inRec->day, inRec->hour,
                            inRec->minute, inRec->second);
}
 
// ---------------------------------------------------------------------------
//      TimeValue64ToDateTimeRec
// ---------------------------------------------------------------------------
 
void TimeValue64ToDateTimeRec(const TimeValue64 *inTime64, TimeScale inTimeScale, DateTimeRec *outRec)
{
 
    TimeValue64     time64;
    TimeValue64     temp64;
 
#define kNumSecondsPerMinute        60
#define kNumMinutesPerHour          60
#define kNumHoursPerDay             24
 
#define kNumSecondsPerHour          (kNumSecondsPerMinute * kNumMinutesPerHour)
#define kNumSecondsPerDay           (kNumSecondsPerMinute * kNumMinutesPerHour * kNumHoursPerDay)
 
    
    memset(outRec, 0, sizeof(*outRec));
    time64 = *inTime64;
    if (inTimeScale == 0)  {
        DEBUGF(("TimeValue64ToDateTimeRec-timescale=0"));
        goto exit;
    }
 
    temp64 = time64 / (kNumSecondsPerDay * inTimeScale);
    if (temp64 > 0)  {
        outRec->day = (short)temp64;
        time64 -= (temp64 * kNumSecondsPerDay * inTimeScale);
    }
    
    temp64 = time64 / (kNumSecondsPerHour * inTimeScale);
    if (temp64 > 0)  {
        outRec->hour = (short)temp64;
        time64 -= (temp64 * kNumSecondsPerHour * inTimeScale);
    }
    
    temp64 = time64 / (kNumSecondsPerMinute * inTimeScale);
    if (temp64 > 0)  {
        outRec->minute = (short)temp64;
        time64 -= (temp64 * kNumSecondsPerMinute * inTimeScale);
    }
                
    temp64 = (time64 + inTimeScale/2) / (inTimeScale);
    if (temp64 > 0)  {
        outRec->second = (short)temp64;
    }
exit:
    return;
}
 
 
// ---------------------------------------------------------------------------
//      TimeValue64ToString
// ---------------------------------------------------------------------------
 
void TimeValue64ToString(const TimeValue64 *inTime64, TimeScale inTimeScale, char *outString)
{
    DateTimeRec     dtrec;  
    
    TimeValue64ToDateTimeRec(inTime64, inTimeScale, &dtrec);
    DateTimeRecToString(&dtrec, outString);
}
 
#pragma mark -
 
// ---------------------------------------------------------------------------
//      CStringToCStringPtr
// ---------------------------------------------------------------------------
 
OSErr CStringToCStringPtr(const char *inString, CStringPtr *outCStringPtr)
{
    return StringToCStringPtr(inString, strlen(inString), outCStringPtr);
}
 
// ---------------------------------------------------------------------------
//      PStringToCStringPtr
// ---------------------------------------------------------------------------
 
OSErr PStringToCStringPtr(const unsigned char *inString, CStringPtr *outCStringPtr)
{
    return StringToCStringPtr((const char*)&(inString[1]), inString[0], outCStringPtr);
}
 
// ---------------------------------------------------------------------------
//      StringToCStringPtr
// ---------------------------------------------------------------------------
 
OSErr StringToCStringPtr(const char *inString, UInt32 inStringLength, CStringPtr *outCStringPtr)
{
    Ptr         myPtr;
    OSErr       err = noErr;
    
    myPtr = QTSNewPtr((long)(inStringLength + 1), 0L, NULL);
    if (myPtr == NULL)  {
        err = memFullErr;
        *outCStringPtr = NULL;
    }  else  {
        if (inStringLength > 0)  {
            BlockMoveData(inString, myPtr, (long)inStringLength);
        }
        myPtr[inStringLength] = '\0';
        *outCStringPtr = myPtr;
    }
    return err;
}
 
//----------------------------------------------------------------------------------------
//      CopyCToPStr: 
//----------------------------------------------------------------------------------------
 
void CopyCToPStr(const char *inCString, unsigned char *outPString)
{
    CopyCToPStrn(inCString, outPString, kMaxPStringLength);
} 
 
//----------------------------------------------------------------------------------------
//      CopyCToPStrn 
//----------------------------------------------------------------------------------------
 
void CopyCToPStrn(const char *inCString, unsigned char *outPString, UInt32 inMaxLength)
{
    unsigned long       length;
    
    length = strlen(inCString);
    if (length > inMaxLength)  {
        length = kMaxPStringLength;
    }
    BlockMoveData(inCString, &(outPString[1]), (long)length);
    outPString[0] = (unsigned char)length;
} 
 
//----------------------------------------------------------------------------------------
//      CopyPToCStr: 
//----------------------------------------------------------------------------------------
 
void CopyPToCStr(const unsigned char *inPString, char *outCString)
{
    CopyPToCStrn(inPString, outCString, kMaxPStringLength);
} 
 
//----------------------------------------------------------------------------------------
//      CopyPToCStrn 
//----------------------------------------------------------------------------------------
 
void CopyPToCStrn(const unsigned char *inPString, char *outCString, UInt32 inMaxLength)
{
    unsigned long       length;
    
    length = inPString[0];
    if (length > inMaxLength)  {
        length = inMaxLength;
    }
    BlockMoveData( &(inPString[1]), outCString, (long)length );
    outCString[length] = '\0';
} 
 
// ---------------------------------------------------------------------------
//      pstrcpy
// ---------------------------------------------------------------------------
 
unsigned char *pstrcpy(unsigned char *dest, const unsigned char *source)
{
    BlockMoveData(source, dest, source[0]+1);
    return dest;
}
 
// ---------------------------------------------------------------------------
//      pstrncpy
// ---------------------------------------------------------------------------
 
unsigned char *pstrncpy(unsigned char *dest, const unsigned char *source, long maxLength)
{
    long        copyLength;
    
    if (maxLength < source[0])  {
        copyLength = maxLength+1;
    }  else  {
        copyLength = source[0]+1;
    }
    BlockMoveData(source, dest, copyLength);
    dest[0] = (unsigned char)(copyLength-1);
    return dest;
}
 
// ---------------------------------------------------------------------------
//      pstrcat
// ---------------------------------------------------------------------------
 
unsigned char *pstrcat(unsigned char *dest, const unsigned char *source)
{
    BlockMoveData(source + 1, dest + dest[0]+1, source[0]);
    dest[0] = (unsigned char)(dest[0] + source[0]);
    return dest;
}
 
// ---------------------------------------------------------------------------
//      pstrncat
// ---------------------------------------------------------------------------
 
unsigned char *pstrncat(unsigned char *dest, const unsigned char *source, long maxLength)
{
    long        copyLength;
    
    if (maxLength - (dest[0]+1) < source[0])  {
        copyLength = maxLength - (dest[0]+1);
    }  else  {
        copyLength = source[0];
    }
    BlockMoveData(source + 1, dest + dest[0]+1, copyLength);
    dest[0] = (unsigned char)(dest[0] + copyLength);
    return dest;
}
 
// ---------------------------------------------------------------------------
//      ScanTo
// ---------------------------------------------------------------------------
 
char *ScanTo(const char *inText, char inChar, UInt32 inTextLength)
{
    const char  *current = inText;
    const char  *end = inText + inTextLength;
    Boolean     found = false;
 
    // like strchr except it doesn't assume null terminated
    while (current < end)  {
        if (current[0] == inChar)  {
            found = true;
            break;
        }
        ++current;
    }
    return (found ? (char*)current : NULL);
}
 
// ---------------------------------------------------------------------------
//      ScanToString
// ---------------------------------------------------------------------------
 
const char *ScanToString(const char *inText, UInt32 inTextLength,
                const char *inMatchString, UInt32 inMatchStringLength)
{
    const char  *current = inText;
    const char  *end = inText + inTextLength;
    Boolean     done = false;
    Boolean     found = false;
    char        firstChar;
    
    firstChar = inMatchString[0];
    while ( (current < end)  &&
            ((current = ScanTo(current, firstChar, end - current)) != NULL) )  {
        if (StartsWith(current, end - current, inMatchString, inMatchStringLength))  {
            found = true;
            break;
        }  else  {
            ++current;
        }
    };
    if (!found)  {
        current = NULL;
    }
    return current;
}
 
// ---------------------------------------------------------------------------
//      StartsWith
// ---------------------------------------------------------------------------
 
Boolean StartsWith(const char *inLine, UInt32 inMaxLineLength,
                const char *inMatchString, UInt32 inMatchStringLength)
{
    Boolean     matches = false;
 
    if ((inMaxLineLength == 0)  ||  (inLine[0] == '\0')  ||
        (inMatchStringLength == 0)  ||  (inMatchString[0] == '\0') )  {
        //DEBUGF(("StartsWith - one string is empty"));
    }  else  {
        if (inMaxLineLength >= inMatchStringLength)  {
            matches = EqualChars(inLine, inMatchStringLength, inMatchString, inMatchStringLength);
        }
    }
    return matches;
}
 
// ---------------------------------------------------------------------------
//      EndsWith
// ---------------------------------------------------------------------------
 
Boolean EndsWith(const char *inLine, UInt32 inMaxLineLength,
                    const char *inMatchString, UInt32 inMatchStringLength)
{
    Boolean     matches = false;
 
    if ((inMaxLineLength == 0)  ||  (inLine[0] == '\0')  ||
        (inMatchStringLength == 0)  ||  (inMatchString[0] == '\0') )  {
        //DEBUGF(("EndsWith - one string is empty"));
    }  else  {
        if (inMaxLineLength >= inMatchStringLength)  {
            matches = EqualChars(inLine + (inMaxLineLength - inMatchStringLength),
                    inMatchStringLength, inMatchString, inMatchStringLength);
        }
    }
    return matches;
}
 
// ---------------------------------------------------------------------------
//      EqualChars
// ---------------------------------------------------------------------------
 
Boolean EqualChars(const char *inCharsA, UInt32 inCharsALength,
                    const char *inCharsB, UInt32 inCharsBLength)
{
#if TARGET_API_MAC_CARBON
    return (Boolean)(IdenticalText(inCharsA, inCharsB,
                    inCharsALength, inCharsBLength, nil) == 0);
#else
    // IUMagIDString has some problems with zero lengths, so check beforehand
    if ((inCharsALength > 0)  &&  (inCharsA[0] != '\0')  &&
        (inCharsBLength > 0)  &&  (inCharsB[0] != '\0'))  {
        return (Boolean)(IUMagIDString(inCharsA, inCharsB,
                (short)inCharsALength, (short)inCharsBLength) == 0);
    }
    return false;
#endif
}
 
// ---------------------------------------------------------------------------
//      GetLineEnd
// ---------------------------------------------------------------------------
 
const char *GetLineEnd(const char *inChars, UInt32 inMaxLength)
{
    const char      *current = inChars;
    const char      *end = inChars + inMaxLength;
     
    while ( (current < end)     &&
            (current[0] != CR)  &&
            (current[0] != LF)  &&
            (current[0] != '\0') )  {
            
        ++current;
    }
    return current;
}
 
// ---------------------------------------------------------------------------
//      GetNextLineStart
// ---------------------------------------------------------------------------
 
const char *GetNextLineStart(const char *inChars, UInt32 inMaxLength)
{
    const char      *current = inChars;
    const char      *end = inChars + inMaxLength;
     
    while ( (current < end)     &&
            (current[0] == CR)  &&
            (current[0] == LF)  &&
            (current[0] != '\0') )  {
        ++current;
    }
    return current;
}
 
// ---------------------------------------------------------------------------
//      IsEOLChar
// ---------------------------------------------------------------------------
 
Boolean IsEOLChar(char inChar)
{
    return ((inChar == CR)  ||  (inChar == LF));
}
 
// ---------------------------------------------------------------------------
//      GetShortDateTimeString
// ---------------------------------------------------------------------------
 
void GetShortDateTimeString(char *outString, UInt32 inRandomNum)
{
    UInt32          secs;
    DateTimeRec     rec;
    UInt32          randomNum;
    OSErr           err = noErr;
    
    GetDateTime(&secs);
    SecondsToDate( secs, &rec);
    randomNum = inRandomNum & 0x000000FF;
    if (randomNum == 0)  {
        sprintf(outString, "%02d%02d%02d%02d%02d%02d",
            rec.year > 1999 ? rec.year - 2000 : rec.year - 1900,
            rec.month, rec.day, rec.hour, rec.minute, rec.second);
    }  else  {
        sprintf(outString, "%02d%02d%02d%02d%02d%02d%02d",
            rec.year > 1999 ? rec.year - 2000 : rec.year - 1900,
            rec.month, rec.day, rec.hour, rec.minute, rec.second, randomNum);
    }
}
 
#pragma mark -
 
//-----------------------------------------------------------------------------
//      GetFileContents
//-----------------------------------------------------------------------------
 
OSErr GetFileContents(const FSSpec *inSpec, UInt32 inMaxHandleSize,
                    Handle *outContents, UInt32 *outFileSize)
{
    OSErr       err = noErr;
    short       refNum = kFileNotOpen;
    long        length;
    Handle      myHandle = NULL;
    
    EXITIFERR( err = FSpOpenDF(inSpec, fsRdPerm, &refNum) );
    EXITIFERR( err = GetEOF(refNum, &length) );
    if (outFileSize != NULL)  {
        *outFileSize = length;
    }
    if ((inMaxHandleSize != 0)  &&  (length > (SInt32)inMaxHandleSize))  {
        length = inMaxHandleSize;
    }
 
    myHandle = NewHandle(length);
    EXITIFERR( err = MemError() );
    HLock(myHandle);
    EXITIFERR( err = FSRead(refNum, &length, *myHandle) );
    HUnlock(myHandle);
 
    *outContents = myHandle;
exit:
    if (refNum != kFileNotOpen)  {
        FSClose(refNum);
    }
    if (err != noErr)  {
        DisposeHandle(myHandle);    
    }
    return err;
}
 
//-----------------------------------------------------------------------------
//      MakeFolderIfNecessary
//-----------------------------------------------------------------------------
 
OSErr MakeFolderIfNecessary( short inVRefNum, long inParentDirID, 
                    const StringPtr inName, long *outFolderDirID )
{
    OSErr       err = noErr;
    // try to get info on it
    if (!FolderExists(inVRefNum, inParentDirID, inName, outFolderDirID))  {
        err = DirCreate(inVRefNum, inParentDirID, inName, outFolderDirID);
    }
    return err;
}
 
//-----------------------------------------------------------------------------
//      FolderExists
//-----------------------------------------------------------------------------
 
Boolean FolderExists(const short inVRefNum, const long inParentDirID,
                                const StringPtr inName, long *outFolderDirID)
{
    CInfoPBRec      myCPB;
    OSErr           err;
 
    memset( &myCPB, 0, sizeof(CInfoPBRec) );
    myCPB.dirInfo.ioNamePtr = (StringPtr)inName;    //  ok to use const, since ioFDirIndex == 0
    myCPB.dirInfo.ioVRefNum = inVRefNum;
    myCPB.dirInfo.ioDrDirID = inParentDirID;     
    myCPB.dirInfo.ioFDirIndex = 0;  // to get info about the actual folder itself   
 
    err = PBGetCatInfoSync(  &myCPB );
    *outFolderDirID = myCPB.dirInfo.ioDrDirID;
    return (Boolean)(err == noErr);
}
 
//-----------------------------------------------------------------------------
//      GetAppRelativeFolderSpec
//-----------------------------------------------------------------------------
 
OSErr GetAppRelativeFolderSpec(const StringPtr inFolderName, FSSpec *outFolderSpec)
{
    OSErr       err = noErr;
    FSSpec      mySpec;
 
    if (inFolderName != NULL)  {
        FindThisApplication(&mySpec);
        err = FSMakeFSSpec(mySpec.vRefNum, mySpec.parID, inFolderName, outFolderSpec);
    }  else  {
        FindThisApplication(outFolderSpec);
    }
                
    return err;
}
 
#pragma mark -
 
// ---------------------------------------------------------------------------
//  DialogGetItemHandle
// ---------------------------------------------------------------------------
void DialogSetItemHandle( DialogPtr inDialog, DialogItemIndex inItemIndex, Handle handle)
{
    Handle  temp;
    short   type;
    Rect    rect;
    
    GetDialogItem( inDialog, inItemIndex, &type, &temp, &rect);
    SetDialogItem( inDialog, inItemIndex, type, handle, &rect);
}
 
// ---------------------------------------------------------------------------
//  DialogGetItemHandle
// ---------------------------------------------------------------------------
void DialogGetItemHandle( DialogPtr inDialog, DialogItemIndex inItemIndex, Handle* handle)
{
    short   type;
    Rect    rect;
    
    GetDialogItem( inDialog, inItemIndex, &type, handle, &rect);
}
 
// ---------------------------------------------------------------------------
//  DialogSetControlValue
// ---------------------------------------------------------------------------
void DialogSetControlValue( DialogPtr inDialog, DialogItemIndex inItemIndex, SInt16 value)
{
    Handle  handle;
    short   type;
    Rect    rect;
    
    GetDialogItem( inDialog, inItemIndex, &type, &handle, &rect);
    SetControlValue( (ControlHandle)handle, value);
}
 
// ---------------------------------------------------------------------------
//  DialogGetControlValue
// ---------------------------------------------------------------------------
SInt16 DialogGetControlValue( DialogPtr inDialog, DialogItemIndex inItemIndex)
{
    Handle  handle;
    short   type;
    Rect    rect;
    SInt16  value;
    
    GetDialogItem( inDialog, inItemIndex, &type, &handle, &rect);
    value = GetControlValue( (ControlHandle)handle);
    return value;
}
// ---------------------------------------------------------------------------
//  DialogSetControlTitle
// ---------------------------------------------------------------------------
void DialogSetControlTitle( DialogPtr inDialog, DialogItemIndex inItemIndex, StringPtr title)
{
    Handle  handle;
    short   type;
    Rect    rect;
    
    GetDialogItem( inDialog, inItemIndex, &type, &handle, &rect);
    SetControlTitle( (ControlHandle)handle, title);
}
 
// ---------------------------------------------------------------------------
//  DialogGetControlTitle
// ---------------------------------------------------------------------------
void DialogGetControlTitle( DialogPtr inDialog, DialogItemIndex inItemIndex, StringPtr title)
{
    Handle  handle;
    short   type;
    Rect    rect;
    
    GetDialogItem( inDialog, inItemIndex, &type, &handle, &rect);
    GetControlTitle( (ControlHandle)handle, title);
}
 
// ---------------------------------------------------------------------------
//  DialogSetRadioButton
// ---------------------------------------------------------------------------
void DialogSetRadioButton( DialogPtr inDialog, DialogItemIndex inItemIndex, Boolean enable)
{
    DialogSetCheckBox( inDialog, inItemIndex, enable);
}
 
// ---------------------------------------------------------------------------
//  DialogGetRadioButton
// ---------------------------------------------------------------------------
void DialogGetRadioButton( DialogPtr inDialog, DialogItemIndex inItemIndex, Boolean* enabled)
{
    DialogGetCheckBox(inDialog, inItemIndex, enabled);
}
 
// ---------------------------------------------------------------------------
//  DialogSetCheckBox
// ---------------------------------------------------------------------------
void DialogSetCheckBox( DialogPtr inDialog, DialogItemIndex inItemIndex, Boolean enable)
{
    DialogSetControlValue( inDialog, inItemIndex, (short)(enable? 1: 0));
}
 
// ---------------------------------------------------------------------------
//  DialogGetCheckBox
// ---------------------------------------------------------------------------
void DialogGetCheckBox( DialogPtr inDialog, DialogItemIndex inItemIndex, Boolean* enabled)
{
    SInt16  value;
    
    value = DialogGetControlValue( inDialog, inItemIndex);
    if (value == 0){
        *enabled = false;
    }else{
        *enabled = true;
    }
}
 
// ---------------------------------------------------------------------------
//  DialogSetTextInteger
// ---------------------------------------------------------------------------
void DialogSetTextInteger( DialogPtr inDialog, DialogItemIndex inItemIndex, SInt32 number)
{
    Str63   text;
    
    NumToString( number, text);
    DialogSetText( inDialog, inItemIndex, text, false);     
}
 
// ---------------------------------------------------------------------------
//  DialogGetTextInteger
// ---------------------------------------------------------------------------
SInt32 DialogGetTextInteger( DialogPtr inDialog, DialogItemIndex inItemIndex)
{
    Str63   text;
    SInt32  number;
    
    DialogGetText( inDialog, inItemIndex, text);        
    StringToNum( text, &number);    
    return number;
}
 
// ---------------------------------------------------------------------------
//  DialogSetText
// ---------------------------------------------------------------------------
void DialogSetText(DialogPtr inDialog, DialogItemIndex inItemIndex, StringPtr text, Boolean inSelectText)
{
    Handle  handle;
    short   type;
    Rect    temp;
    
    GetDialogItem( inDialog, inItemIndex, &type, &handle, &temp);
    SetDialogItemText( handle, text);
    if (inSelectText)  {    
        DialogSelectText( inDialog, inItemIndex);
    }   
}
 
// ---------------------------------------------------------------------------
//  DialogGetText
// ---------------------------------------------------------------------------
void DialogGetText( DialogPtr inDialog, DialogItemIndex inItemIndex, StringPtr text)
{
    Handle  handle;
    short   type;
    Rect    temp;
    
    GetDialogItem( inDialog, inItemIndex, &type, &handle, &temp);
    GetDialogItemText( handle, text);       
}
 
// ---------------------------------------------------------------------------
//  DialogSelectText
// ---------------------------------------------------------------------------
void DialogSelectText( DialogPtr inDialog, DialogItemIndex inItemIndex)
{
    SelectDialogItemText( inDialog, inItemIndex, 0, 32767);
}
 
// ---------------------------------------------------------------------------
//  DialogSetItemRect
// ---------------------------------------------------------------------------
void DialogSetItemRect( DialogPtr inDialog, DialogItemIndex inItemIndex, Rect* rect)
{
    Handle  handle;
    short   type;
    Rect    temp;
    
    GetDialogItem( inDialog, inItemIndex, &type, &handle, &temp);
    SetDialogItem( inDialog, inItemIndex, type, handle, rect);
}
 
// ---------------------------------------------------------------------------
//  DialogGetItemRect
// ---------------------------------------------------------------------------
void DialogGetItemRect( DialogPtr inDialog, DialogItemIndex inItemIndex, Rect* rect)
{
    Handle  handle;
    short   type;
    
    GetDialogItem( inDialog, inItemIndex, &type, &handle, rect);
}
 
// ---------------------------------------------------------------------------
//  DialogRefreshItemRect
// ---------------------------------------------------------------------------
void DialogRefreshItemRect( DialogPtr inDialog, DialogItemIndex inItemIndex)
{
    Rect    rect;
    
    DialogGetItemRect( inDialog, inItemIndex, &rect);
#if TARGET_API_MAC_CARBON
    InvalWindowRect( GetDialogWindow(inDialog), &rect);
#else
    InvalRect( &rect);
#endif
}
 
// ---------------------------------------------------------------------------
//  DialogEnableItem
// ---------------------------------------------------------------------------
void DialogEnableItem( DialogPtr inDialog, DialogItemIndex inItemIndex, Boolean enable)
{
    Handle  handle;
    short   type;
    Rect    rect;
    
    GetDialogItem( inDialog, inItemIndex, &type, &handle, &rect);
    if ( handle != NULL){
        HiliteControl( (ControlHandle)handle, (short)(enable? 0: 255));
    }
}
 
// ---------------------------------------------------------------------------
//  DialogShowItem
// ---------------------------------------------------------------------------
void DialogShowItem( DialogPtr inDialog, DialogItemIndex inItemIndex, Boolean show)
{
    if (show){
        ShowDialogItem( inDialog, inItemIndex);
    }else{
        HideDialogItem( inDialog, inItemIndex);
    }
}
 
// ---------------------------------------------------------------------------
//  DialogOffsetControl
// ---------------------------------------------------------------------------
void DialogOffsetControl( DialogPtr inDialog, DialogItemIndex inItemIndex, SInt16 xOffset, SInt16 yOffset)
{
    Rect            rect;
    ControlHandle   control;
    
    DialogGetItemRect( inDialog, inItemIndex, &rect);
    MacOffsetRect( &rect, xOffset, yOffset);
    DialogSetItemRect( inDialog, inItemIndex, &rect);
    DialogGetItemHandle( inDialog, inItemIndex, (Handle*)&control); 
    MoveControl( control, rect.left, rect.top);
}
 
// ---------------------------------------------------------------------------
//  DialogAnimateControl
// ---------------------------------------------------------------------------
void DialogAnimateControl( DialogPtr inDialog, DialogItemIndex inItemIndex)
{
    ControlHandle   handle;
    UInt32          ticks;
    
    DialogGetItemHandle( inDialog, inItemIndex, (Handle*)&handle);
    HiliteControl( handle, kControlButtonPart);
    Delay( 8, &ticks);
    HiliteControl( handle, 0);
}
 
// ---------------------------------------------------------------------------
//  DialogSetControl
// ---------------------------------------------------------------------------
void DialogSetControlProc( DialogPtr inDialog, DialogItemIndex inItemIndex, ControlActionUPP proc)
{
    ControlHandle   control;
    
    DialogGetItemHandle( inDialog, inItemIndex, (Handle*)&control);
    SetControlAction( control, proc);
}
 
// ---------------------------------------------------------------------------
//  DialogSetControlRange
// ---------------------------------------------------------------------------
void DialogSetControlRange( DialogPtr inDialog, DialogItemIndex inItemIndex, SInt16 min, SInt16 max)
{
    ControlHandle   control;
    
    DialogGetItemHandle( inDialog, inItemIndex, (Handle*)&control);
    SetControlMinimum( control, min);
    SetControlMaximum( control, max);
}
 
#pragma mark -
 
typedef struct UserItemRec  {
    long padding1;
    Rect box;
    short padding2;
} UserItemRec;
 
typedef struct DITLRec  {
    short numItems;
    UserItemRec theUserItems[1];
} DITLRec, **DITLHand;
 
 
// ---------------------------------------------------------------------------
//      DITLGetItemRect
// ---------------------------------------------------------------------------
 
void DITLGetItemRect(Handle inDITLHandle, DialogItemIndex inItemIndex, Rect *outRect)
{
    DITLHand        myDitlHandle = (DITLHand)inDITLHandle;
 
    *outRect = (**myDitlHandle).theUserItems[inItemIndex-1].box;
}
 
 
// ---------------------------------------------------------------------------
//      DITLSetItemRect
// ---------------------------------------------------------------------------
 
void DITLSetItemRect(Handle inDITLHandle, DialogItemIndex inItemIndex, Rect *inRect)
{
    DITLHand        myDitlHandle = (DITLHand)inDITLHandle;
 
    (**myDitlHandle).theUserItems[inItemIndex-1].box = *inRect;
}
 
#pragma mark -
 
// ---------------------------------------------------------------------------
//  MenuEnableItem
// ---------------------------------------------------------------------------
void MenuEnableItem( MenuHandle menu, MenuItemIndex index, Boolean enable)
{
    if (enable){
        DisableMenuItem( menu, index);
    }else{
        MacEnableMenuItem( menu, index);
    }
}
 
#pragma mark -
 
//-----------------------------------------------------------------------------
//      FindThisApplication
//-----------------------------------------------------------------------------
// return a File Spec for the current app file
 
static void FindThisApplication(FSSpec *outSpec)
{
    ProcessSerialNumber process;
    ProcessInfoRec      info;
    
    MacGetCurrentProcess(&process);
    
    info.processInfoLength = sizeof(ProcessInfoRec);
    info.processName = nil;
    info.processAppSpec = outSpec;
 
    GetProcessInformation(&process, &info);
}
 
 
 
#pragma mark -
 
#define kMaxDebugFBufferSize        512
 
// ---------------------------------------------------------------------------
//      Logger_New
// ---------------------------------------------------------------------------
 
OSErr Logger_New(const FSSpec *inFileSpec, SInt32 inFlags,
                OSType inFileCreator, OSType inFileType, Logger *outLog)
{
    OSErr       err = noErr;
    Logger      log = NULL;
    
    log = (Logger)QTSNewHandleClear(sizeof(LoggerRecord));
    if (log == NULL)  {
        EXITERR( err = memFullErr );
    }
    EXITIFERR( err = MemError() );
    
    BlockMoveData(inFileSpec, &((**log).fileSpec), sizeof(FSSpec));
    (**log).flags = inFlags;
    (**log).fileRefNum = kFileNotOpen;
    (**log).fileCreator = inFileCreator;
    (**log).fileType = inFileType;
    *outLog = log;
 
exit:
    return err;
}
 
// ---------------------------------------------------------------------------
//      Logger_Dispose
// ---------------------------------------------------------------------------
 
void Logger_Dispose(Logger inLog)
{
    if (inLog != NULL)  {
        if ((**inLog).fileRefNum != kFileNotOpen)  {
            FSClose((**inLog).fileRefNum);
        }
        DisposeHandle((Handle)inLog);
    }
}
 
// ---------------------------------------------------------------------------
//      Logger_OpenFile
// ---------------------------------------------------------------------------
 
OSErr Logger_OpenFile(Logger inLog)
{
    OSErr       err = noErr;
    char        oldState;
    short       refNum = kFileNotOpen;
    long        length = 0;
    
    oldState = HGetState((Handle)inLog);
    HLock((Handle)inLog);
    err = FSpOpenDF(&((**inLog).fileSpec), fsRdWrPerm, &refNum);
    if (err == fnfErr)  {
        EXITIFERR( err = FSpCreate(&((**inLog).fileSpec), (**inLog).fileCreator, (**inLog).fileType, smSystemScript) );
        EXITIFERR( err = FSpOpenDF(&((**inLog).fileSpec), fsRdWrPerm, &refNum) );
    }
        
    EXITIFERR( err = GetEOF(refNum, &length) );
    (**inLog).fileRefNum = refNum;
    (**inLog).fileLength = length;
 
exit:
    HSetState((Handle)inLog, oldState);
    return err;
}
 
// ---------------------------------------------------------------------------
//      Logger_CloseFile
// ---------------------------------------------------------------------------
 
void Logger_CloseFile(Logger inLog)
{
    if ((**inLog).fileRefNum != kFileNotOpen)  {
        FSClose((**inLog).fileRefNum);
        (**inLog).fileRefNum = kFileNotOpen;
    }
}
 
// ---------------------------------------------------------------------------
//      Logger_Write
// ---------------------------------------------------------------------------
 
OSErr Logger_Write(Logger inLog, SInt32 inFlags, const char *inData, UInt32 inLength)
{
    OSErr       err = noErr;
    Boolean     fileWasOpen = true;
    long        count = inLength;
    SInt32      flags = (**inLog).flags | inFlags;
 
    if ((**inLog).fileRefNum == kFileNotOpen)  {
        EXITIFERR( err = Logger_OpenFile(inLog) );
        fileWasOpen = false;
    }
    
    EXITIFERR( err = SetFPos((**inLog).fileRefNum, fsFromLEOF, 0) );
 
    if (flags & kLoggerWriteFlag_AddDateTime)  {
        EXITIFERR( err = Logger_WriteDateTime(inLog) ); 
    }
    
    EXITIFERR( err = FSWrite((**inLog).fileRefNum, &count, inData) );
    
    if (flags & kLoggerWriteFlag_AddEOL)  {
        EXITIFERR( err = Logger_WriteEOL(inLog) );
    }
 
exit:
    if (!fileWasOpen)  {
        Logger_CloseFile(inLog);
    }
    return err;
}
 
// ---------------------------------------------------------------------------
//      Logger_Printf
// ---------------------------------------------------------------------------
 
OSErr Logger_Printf(Logger inLog, SInt32 inFlags, const char *format, ...)
{
    OSErr       err = noErr;
    Boolean     fileWasOpen = true;
    long        count;
    SInt32      flags = (**inLog).flags | inFlags;
    unsigned char buffer[kMaxDebugFBufferSize];
    va_list     ptr;
    
    va_start(ptr, format);
    buffer[0] = (unsigned char)vsprintf((char*)buffer + 1, format, ptr);
    va_end(ptr);
 
    if ((**inLog).fileRefNum == kFileNotOpen)  {
        EXITIFERR( err = Logger_OpenFile(inLog) );
        fileWasOpen = false;
    }
    
    EXITIFERR( err = SetFPos((**inLog).fileRefNum, fsFromLEOF, 0) );
 
    if (flags & kLoggerWriteFlag_AddDateTime)  {
        EXITIFERR( err = Logger_WriteDateTime(inLog) ); 
    }
    
    count = buffer[0];
    EXITIFERR( err = FSWrite((**inLog).fileRefNum, &count, &(buffer[1])) );
    
    if (flags & kLoggerWriteFlag_AddEOL)  {
        EXITIFERR( err = Logger_WriteEOL(inLog) );
    }
 
exit:
    if (!fileWasOpen)  {
        Logger_CloseFile(inLog);
    }
    return err;
}
 
// ---------------------------------------------------------------------------
//      Logger_WriteEOL
// ---------------------------------------------------------------------------
 
OSErr Logger_WriteEOL(Logger inLog)
{
    OSErr       err = noErr;
    Boolean     fileWasOpen = true;
    long        count;
    UInt32      eol;
 
#if TARGET_OS_MAC
    #define kEOL                    0x0d000000
    #define kEOLLength      1
#else
    #define kEOL                    0x0d0a0000
    #define kEOLLength      2
#endif
 
    if ((**inLog).fileRefNum == kFileNotOpen)  {
        EXITIFERR( err = Logger_OpenFile(inLog) );
        fileWasOpen = false;
    }
    
    EXITIFERR( err = SetFPos((**inLog).fileRefNum, fsFromLEOF, 0) );
 
    eol = kEOL;
    count = kEOLLength;
 
    EXITIFERR( err = FSWrite((**inLog).fileRefNum, &count, &eol) );
    
exit:
    if (!fileWasOpen)  {
        Logger_CloseFile(inLog);
    }
    return err;
}
 
// ---------------------------------------------------------------------------
//      Logger_WriteDateTime
// ---------------------------------------------------------------------------
 
OSErr Logger_WriteDateTime(Logger inLog)
{
    OSErr           err = noErr;
    Boolean         fileWasOpen = true;
    long            count;
    UInt32          secs;
    Str255          tempString;
 
    if ((**inLog).fileRefNum == kFileNotOpen)  {
        EXITIFERR( err = Logger_OpenFile(inLog) );
        fileWasOpen = false;
    }
 
    EXITIFERR( err = SetFPos((**inLog).fileRefNum, fsFromLEOF, 0) );
 
    GetDateTime(&secs);
    DateString(secs, shortDate, tempString, NULL);
    pstrcat(tempString, "\p ");
    count = tempString[0];
    EXITIFERR( err = FSWrite((**inLog).fileRefNum, &count, &(tempString[1])) );
 
    TimeString(secs, true, tempString, NULL);
    pstrcat(tempString, "\p - ");
    count = tempString[0];
    EXITIFERR( err = FSWrite((**inLog).fileRefNum, &count, &(tempString[1])) );
 
    
exit:
    if (!fileWasOpen)  {
        Logger_CloseFile(inLog);
    }
    return err;
}
 
static Logger sDebugLog = NULL;
static SInt32 sDebugFlags = kDebugFlag_WriteToLog;
 
// ---------------------------------------------------------------------------
//      SetDebugLog
// ---------------------------------------------------------------------------
 
void SetDebugLog(Logger inLog)
{
    sDebugLog = inLog;
}
 
// ---------------------------------------------------------------------------
//      SetDebugFlags
// ---------------------------------------------------------------------------
 
void SetDebugFlags(SInt32 inFlags, SInt32 inFlagsMask)
{
    sDebugFlags &= ~inFlagsMask;
    sDebugFlags |= (inFlags & inFlagsMask);
}
 
#define DEBUGGER_STR( _pascalStrWithNull)   DebugStr( _pascalStrWithNull);
 
#if USHER_DEBUG
 
// ---------------------------------------------------------------------------
//      samplecodeutilsdebugf
// ---------------------------------------------------------------------------
 
void samplecodeutilsdebugf(const char* format, ...)
{
#if USHER_DEBUG
    unsigned char buffer[kMaxDebugFBufferSize];
    va_list ptr;
    
    va_start(ptr, format);
    buffer[0] = (unsigned char)vsprintf((char*)buffer + 1, format, ptr);
    va_end(ptr);
    
#define kLogDebugPrefix     "<debugf>"  
    if (sDebugFlags & kDebugFlag_WriteToLog)  {
        if (sDebugLog != NULL)  {
            Logger_Write(sDebugLog, kLoggerWriteFlag_AddDateTime,
                        kLogDebugPrefix, strlen(kLogDebugPrefix));
            Logger_Write(sDebugLog, kLoggerWriteFlag_AddEOL,
                        (const char*)&(buffer[1]), buffer[0]);
        }
    }
    if (sDebugFlags & kDebugFlag_DebugStr)  {
        DEBUGGER_STR( buffer);
    }
#else
    #pragma unused(format)
#endif
}
 
#endif