[futurebasic] FSSpecs vs FSRefs

Message: < previous - next > : Reply : Subscribe : Cleanse
Home   : January 2008 : Group Archive : Group : All Groups

From: Ken Shmidheiser <kshmidheiser@...>
Date: Wed, 23 Jan 2008 04:12:12 -0500
With the recent discussions concerning FSSpec vs FSRefs,
I through together a little utility to show how easily interchangeable
they are. At the same time, FSRefs are superior in their
capabilities, although not quite as simple to use as FSSpecs.

To make the best use of this, create a file on your Desktop
with an extremely long name. Using the utility, notice how
much more gracefully FSRefs handle the long name.

This demo also shows different techniques that can be used
to obtain an FSRef depending on whether the code is
compiled as a CFM app with FB, or as a Universal Binary
with gcc via FBtoC.

FBtoC has the very nice capability of directly returning
an FSRef with File$, while FB can only return an FSSpec
with the File$ statement.

Ken


/*

FSSpec vs FSRef File Names Demo

This code shows how easy it is to convert
an FSSpec into an FSRef, and vice versa.

It also shows the superiority of FSRefs in
OS X with their ability to contain long
file names.

This code should compile without error
in either FB or FBtoC. The FB portion
uses the FB File$ statement to capture
an FSSpec, while the FBtoC portion captures
an FSRef. The demo shows how either result
can be converted to the to other and
information extracted-- in this case the
full long file name as opposed to the
name truncated to 31 characters by FB.

To best see this in action, create a file
with a long name-- well in excess of 32
characters, open it with the compiled
program (the code uses two different tech-
niques depending on how whether its compiled
in FB or with gcc via FBtoC. The window
title will remind you of how it was compiled.)

Ken Shmidheiser
January 23, 2008

*/


#if ndef _FBtoC
output file "FSRef_Demo_FB"
#else
output file "FSRef_Demo_FBtoC"
#endif

include "Tlbx Fonts.incl"
include "Tlbx MoreFilesX.incl"
include "Tlbx CFString.incl"

_mainWnd = 1

begin enum 1
_fsName
_frName
_fsChar
_frChar
_quitBtn
_fileBtn
_cStat
_c1Stat
_c2Stat
_c3Stat
_cSep
_c1Sep
end enum


local fn BuildWindow
dim as Str255             s
dim as ControlFontStyleRec   tfs
dim as Rect               r
dim as WindowAttributes      wa
'~'1

wa = _kWindowCloseBoxAttribute¬
      _kWindowCollapseBoxAttribute

def NewWindowPositionMethod( _kWindowAlertPositionOnMainScreen )
SetRect( r, 336, 136, 816, 496 )

#if ndef _FBtoC
s = "FSSpec vs FSRef—Source compiled in FutureBASIC"
#else
s = "FSSpec vs FSRef—Source compiled in gcc with FBtoC"
#endif

appearance window -_mainWnd, s, @r, _kDocumentWindowClass, wa
def NewWindowPositionMethod( 0 )
def SetWindowBackground( _kThemeActiveDialogBackgroundBrush, _zTrue )


SetRect( r, 23, 49, 457, 65 )
appearance button _fsName,,,,,, @r, _kControlEditTextProc

SetRect( r, 23, 159, 457, 244 )
appearance button _frName,,,,,, @r, _kControlEditTextProc

SetRect( r, 393, 76, 457, 92 )
appearance button _fsChar,,,,,, @r, _kControlEditTextProc

SetRect( r, 393, 258, 457, 274 )
appearance button _frChar,,,,,, @r, _kControlEditTextProc

SetRect( r, 390, 315, 460, 335 )
appearance button _quitBtn,,,,, "Quit", @r, _kControlPushButtonProc

SetRect( r, 261, 315, 378, 335 )
s = "Open File..."
appearance button _fileBtn,,,,, s, @r, _kControlPushButtonProc

SetRect( r, 20, 20, 460, 41 )
appearance button _cStat,,,,,, @r, _kControlStaticTextProc
s = "File name with FSSpec (31 character maximum):"
def SetButtonTextString( _cStat, s )

SetRect( r, 181, 76, 385, 92 )
appearance button _c1Stat,,,,,, @r, _kControlStaticTextProc
tfs.flags = _kControlUseJustMask
tfs.just = _teJustRight
def SetButtonFontStyle( _c1Stat, tfs )
s = "File name length with FSSpec:"
def SetButtonTextString( _c1Stat, s )

SetRect( r, 20, 130, 460, 151 )
appearance button _c2Stat,,,,,, @r, _kControlStaticTextProc
s = "File name with FSRef (254 character maximum):"
def SetButtonTextString( _c2Stat, s )

SetRect( r, 181, 258, 385, 274 )
appearance button _c3Stat,,,,,, @r, _kControlStaticTextProc
tfs.flags = _kControlUseJustMask
tfs.just = _teJustRight
def SetButtonFontStyle( _c3Stat, tfs )
s = "File name length with FSRef:"
def SetButtonTextString( _c3Stat, s )

SetRect( r, 19, 112, 460, 122 )
appearance button _cSep,,,,,, @r, _kControlSeparatorLineProc

SetRect( r, 19, 285, 460, 295 )
appearance button _c1Sep,,,,,, @r, _kControlSeparatorLineProc

appearance window _mainWnd

end fn


local fn GetLongFileNameFromFSRef$( fsRef as ^FSRef )
dim as str255      @ name
dim as HFSUniStr255    hsfName
dim as CFStringRef     cfStr
dim as OSErr           err
dim as boolean       result
'~'1

err = fn FSGetCatalogInfo( #fsRef, _kFSCatInfoNone, #0, hsfName, #0, #0)
if err then stop "FSGetCatalogInfo Error:" + str$( err )
long if ( err == _noErr )
cfStr = fn CFStringCreateWithCharacters( 0,¬
hsfName.unicode[0], hsfName.length )
long if ( cfStr )
result = fn CFStringGetPascalString( cfStr,¬
@name, sizeof( name ), _kCFStringEncodingMacRoman )
CFRelease( cfStr )
end if
end if

end fn = name


local fn UserCanceled
def SetButtonTextString ( _fsName, "User canceled" )
def SetButtonTextString ( _frName, "User canceled" )
def SetButtonTextString ( _fsChar, "" )
def SetButtonTextString ( _frChar, "" )
end fn


local fn FillFields( specName as str255, refName as str255 )
dim as str255 s
'~'1

s = specName
def SetButtonTextString ( _fsName, s )

s = str$( s[0] )
def SetButtonTextString ( _fsChar, s )

s = refName
def SetButtonTextString ( _frName, s )

s = str$( s[0] )
def SetButtonTextString ( _frChar, s )


end fn


local fn DoFileFind
dim as str255  fileName, s
dim as FSSpec   fs
dim as FSRef    fsRef
dim as OSErr    err
'~'1

#if ndef _FBtoC

s = "Get file FSSpec in FB"
fileName = files$( _FSSpecOpen,, s, fs )
long if ( fileName[0] )
// Convert FSSpec to FSRef
err = fn FSpMakeFSRef( #fs, @fsRef)
s = fn GetLongFileNameFromFSRef$( fsRef )
fn FillFields( fs.name, s )
xelse
fn UserCanceled
end if

#else

s = "Get file FSRef in FBtoC"
fileName = files$( _FSRefOpen,, s, fsRef )
long if fileName[0]
// Convert FSRef to FSSpec
err = fn FSGetCatalogInfo ( fsRef, 0, #0, #0, fs, #0 )
s = fn GetLongFileNameFromFSRef$( fsRef )
fn FillFields( fs.name, s )
xelse
fn UserCanceled
end if

#endif


end fn


local fn DoDialog
dim as long ev, id
'~'1

ev = dialog( 0 )
id = dialog( ev )

select ev
case _wndClick     : window id
case _wndClose     : end
case _btnClick
select window( _outputWnd )
case _mainWnd
select id
case _quitBtn   : end
case _fileBtn   : fn DoFileFind
end select
end select
end select

end fn

on dialog fn DoDialog

fn BuildWindow

do
HandleEvents
until gFBQuit