[futurebasic] Re: Edit Field Search

Message: < previous - next > : Reply : Subscribe : Cleanse
Home   : May 2003 : Group Archive : Group : All Groups

From: Ken Shmidheiser <kshmidheiser@...>
Date: Mon, 12 May 2003 00:09:36 -0400
Craig Hoyt asked:

>I was surprised to see the amount of posts generated by my 'days between
>dates' question and reply. I agree with those who favor the formula method
>over the counting method. There are too many exception handling in the
>counting method to make it practical. Those who need to understand the
>formula are making their life more complicated. I tested it and it worked!
>I don't fully understand it but it works. That's good enough for me.


For the list skeptics (I admit this may add to the skepticism) I have
located a discussion of the algorithm used in the day difference
function I posted here. I translated several Julian Date functions
from Pascal, C and several variations of BASIC, but this one-- a
modified Julian Date function which sees use by astronomers-- seemed
the most robust. Here goes:

http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/Q109/4/51.asp&NoWebContent=1

Note the innuendo in difference between VB's implementation of INT
compared with FB^3's FIX. I hope my translation proves accurate. It's
possible that the function input variables should be redimensioned to:

local fn AstroDay#( inyear as long, inmonth as int, inday as double )

For those who prefer counting vs algorithm, please don't slay me, I'm
just the messenger! Michael Evans offered a fine solution.

I do feel that Craig's implementation, while just fine for his
purposes, does severely limit the range of the AstroDay algorithm.

Alain can read my mind, because both samples are going into the
Rosetta Stone Library giving us an equivalent to VB's datefiff
function.

At any rate, after a quiet few months, I'm very happy to see some
excellent code being posted here.


>I have another question... Below is a function taken from the search edit
>field example on the r7 CD. I am having a hard time wrapping my mind around
>parts of this function. I created a similar routine to search an edit field
>using the munger function. I wanted to have my search case insensitive so I
>too transformed both the TEHandle and the search string. My problem is that
>converting the TEHandle to upper case and then applying the munger function
>changes the entire contents of the edit field to upper case. In the example
>below the TEHandle is transformed to UC as mine is but then transferred to
>the pointer upTxtHP. The munger function is applied to the TEHandle and not
>the upTxtHP. I'm confused. Can anyone adapt this function to; A) not use a
>passed pointer (or handle) and B) not change the case of the contents of
>the edit field the same way as the example does.


I don't have much time, so I just cut and pasted the following demo
which allows a user to open a text file into an edit field and do a
search and replace on the handle. Perhaps you can get a few ideas
from it. (Note: Fn HandleSearchAndReplace)

I wrote this in a couple hours last year as an experimental GUI for a
project I was working on. It seems fairly robust, but watch for bugs.

Best,

Ken

please watch for lost constant underscores on the Associate server


#if cpu68K
compile shutdown "Requires PPC or Carbon Compile"
#endif

begin globals
// Create containers to hold undo data
dim as container gOriginalC, gRevisedC
dim as boolean   gUndoFlag
end globals

// Initialize containers to hold text
gOriginalC = ""
gRevisedC  = ""

// Enumerate edit field and control constants
begin enum 1
_oldStrLabelEF
_newStrLabelEF
_oldStrEF
_newStrEF
_mainEF
_errorEF
_openBtn
_replaceBtn
_saveBtn
end enum

// Turn on new navigation services
gFBUseNavServices = _zTrue

// Build menus
local fn BuildMenus

apple menu "(Demo..."

menu 1, 0, _enable,  "File"
menu 1, 1, _enable,  "Open/O"
menu 1, 2, _enable,  "Replace/R"
menu 1, 3, _disable, "-"
menu 1, 4, _enable,  "Save/S"
menu 1, 5, _disable, "-"
menu 1, 6, _enable,  "Close"

// Enable Select All in Edit menu
gFBEditSelectAll = _zTrue

// FB^3's own Edit menu set as 2
edit menu 2

// Enable "Undo" in Edit menu
menu 2, 1, _enable

end fn

// Create main window
local fn BuildWindow
dim as rect r

setrect( r, 0, 0, 600, 400 )
appearance Window -1, "File String Parser", @r,¬
_kDocumentWindowClass, _kWindowStandardFloatingAttributes

def SetWindowBackground( _kThemeActiveDialogBackgroundBrush,_zTrue )

text _sysFont, 11
edit = 3
setrect( r, 10, 20, 155, 35 )
edit field _oldStrLabelEF, "Find this string:", @r, _statNoFramed,_rightJust

offsetrect( r, 0, 34 )
edit field _newStrLabelEF, "Replace with this string:",
@r,_statNoFramed,_rightJust

text _courier, 11
setrect( r, 161, 20, 450, 35 )
edit field _oldStrEF, "", @r,_framedNoCR,_leftJust

offsetrect( r, 0, 34 )
edit field _newStrEF, "", @r,_framedNoCR,_leftJust

text _courier, 11
edit = 4
setrect( r, 20, 90, 434, 340 )
edit field _mainEF,"",@r,_framed,_leftJust
setrect( r, 434, 86, 450, 343 )
scroll button -_mainEF,0,0,0,0, @r, _scrollOther

setrect( r, 470, 130, 590, 220 )
edit field _errorEF,"",@r,_statNoframed,_leftJust

setrect( r, 470, 20, 590, 40)
button _openBtn, 1, "Open file...", @r,_push

offsetrect( r, 0, 35 )
button _replaceBtn, 1, "Replace string", @r,_push

offsetrect( r, 0, 35 )
button _saveBtn, 1, "Save results", @r,_push

edit field _mainEF

window 1

end fn

//  Read contents of selected file into a handle
local fn LoadFileIntoHandle( fileStr as str255, vol as int )
dim as handle @ fileH
dim as long     fileLen
dim as OSErr    err

open "I", #1, fileStr, ,vol

fileLen = lof(1, 1)
   fileH = fn newhandle _clear( fileLen )
     err = syserror

long if fileH != 0 and err == 0
read file #1, [fileH], fileLen
end if
close #1

end fn = fileH

//  Place text from handle created by fn LoadFileIntoHandle
// into specified edit field
local fn TextHandleIntoEF( efID as int, fileH as handle )
dim as long  size
dim teH as ..TERec

edit$(efID) = ""

size = fn gethandlesize( fileH )
  teH = teHandle( efID )

HLock( fileH )
// Purposely limit edit field size to 32K to avoid inherent TE problems
if ( size > 32000 ) then size = 32000
TEInsert( [fileH], size, teH )
TESetSelect( 0, 0, teH )
HunLock( fileH )

end fn

// Open file, load text into edit field
local fn LoadFile( efID as int )
dim as handle  @ fileH
dim as integer @ vRefNum
dim as str255    fileNameStr

fileNameStr = FILES$( _fOpen, "TEXT", ,vRefNum )
long if fileNameStr = ""
exit fn
xelse
fileH = FN LoadFileIntoHandle( fileNameStr, vRefNum )
end if

// If file handle is valid, load its contents into edit field
long if fileH != 0
fn TextHandleIntoEF( efID, fileH )
def DisposeH( fileH )
xelse
beep
end if

setselect _maxInt, _maxInt
setselect 0, 0

// Switch focus to main field
edit field  efID

end fn

clear local mode
local fn HandleSearchAndReplace( searchH as handle,¬
                               findStr as str255,¬
                            replaceStr as str255 )

dim as long     startSearch, oldSearch, count
dim as OSStatus status

startSearch = 0 ' start search at beginning
oldSearch   = 0 ' synch flag
count       = 0 ' clear count

do
status = fn munger( searchH,¬
                 startSearch,¬
                @findStr + 1,¬
                  findStr[0],¬
             @replaceStr + 1,¬
               replaceStr[0] )

long if startSearch > oldSearch
count++
oldSearch = startSearch
end if

until startSearch <= 0

end fn = count

// Determine number of lines in target edit field
local fn CountLinesInEF( efID as int )
dim as int    lines
dim as handle teH

teH = TEHANDLE( efID )
lines = teH..teNLines%

end fn = lines

// Check to see if all necessary information is present to perform replace
local fn CheckForCompleteInfo
dim as boolean noErrors

noErrors = _false

edit$(_errorEF ) = ""

long if edit$(_mainEF) = ""
edit$(_errorEF) = "Please open a file to parse."

edit field _mainEF
exit fn
end if

long if edit$(_oldStrEF) = ""
edit$(_errorEF) = "Please enter a string to find¬
  as a target in the ""Find this string"" field."
edit field _oldStrEF
exit fn
end if

noErrors = _true

end fn = noErrors

// Initialize the three functions above to replace string
local fn DoReplace
dim as str255   testStr, oldSubStr, newSubStr
dim as handle @ teH
dim as long     i

// Make sure all information for replace is present
if fn CheckForCompleteInfo = _false then exit fn

// Initialize replace strings
testStr = "" : oldSubStr = "" : newSubStr = ""

oldSubStr = edit$(_oldStrEF)
newSubStr = edit$(_newStrEF)

// Load original field contents into its container for undo
gOriginalC = edit$(_mainEF)

get field teH, _mainEF

for i = 1 to fn CountLinesInEF( _mainEF )
fn HandleSearchAndReplace( teH, oldSubStr, newSubStr )
next i

gRevisedC = &teH

kill field teH

edit$( _mainEF ) = ""

// Load finished container into edit field
edit$( _mainEF ) = #gRevisedC
gUndoFlag = _true

setselect 0, 0

end fn

// Very rudimentary Undo function
local FN Undo

long if gUndoFlag = _true
edit$(_mainEF) = #gOriginalC
gUndoFlag = _false
xelse
edit$(_mainEF) = #gRevisedC
gUndoFlag = _true
end if

end fn

// Function to save completed results
clear local
local fn SaveFile
dim as str255    fStr
dim as integer @ defaultVol
dim as handle  @ textH

get field textH, _mainEF

def open "TEXTttxt"

menu

fStr = files$( _fSave, "Save As...", "untitled", defaultVol )
long if fStr[0]
open "O", #1, fStr, 1, defaultVol
write file# 1, [textH], fn gethandlesize(textH)
close #1
end if

menu 1, 0, 1

end fn

// Dialog handlers
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 _openBtn    : fn LoadFile( _mainEF )
case _replaceBtn : fn DoReplace
case _saveBtn    : fn SaveFile
end select
end select

end fn

// Menu handlers
clear local
local fn DoMenus
dim as long menuID, itemID

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

select case( menuID )
case _applemenu
select( itemID )
case 1
end select
case 1
select( itemID )
case 1 : fn LoadFile( _mainEF )
case 2 : fn DoReplace
case 4 : fn SaveFile
case 6 : gFBQuit = _zTrue
end select
case 2
select( itemID )
case 1 : FN Undo
end select
end select

menu

end fn

// Main event loop
on dialog fn DoDialog
on menu   fn DoMenus

fn BuildMenus
fn BuildWindow

do
handleevents
until gFBQuit
end