[futurebasic] Re: Empty array resource

Message: < previous - next > : Reply : Subscribe : Cleanse
Home   : November 2002 : Group Archive : Group : All Groups

From: Ken Shmidheiser <kshmidheiser@...>
Date: Thu, 7 Nov 2002 08:34:09 -0500
First of all, thanks to Heather, Alain and Robert C. for their input.

Robert, probably the reason for your crash was the open "unix"
function which has nowhere to go on a PPC in Classic.

Heather, thanks for catching my array bounds error caused by the
integer where an unsigned long was needed. You were right, I was
simply trying to build a resource inside the application, after which
I was going to strip it out and use it in my spell-checking app. (I
have never been successful in creating an external resource to hold
an array, hence the my reason for going internal any my aversion to
the external. As you will see below, I continue to hit 1000 in this
area.) Even after building an application with your modified code, I
was unable to duplicate your results here. The resource remained
empty. I really hoped it would work just to allow me to continue with
some tests here. Concerning the resource limitations you mentioned,
the late Phil Yates once helped me build a really huge array resource
that functioned perfectly. Perhaps someone else on the list knows the
practical limitation.

Heather, when you wrote:

>I'd suggest saving to a data file using the Read & Write Dynamic functions.
>Since this is a Mac OS X only application, you also might make it a
>self-contained bundled app to encapsulate the data file.

I'm sure you are right, but I don't know how to create a
self-contained bundled app with the data file built into it.

Alain, thanks for your include code. Alas, it creates an external
array with an empty resource. I have included my rewritten version
below-- I converted some IFs to LONG IFs trying to take into account
line breaks. As usual, I expect the Associate server will strip off
my constant underscores, but they should appear in the e-mail
version. I have bookmarked the spot at which the code fails. I do
know that the array is properly build and can be displayed as tested.
It just never makes it to the resource.

Perhaps you will be able to help me correct the error of my ways.

I am very discouraged that I have never been able to master the art
of creating an array resource. I had hoped the new functions such as
USR REPLACERESOURCE would help, but I'm as stuck as ever.

Thanks again for the help.

Ken


#if ( CarbonLib == 0 ) or ( ndef _appearanceRuntime )
compile shutdown "Must be compiled as Appearance Compliant with Carbon"
#endif

dim system 20000000

DEF FN UBound(@P AS PTR) = [P + _AutoXREFCurr] - 1

#if 0
'~';
Resource<->Arrays.incl  (rev. 1)
by Alain Pastor & Jay reeve
August 19, 2001
'~';
#endif
'~';
goto "End Resource<->Arrays.incl"
#if CarbonLib
local fn WDRefNumToFSSpec( inName as str63,¬
inWDRefNum as short, outFSSpec as ^FSSpec )
/*
Convert inName and wdRefNum to a FSSpec.
If inName is the null-string, the FSSpec is for a folder.
In Carbon, inWDRefNum is an FB-simulated wdRefNum.
*/
dim err as OSErr
if ( outFSSpec == 0) then err = _paramErr : exit fn
#if CarbonLib // simulated wdRefNum
inWDRefNum -= _FBWDStartNum
long if ( inWDRefNum >= 0 ) and ( inWDRefNum < _FBWDListSize )
outFSSpec.vRefNum = gFMWDVolList%(inWDRefNum)
outFSSpec.parID   = gFMWDDirList&(inWDRefNum)
outFSSpec.name    = inName
err = _noErr
xelse
err = _fnfErr
end if
#else // "real" wdRefNum
err = fn FSMakeFSSpec( inWDRefNum, 0, inName, #outFSSpec )
#endif
end fn = err
#endif
'~';
local fn DynaToRsrc(@HndlPtr as ptr,fileName$,RsrcName$)
dim as short  oldRef,resRef,&,tempID
dim as handle oldResH
dim as long   hSize
dim as FSSpec fSpec

if HndlPtr.0& = _nil¬
then stop "No handle in FN DynaToRsrc":Exit fn
hSize = fn GetHandleSize(HndlPtr.0&)
SetHandleSize(HndlPtr.0&,hSize + 8)
blockmove(HndlPtr+_AutoXREFCurr,[HndlPtr.0&]+hSize,8)

oldRef = fn CurResFile
long if fileName$[0]
#if CarbonLib = 0
fSpec.name    = fileName$
fSpec.vRefNum = system(_aplVol)
fSpec.parID   = 0
#else
long if fn WDRefNumToFSSpec( fileName$, system(_aplVol), fSpec )
stop "Unable to convert wdRefNum¬
  to FSSpec in FN DynaToRsrc" : exit fn
end if
#endif
resRef = fn FSpOpenResFile(fSpec,_fsRdWrPerm)
long if resRef < 0
FSpCreateResFile(fSpec,_"RSED",_"rsrc",_nil)
long if fn ResError = _noErr
resRef = fn FSpOpenResFile(fSpec,_fsRdWrPerm)
long if resRef < 0
stop "Can't open Rsrc file in FN DynaToRsrc"
exit fn
end if
xelse
stop "Unable to create resFile in FN DynaToRsrc"
exit fn
end if
end if
xelse
resRef = system(_aplRes)
end if
UseResFile(resRef)
SetResLoad(_false)
tempID = FN Unique1ID(_"DYNA")
AddResource(HndlPtr.0&,_"DYNA",tempID,RsrcName$)
long if fn ResError = _noErr
oldResH = fn Get1Resource(_"DYNA",128)
Long if oldResH
RmveResource(oldResH)
long if fn ResError
RmveResource(HndlPtr.0&)
exit "DynaToRsrc exit"
end if
end if
SetResInfo(HndlPtr.0&,128,#_nil)
SetResAttrs(HndlPtr.0&,_resPurgeable%)
ChangedResource(HndlPtr.0&)
WriteResource(HndlPtr.0&)
UpdateResFile(resRef)
DetachResource(HndlPtr.0&)
end if
"DynaToRsrc exit"
SetResLoad(_true)
UseResFile(oldRef)
long if oldRef != resRef and resRef != system(_aplRes)
CloseResFile(resRef)
end if
end fn

'~';
local fn RsrcToDyna(@HndlPtr as ptr,FileName$,RsrcName$)
dim as short  oldRef,resRef
dim as long   hSize
dim as FSSpec fSpec

oldRef = fn CurResFile
long if fileName$[0]
#if CarbonLib = 0
fSpec.name    = FileName
fSpec.vRefNum = system(_aplVol)
fSpec.parID   = 0
#else
long if fn WDRefNumToFSSpec( fileName$, system(_aplVol), fSpec )
stop "Unable to convert wdRefNum to FSSpec in FN RsrcToDyna"
exit fn
end if
#endif
resRef = fn FSpOpenResFile(fSpec,_fsRdWrPerm)
long if resRef < 0
print "Unable to open resfile in FN RsrcToDyna"
exit fn
end if
xelse
resRef = system(_aplRes)
end if
UseResFile(resRef)
HndlPtr.0& = fn GetNamedResource(_"DYNA",RsrcName)
long if HndlPtr.AutoXREFHndl&
DetachResource(HndlPtr.AutoXREFHndl&)
hSize = fn GetHandleSize(HndlPtr.AutoXREFHndl&) - 8
HndlPtr.AutoXREFCurr&;8 = [HndlPtr.AutoXREFHndl&] + hSize
SetHandleSize(HndlPtr.AutoXREFHndl&,hSize)
end if
UseResFile(oldRef)
long if oldRef != resRef and resRef != system(_aplRes)
CloseResFile(resRef)
end if
end fn

'~';
local fn CtnrToRsrc(@HndlPtr as ptr,fileName$,RsrcName$)
dim as short  oldRef,resRef,&,tempID
dim as handle oldResH
dim as FSSpec fSpec

HndlPtr.0& = HndlPtr.0&
long if HndlPtr.0& = 0
stop "No handle in FN CtnrToRsrc"
Exit fn
end if
oldRef = fn CurResFile
long if fileName$[0]
#if CarbonLib = 0
fSpec.name    = fileName$
fSpec.vRefNum = system(_aplVol)
fSpec.parID   = 0
#else
long if fn WDRefNumToFSSpec( fileName$, system(_aplVol), fSpec )
stop "Unable to convert wdRefNum to FSSpec in FN CtnrToRsrc"
exit fn
end if
#endif
resRef = fn FSpOpenResFile(fSpec,_fsRdWrPerm)
long if resRef < 0
FSpCreateResFile(fSpec,_"RSED",_"rsrc",_nil)
long if fn ResError = _noErr
resRef = fn FSpOpenResFile(fSpec,_fsRdWrPerm)
long if resRef < 0
stop "Can't open Rsrc file in FN CtnrToRsrc"
end if
exit fn
xelse
stop "Unable to create resFile in FN CtnrToRsrc"
exit fn
end if
end if
xelse
resRef = system(_aplRes)
end if
UseResFile(resRef)
SetResLoad(_false)
tempID = FN Unique1ID(_"CTNR")
AddResource(HndlPtr.0&,_"CTNR",tempID,RsrcName$)
long if fn ResError = _noErr
oldResH = fn Get1Resource(_"CTNR",128)
Long if oldResH
RmveResource(oldResH)
long if fn ResError
RmveResource(HndlPtr.0&)
exit "CtnrToRsrc exit"
end if
end if
SetResInfo(HndlPtr.0&,128,#_nil)
SetResAttrs(HndlPtr.0&,_resPurgeable%)
ChangedResource(HndlPtr.0&)
WriteResource(HndlPtr.0&)
UpdateResFile(resRef)
DetachResource(HndlPtr.0&)
end if
"CtnrToRsrc exit"
SetResLoad(_true)
UseResFile(oldRef)
long if oldRef != resRef and resRef != system(_aplRes)
CloseResFile(resRef)
end if
end fn

'~';
local fn RsrcToCtnr(@HndlPtr as ptr,FileName$,RsrcName$)
dim as short  oldRef,resRef
dim as FSSpec fSpec

oldRef = fn CurResFile
long if FileName$[0]
#if CarbonLib = 0
fSpec.name    = FileName$
fSpec.vRefNum = system(_aplVol)
fSpec.parID   = 0
#else
long if fn WDRefNumToFSSpec( FileName$, system(_aplVol), fSpec )
stop "Unable to convert wdRefNum to FSSpec in FN RsrcToCtnr"
exit fn
end if
#endif

resRef = fn FSpOpenResFile(fSpec,_fsRdWrPerm)
long if resRef < 0
print "Unable to open resfile in FN RsrcToCtnr"
exit fn
end if
xelse
resRef = system(_aplRes)
end if
UseResFile(resRef)
HndlPtr.0& = fn GetNamedResource(_"CTNR",RsrcName)
long if HndlPtr.0&
DetachResource(HndlPtr.0&)
end if
UseResFile(oldRef)
long if oldRef != resRef and resRef != system(_aplRes)
CloseResFile(resRef)
end if
end fn

'~';
"End Resource<->Arrays.incl"
// DEMO ROUTINE
'~';
local fn BuildWindow
dim as rect  r
dim as str63 infoStr

infoStr = "Press button to build array resource."

setrect( r, 0, 0, 400, 250)
appearance Window -1, "Build SoundexDict Array", @r,¬
_kDocumentWindowClass, _kWindowStandardFloatingAttributes

def SetWindowBackground( _kThemeActiveDialogBackgroundBrush,_zTrue)

setrect( r, 20, 20, 364, 190)
edit field -10, infoStr, @r,_copyOnlyframed,_leftJust
setrect( r, 364, 20, 380, 190)
scroll button -10,0,0,0,0, @r, _scrollOther

setrect( r, 260, 210, 380, 230)
button 1,1,"Build array",@r,_shadow
window 1

end fn

begin globals
dim dynamic  dictStrArray( _maxLong ) as str63
dim as str63 gResNameStr
end globals

LOCAL MODE
_soundexNil$ = "0000"
LOCAL FN Soundex$( codeWord AS STR255 )
DIM AS LONG          i,u
DIM AS UNSIGNED CHAR charCode,lastCode
DIM AS STR31         outputStr

outputStr = _soundexNil$
IF codeWord[0] = _nil THEN EXIT FN
UppercaseStripDiacritics(@codeWord[1],¬
codeWord[0],_smCurrentScript)
outputStr[1] = codeWord[1]
charCode     = outputStr[1] : GOSUB "getSoundexCode"
lastCode     = charCode
i = 1 : u = 1
WHILE i <= codeWord[0]
i++ : charCode = codeWord[i] : GOSUB "getSoundexCode"
LONG IF charCode > 0 AND lastCode <> charCode
u++ : outputStr[u] = charCode
IF u = 4 THEN EXIT WHILE
END IF
lastCode = charCode
WEND
EXIT FN
"getSoundexCode"
SELECT charCode
CASE _"B", _"F", _"P", _"V"
charCode = _"1"
CASE _"C", _"G", _"J", _"K", _"Q", _"S", _"X", _"Z"
charCode = _"2"
CASE _"D", _"T"
charCode = _"3"
CASE _"L"
charCode = _"4"
CASE _"M", _"N"
charCode = _"5"
CASE _"R"
charCode = _"6"
CASE ELSE
charCode = 0
END SELECT
RETURN
END FN = outputStr

local fn BuildDictionaryArray
dim as str255  wStr, soundexStr
'Date { 11/6/02 } H.D. changed integer to unsigned long
dim as unsigned Long i
wStr = "cat " + " /usr/share/dict/words"

i = 0
OPEN "UNIX", 2, wStr
DO
LINE INPUT #2, wStr
soundexStr = fn Soundex$( wStr)
dictStrArray(i) = soundexStr + wStr
i++
UNTIL EOF (2)
CLOSE  2

compress dynamic dictStrArray
end fn

local fn BuildResourceArray
dim as unsigned Long i, arraySize

//gResFileName = ""'to store in the resource fork of the app
gResNameStr = "soundexDict.rsrc"

edit$(10) = "Building Soundex Dictionary array..."¬
+ chr$(13) + "It takes several minutes to index 230,000-plus words"¬
+ chr$(13) + chr$(13)

// Build the dynamic array
fn BuildDictionaryArray

// Test for max elements
arraySize = fn UBound( dictStrArray )

edit$(10, _maxInt, _maxInt ) =¬
  "The array has:" + str$(arraySize) + " elements." + chr$(13)¬
  + chr$(13) + "The first 50 elements are:" + chr$(13)

// Show first 50 elements in array
for i = 1 to 50
edit$(10, _maxInt, _maxInt ) =¬
  dictStrArray(i) + chr$(13)
next i

edit$(10, _maxInt, _maxInt ) = chr$(13)¬
+ "The last 50 elements are:" + chr$(13)

// Show last 50 elements in array
for i = arraySize - 50 to arraySize
edit$(10, _maxInt, _maxInt ) = dictStrArray(i) + chr$(13)
next i

edit$(10, _maxInt, _maxInt ) = chr$(13)¬
+ "Building DATA resource array..." + chr$(13)

// Using Alain and Jay's include, place array
// into resource named "soundexWordArray"
fn DynaToRsrc( dictStrArray, gResNameStr, "soundexWordArray" )

edit$(10, _maxInt, _maxInt ) = chr$(13)¬
+ "DATA resource array is completed..." + chr$(13)¬
+ "...and dynamic array has been discarded."

// Empty dynamic array
kill dynamic dictStrArray

edit$(10, _maxInt, _maxInt ) = chr$(13)¬
+ "Rebuilding array using resource information..."

// Refill dynamic array from resouurce file
fn RsrcToDyna( dictStrArray, gResNameStr," soundexWordArray")

'~Resource array is never built
'~so the following tests fail

/*
// Test for max elements in array from resource
arraySize = fn UBound( dictStrArray )

edit$(10, _maxInt, _maxInt ) =¬
  "The rebuilt array has:" + str$(arraySize) + " elements."¬
+ chr$(13) + chr$(13) + "The first 50 elements are:" + chr$(13)

// Show first 50 elements in array from resource
for i = 1 to 50
edit$(10, _maxInt, _maxInt ) =¬
  dictStrArray(i) + chr$(13)
next i

edit$(10, _maxInt, _maxInt ) = chr$(13)¬
+ "The last 50 elements are:" + chr$(13)

// Show last 50 elements in array from resource
for i = arraySize - 50 to arraySize
edit$(10, _maxInt, _maxInt ) = dictStrArray(i) + chr$(13)
next i
*/

// Empty dynamic array
kill dynamic dictStrArray


edit$(10, _maxInt, _maxInt ) = chr$(13)¬
+ "DATA array build complete." + chr$(13)¬
+ chr$(13) + "Close window or Quit to end."¬
+ chr$(13) + chr$(13) + chr$(13) + chr$(13)

end fn

local fn DoDialog
dim as long evnt, id

evnt = dialog(0)
id = dialog(evnt)

select case( evnt )
case _wndClose
select( id )
case 1 :  gFBQuit = _zTrue
end select
case _btnClick
select( id )
case 1
fn BuildResourceArray
end select
end select

end fn

on dialog fn DoDialog

fn BuildWindow

do
handleevents
until gFBQuit
end