[futurebasic] OS X Word Finder

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

From: Ken Shmidheiser <kshmidheiser@...>
Date: Sun, 3 Nov 2002 18:29:04 -0500
Here's a little OS X 10.x utility that explores an FB^3-generated
Aqua GUI interface on a Unix utility and database. The
forward/reverse button handling could stand some work-- suggestions
invited.

Let me know what you think. Bug reports, criticisms, comments welcomed.

Ken

p.s. Please watch for e-mail line breaks and lost constant
underscores on the Associate server.

/*

    OS X Word Finder

    A obscure piece of OS X trivia is that each
    version ships with a list of all the words
    in Webster's 2nd International Dictionary
    (234,936 of them to be precise).

    This little utility allows you to search
    that database by entering at least three
    characters from any word. (Searching for
    one- or two letter- combinations is possible,
    but unwieldly.) OS X Word Finder returns all
    the words that contain the letter combination
    entered. OS X Word Finder uses the Unix "grep"
    utility to parse its response into an array.
    The operation is extremely quick.

    Example: Entering the letters "ine"
    returns a list of 5,384 words containing
    that three-letter combination.

    I wrote this as an exercise to combine
    Unix functions with a pleasant FB^3 GUI.

    Due to FB^3's 32K edit field size limitation,
    lists in excess of 500 words are displayed
    500 at a time.

    Ken Shmidheiser
    Somerset, KY

    11-3-02

*/

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

output file "OS X Word Finder"

begin globals
dim dynamic      dictStr( _maxLong ) as str63
dim as container gC
dim as integer   gDirection
end globals

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

local fn BuildMenus

apple menu "About OS X Word Finder"

menu 1, 0, _enable, "File"
menu 1, 1, _enable, "Find word"

gFBEditSelectAll = _zTrue
edit menu 2

end fn

local fn AboutWindow
dim as str255 infoStr
dim as rect   r

setrect( r, 0, 0, 250, 160 )
appearance Window -2, "About Word Finder", @r,¬
_kDocumentWindowClass, _kWindowStandardFloatingAttributes
def SetWindowBackground( _kThemeActiveDialogBackgroundBrush,_zTrue)

text _sysFont, 16, _boldbit%, _srcCopy
color _zRed
setrect( r, 20, 20, 230, 60 )
edit field -10,, @r, _statNoFramed,_centerJust

infoStr = CHR$(13) + "OS X Word Finder" + CHR$(13)

edit$(10) = infoStr

text _applFont, 12, 0,_srcCopy
setrect( r, 20, 70, 230, 140 )
color _zBlack
edit field -11,, @r, _statNoFramed,_centerJust

infoStr = +"Coded in FB^3 by Ken Shmidheiser" + CHR$(13)¬
+ "Somerset, KY" + CHR$(13) + "November 3, 2002"

edit$(11) = infoStr

def windowreposition( 2, 1, _kWindowAlertPositionOnParentWindowScreen )

window 2

end fn

local fn AlphaFilter
dim as str15 keyStr
dim as str63 testStr

keyStr  = tekey$
testStr = edit$(9)

long if testStr[0] < 26

long if testStr[0] < 25// enable alpha keys
IF keyStr >= "a" and keyStr<= "z" then tekey$ = keyStr
IF keyStr >= "A" and keyStr<= "Z" then tekey$ = keyStr
end if

select case asc ( keyStr )
case 28, 29// enable arrow keys
tekey$ = keyStr
case 8, 127// enable delete keys
tekey$ = keyStr
end select

xelse
beep
end if

end fn

local fn BuildWindow
dim as pointer @ filterFN
dim as rect      r

setrect( r, 0, 0 , 450, 340 )
appearance Window -1, "OS X Word Finder", @r,¬
_kDocumentWindowClass, _kWindowStandardFloatingAttributes

def SetWindowBackground(_kThemeActiveDialogBackgroundBrush,_zTrue)

edit = 4
text _monaco, 12
setrect( r, 242, 15, 430, 30)
edit field 8,"Enter 3 or more letters:",@r,_statNoFramed,_leftJust

setrect( r, 245, 40, 430, 55)
filterFN = @fn AlphaFilter
edit field 9, "", @r, _framedNoCr, _leftJust, filterFN

setrect( r, 20, 20, 214, 280)
edit field 10,"",@r,_copyOnlyFramed,_leftJust
setrect( r, 214, 16, 230, 284)
scroll button -10,0,0,0,0, @r, _scrollOther

setrect( r, 240, 70, 430, 105)
edit field 11,"",@r,_statNoFramed,_leftJust

setrect( r, 340, 300, 435, 320)
button 1, 1, "Find word", @r, _shadow

setrect( r, 20, 300, 120, 320)
appearance button 2, 1, 0, 0, 1, "<‹ Previous 500",¬
@r, _kControlBevelButtonSmallBevelProc

setrect( r, 130, 300, 230, 320)
appearance button 3, 1, 0, 0, 1, "Next 500 ‹>",¬
@r, _kControlBevelButtonSmallBevelProc

appearance button -2
appearance button -3

edit field 9

window 1

end fn

local fn FindDictionaryWords( wordStr as str63 )
dim as str255  wStr
dim as integer i

wStr = "grep " + wordStr + " /usr/share/dict/words"

i = 0
OPEN "UNIX", 2, wStr
DO
LINE INPUT #2, wStr
dictStr(i) = wStr
i++
UNTIL EOF (2)
CLOSE  2

compress dynamic dictStr

end fn

local fn GetWord
dim as integer i, j, checkNum, numWords

checkNum  = len( Edit$(9) )
edit$(10) = ""

long if checkNum < 3
edit$(11) = "Please enter at least three letters"
exit fn
end if

kill dynamic dictStr
gC = ""

fn FindDictionaryWords( edit$(9) )

numWords = fn UBound( dictStr )

long if numWords = 0
edit$(11) = "No words found."
xelse
edit$(11) = str$( numWords) + " words found"
end if

end fn = numWords

local fn ForwardReverse( whichWay as str15 )
dim as integer i, a, b

a = 0 : b = 0

appearance button 2

select case whichWay
case "reverse" : gDirection--
case "forward" : gDirection++
end select

if gDirection =<  1 then gDirection =  1
if gDirection => 16 then gDirection = 16

if gDirection =  1 then a =    1 : b =  499 : appearance button -2
if gDirection =  2 then a =  501 : b =  999
if gDirection =  3 then a = 1000 : b = 1499
if gDirection =  4 then a = 1500 : b = 1999
if gDirection =  5 then a = 2000 : b = 2499
if gDirection =  6 then a = 2500 : b = 2999
if gDirection =  7 then a = 3000 : b = 3499
if gDirection =  8 then a = 3500 : b = 3999
if gDirection =  9 then a = 4000 : b = 4499
if gDirection = 10 then a = 4500 : b = 4999
if gDirection = 11 then a = 5000 : b = 5499
if gDirection = 12 then a = 5500 : b = 5999
if gDirection = 13 then a = 6000 : b = 6499
if gDirection = 14 then a = 6500 : b = 6999
if gDirection = 15 then a = 7000 : b = 7499
if gDirection = 16 then a = 7500 : b = 8000

gC = ""
for i = a to b
gC += dictStr(i) + chr$(13)
next i

edit$( 10) = #gC
long if len(gC) = 500
gDirection = gDirection
appearance button -3
xelse
appearance button 3
end if

gC = ""

edit field 0

end fn

local fn HandleWords
dim as integer i, numWords

gDirection = 0

numWords = fn GetWord

long if numWords < 500
for i = 0 to numWords
gC += dictStr(i) + chr$(13)
next i
appearance button -2
appearance button -3
edit$( 10 ) = #gC
kill dynamic dictStr
gC = ""
xelse
for i = 0 to 500
gC += dictStr(i) + chr$(13)
next i
appearance button 3
edit$( 10, _maxInt, _maxInt ) = #gC
gC = ""
gDirection = 1
end if

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
case 2 : window close 2
end select
case _btnClick
select( id )
case 1 : fn HandleWords
case 2 : fn ForwardReverse( "reverse" )
case 3 : fn ForwardReverse( "forward" )
end select
case _efReturn
select( id )
case 9 : fn HandleWords
end select
end select

end fn

local fn DoMenu
dim as long menuID, itemID

menuID = menu(_menuID)
itemID = menu(_itemID)

select case( menuID )
case _applemenu
select( itemID )
case 1 : fn AboutWindow
end select
case 1
select( itemID )
case 1 : fn HandleWords
end select
end select
menu

end fn

on dialog fn DoDialog
on menu   fn DoMenu

fn BuildMenus
fn BuildWindow

do
handleevents
until gFBQuit
end