home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
p2demo21.exe
/
PEL
/
SEARCH.PEL
< prev
next >
Wrap
Text File
|
1995-04-19
|
51KB
|
1,890 lines
# $Header: P:\source\wmacros\search.pev 1.99 19 Apr 1995 18:29:50 PFHDWM0 $
# $Tabs:4 7$
##############################################################################
#
# Compuware Corporation
# 31440 Northwestern Highway
# Farmington Hills, Michigan 48334-2564
#
# This source code listing contains information that is
# proprietary to Compuware Corporation and may not be copied
# duplicated, translated, transmitted, stored, retrieved
# or in any manner or by any method conveyed or disclosed
# to a third party or parties without express written
# permission from Compuware Corporation.
#
#
##############################################################################
#### $Workfile: search.pel $: support for search/replace
## search flag settings used by search and replace
#
# primitive flags:
global SEARCH_MAXIMAL_MATCH = 0x0001
global SEARCH_BLOCK = 0x0002
global SEARCH_FORWARD = 0x0004 # backwards = 0
global SEARCH_BACKWARD = 0x0000
global SEARCH_WRAPS = 0x0008
global SEARCH_REGEX = 0x0010
global SEARCH_CASE = 0x0020
global SEARCH_ADVANCE = 0x0040
global SEARCH_WHOLE_WORD = 0x0080
global SEARCH_ONCE_PER_LINE = 0x0100
# The follow globals are only used here
global SEARCH_HIGHLIGHT = 0x0200 # Highlight after the search.
global SEARCH_CENTER_CURSOR = 0x0400 # normalize after search
global SEARCH_GLOBAL = 0x0800 # global search
global SEARCH_MARK_CHG = 0x1000 # mark changed lines (in lc area)
global SEARCH_ALL_BUFFERS = 0x2000 # search all buffers
# Initial setting for search_flags. However,
# each keymap modifies to its own default settings.
# max_match, block, forward, regex, center
global SEARCH_DEFAULT = SEARCH_FORWARD+SEARCH_MAXIMAL_MATCH+ \
SEARCH_REGEX+SEARCH_CENTER_CURSOR+ \
SEARCH_HIGHLIGHT+SEARCH_WRAPS
# case sensitive combos:
global SEARCH_FWD_REGEX_MAX = SEARCH_CASE+SEARCH_FORWARD+SEARCH_REGEX+SEARCH_MAXIMAL_MATCH
global SEARCH_BKWD_REGEX_MAX = SEARCH_CASE+SEARCH_REGEX+SEARCH_MAXIMAL_MATCH
global SEARCH_FWD_REGEX = SEARCH_CASE+SEARCH_FORWARD+SEARCH_REGEX
global SEARCH_BKWD_REGEX = SEARCH_CASE+SEARCH_REGEX
global SEARCH_FWD_ADV = SEARCH_CASE+SEARCH_FORWARD+SEARCH_ADVANCE
global SEARCH_FWD_REGEX_ADV = SEARCH_CASE+SEARCH_FORWARD+SEARCH_REGEX+SEARCH_ADVANCE
global SEARCH_BKWD_REGEX_ADV = SEARCH_CASE+SEARCH_REGEX+SEARCH_ADVANCE
# ignore case combos:
global SEARCH_FWD_REGEX_MAX_IG = SEARCH_FORWARD+SEARCH_REGEX+SEARCH_MAXIMAL_MATCH
global SEARCH_BKWD_REGEX_MAX_IG = SEARCH_REGEX+SEARCH_MAXIMAL_MATCH
global SEARCH_FWD_REGEX_IG = SEARCH_FORWARD+SEARCH_REGEX
global SEARCH_BKWD_REGEX_IG = SEARCH_REGEX
global SEARCH_FWD_IG = SEARCH_FORWARD
## initial search settings
#
global search_flags = SEARCH_DEFAULT #PUBLIC #INT
global search_pattern = ""
global replace_pattern = ""
## Misc. vars:
global MAX_SEARCH = 0x7FFFFFFF # search global search count
global find_mark # string to mark finds with.
global change_mark # string to mark changes with.
#------------------ Search functions --------------------#
#
# Search forward from the current position. This function may also match
# the current position. The user is prompted for a search string.
#
function search_forward( patt ) #PUBLIC #INT
{
local rc
toggle_search_flags(SEARCH_FORWARD, 1 )
if ( selection_type() != NO_SELECTION )
search_flags = or( search_flags, SEARCH_BLOCK )
else
search_flags = and( search_flags, not( SEARCH_BLOCK ) )
rc = sf_search( patt )
return rc
}
function context_search( )
{
search_pattern = symbol_under_cursor()
search_forward( search_pattern )
}
#
# Search backward from the current position. This function may also match
# the current position. The user is prompted for a search string.
#
global function search_backward( patt ) #PUBLIC #INT
{
local rc
toggle_search_flags(SEARCH_FORWARD, 0 )
if ( selection_type() != NO_SELECTION )
search_flags = or( search_flags, SEARCH_BLOCK )
else
search_flags = and( search_flags, not( SEARCH_BLOCK ) )
rc = sf_search( patt )
return rc
}
#
# Search from the current position using the current search_flag settings.
# This function may also match the current position. The user is
# prompted for a search string.
#
function sf_search( patt, flags ) #PUBLIC #INT
{
local status;
local temp = search_flags
# Turn off all-files and advance bits before search
#
search_flags = and(search_flags, not(SEARCH_ADVANCE+SEARCH_ALL_BUFFERS))
if (argcount() > 1)
search_flags = flags;
if ( !patt )
if ( (patt = search_prompt()) )
search_pattern = patt
status = string_search( patt )
# Turn advance bit back on
#
search_flags = or(temp, SEARCH_ADVANCE )
return status;
}
#
# prompt for the search pattern and provide command history
#
local function search_prompt()
{
local arrow = and( search_flags, SEARCH_FORWARD ) ? "" : ""
local regex = and( search_flags, SEARCH_REGEX ) ? "" : "(RE off) "
return prompt_history( "SEARCH", arrow " Search " regex "for: ",
search_pattern, 1, 1, "search_prompt" )
}
#
# Begin searching from the current position for the next occurrence of
# search_pattern ( the last successful search pattern).
#
# Use all of the "search_flags" settings that have been previously defined
#
#
global function search_again() #PUBLIC #INT
{
local success = 0;
# check for a previously successful search
#
if ( !search_pattern )
{
warning( "No previous search pattern." )
return FALSE
}
# begin the search, but instruct search() to
# move forward or backward 1 character (depending on the
# direction of the search)
#
save_position()
message( "" )
search_flags = or(search_flags, SEARCH_ADVANCE)
success = string_search( search_pattern );
if ( success )
restore_position( 0 )
else
restore_position( 1 )
# after the search, turn on the search_advance bit. So the first time
# it will just search, after that, you get search again
#
search_flags = or(search_flags, SEARCH_ADVANCE)
return success;
}
#
# search_again, but force the direction forwards or backwards
#
global function search_again_forward() #PUBLIC #INT
{
toggle_search_flags(SEARCH_FORWARD, 1 )
return search_again()
}
global function search_again_backward() #PUBLIC #INT
{
toggle_search_flags(SEARCH_FORWARD, 0 )
return search_again()
}
#
# Actually perform the search for the string now. Use the current
# "search_flags" settings except for the SEARCH_ADVANCE flag.
#
# It is assumed that the user has been prompted for a search string
# and if one doesn't exist, nothing is done here.
#
local search_selection # array used to save the selection for search_agains.
function string_search( sspatt, sflags )
{
local status
local prevMessage
local block_search = FALSE
local bottom_mark
local top_mark
local bottom_line
local bottom_col
local top_line
local top_col
unhilight_temp_selection()
if ( !sspatt )
return FALSE
else
add_prompt_history("SEARCH", sspatt);
# set the global search_flags to parameter if one isn't passed in
#
if (argcount() == 1 )
sflags = search_flags
#
# set parameter to variable just in case this is called somewhere else
# where it's not done
#
search_pattern = sspatt;
message( "Searching..." )
# if we are searching a block...
#
if ( and(search_flags, SEARCH_BLOCK))
{
if (selection_type() != NO_SELECTION )
{
# if there is currently a selection,
# save the selection and position cursor at the beginning or end
# of the selection depending on direction
#
save_position()
end_selection()
# delete the last saved selection (if there is one)
#
if (search_selection_ok())
delete_search_selection()
block_search = TRUE
save_search_selection( TRUE )
if ( selection_type() == LINE_SELECTION )
goto_bol();
}
else if (and(search_flags, SEARCH_ADVANCE) && search_selection_ok())
{
# if we are searching for the next occurance,
# restore the old selection (if there is one).
#
restore_search_selection()
block_search = TRUE
}
}
else if (search_selection_ok())
delete_search_selection()
status = search( sspatt, sflags )
if ( status )
{
if ( block_search )
{
restore_position( FALSE )
# need to update here to get selection to redraw properly
update_current_view()
remove_selection()
update_current_view()
}
message( "Search completed." )
if ( and(search_flags, SEARCH_CENTER_CURSOR) )
center_cursor()
highlightSearch()
}
else
{
if ( block_search )
{
restore_position( TRUE )
remove_selection()
delete_search_selection()
update_current_view()
warning( "Pattern \"%s\" not found in the block.", search_pattern )
}
else
warning( "Pattern \"%s\" not found.", search_pattern )
}
return status
}
# Function to check to see if there is a search_selection
#
global function search_selection_ok()
{
return (search_selection.type != NO_SELECTION )
}
global function save_search_selection( moveCursor )
{
local bottom_mark
local top_mark
local bottom_line
local bottom_col
local top_line
local top_col
search_selection.type = selection_type()
# calculate the bottom and top of the selection
bottom_mark = selection_mark_bottom()
top_mark = selection_mark_top()
bottom_line = mark_line( bottom_mark )
bottom_col = max( mark_column(bottom_mark), mark_column(top_mark) )
top_line = mark_line( top_mark )
top_col = min( mark_column(bottom_mark), mark_column(top_mark) )
if ( !moveCursor )
save_position()
# save the selection marks, ending up with the cursor at the
# appropriate spot.
if ( and(search_flags, SEARCH_FORWARD ) )
{
goto_pos( bottom_line, bottom_col )
search_selection.bottom = create_mark(pick_unused_mark())
goto_pos( top_line, top_col )
search_selection.top = create_mark(pick_unused_mark())
}
else
{
goto_pos( top_line, top_col )
search_selection.top = create_mark(pick_unused_mark())
goto_pos( bottom_line, bottom_col )
search_selection.bottom = create_mark(pick_unused_mark())
}
if ( !moveCursor )
restore_position( TRUE )
}
# Function to hilight the search block.
#
global function restore_search_selection()
{
# begin_selection(search_selection.type, search_selection.top)
# end_selection(search_selection.bottom)
save_position()
goto_mark( search_selection.top )
begin_selection( search_selection.type )
goto_mark( search_selection.bottom )
end_selection()
restore_position( TRUE )
# update_current_view()
# display_update()
}
# Function to delete the search block.
#
global function delete_search_selection()
{
delete_mark(search_selection.top)
delete_mark(search_selection.bottom)
delete search_selection
}
## Highlight the search target.
#
# If called from the keyboard, display the highlight and wait until another
# key is pressed and then remove it.
#
# original function commented out because could not figure out when
# keyboard_input_pending was changed. This replacement works well
function highlightSearch(dontSaveSelection)
{
if ( and( search_flags, SEARCH_HIGHLIGHT ) )
highlightSearchOn(dontSaveSelection)
}
function highlightSearchOn(dontSaveSelection)
{
local slen
local stype = NORMAL_SELECTION
slen = search_string_length - search_cursor_offset
if ( slen == 0 )
stype = INCLUSIVE_SELECTION
create_offset_selection(stype, buffer_offset + slen, buffer_offset, \
!dontSaveSelection)
}
#
# Find all occurences of the src string one at a time.
# And return an array of found strings with index 0 containing
# the count of found strings. Other indexes are the line number where
# the strings are located
#
global function find_all( srch, prompt )
{
local ch # confirm character
local found, last, slen, line
local tmpFlags
local wrapPass
local wrapOffset
local strings_found # number of replacement done
local srchFwd = and( search_flags, SEARCH_FORWARD )
local remaining = search_count > 1 ? search_count : MAX_SEARCH
local mark_lines = linecommands_enabled && linenumber_width && \
length(find_mark)
local found_array
prompt += 0;
found_array[0] = 0
if (!mark_lines && ( argcount() == 1 ) )
prompt = TRUE
# make sure search pattern is present
#
if ( !srch )
{
srch = search_prompt()
if ( !srch )
return found_array
}
# set search variable and add to history
#
search_pattern = srch
add_prompt_history("SEARCH", search_pattern)
#
# Prepare to perform the search
#
# init for wrapping
wrapPass = !!and( search_flags, SEARCH_WRAPS )
if ( selection_type() != NO_SELECTION )
wrapPass = 0;
wrapOffset = buffer_offset
tmpFlags = and( search_flags, not( SEARCH_ADVANCE + SEARCH_WRAPS ))
# save original position
save_position()
#
# continue to search until the user says no or we can't find any more.
#
save_selection()
search_count = 0
while ( remaining )
{
save_position()
restore_selection()
restore_position(1)
found = search( srch, tmpFlags )
save_selection()
tmpFlags = and( tmpFlags, not( SEARCH_ADVANCE ))
# check for normal termination and handle wrapping
#
if (( wrapPass == 2 ) && ( buffer_offset >= wrapOffset ))
found = FALSE
if ( !found )
{
if ( wrapPass == 1 )
{
searchWrap( srchFwd )
wrapPass = 2
continue # try again
}
else
break # we're done
}
remaining -= found
strings_found += found
# found_array[ strings_found ] = read_line()
found_array[ current_line ] = read_line()
if (mark_lines)
{
#
# mark the line the string is on.
#
save_position()
slen = search_string_length - search_cursor_offset
# goto the beginning of word
goto_buffer_offset( buffer_offset - slen )
last = current_line
# goto end of the word
goto_buffer_offset(buffer_offset + slen)
line = current_line
do {
line_command[line] = find_mark
line--
} while (line > last)
restore_position(1)
}
if (prompt)
{
#
# highlight the search string found and wait for user input
#
highlightSearch(1)
ch = tolower( confirm( "Find Next [Yes|No]? ", "YyNn" ))
unhilight_temp_selection()
if ( ch == "n" )
break
}
skipSearchString( and( tmpFlags, SEARCH_FORWARD ))
}
#
# go back to the original starting position
#
restore_position( !prompt )
message( "Search complete; %d occurrence%s found.",
strings_found, strings_found == 1 ? "" : "s" )
restore_selection()
if (mark_lines) # Make sure that any lines we marked
display_redraw() # will be displayed.
found_array[0] = strings_found
return found_array
}
#------------------ Replace functions --------------------#
#
# Search for the next occurrence of spatt and replace it with rpatt.
# Use the current search_flag settings.
# The function string_replace() is called to perform
# any incremental or global replacements.
#
global function sf_replace( spatt, rpatt ) #PUBLIC #INT
{
local arrow, retcode
if ( !spatt )
{
#
# prompt for the search pattern and provide command history
#
arrow = and( search_flags, SEARCH_FORWARD ) ? "" : ""
spatt = prompt_history( "SEARCH", arrow " Pattern: ", search_pattern, 1, 1, "search_prompt" )
}
# turn off the all-files flag
#
search_flags = and(search_flags, not(SEARCH_ALL_BUFFERS))
# set the search_count variable for later searches
#
if ( and( search_flags, SEARCH_GLOBAL ))
{
search_flags = and( search_flags, not(SEARCH_GLOBAL) )
search_count = MAX_SEARCH
}
# if there is currently a selection, position cursor at beginning
# of selection depending on direction
#
if ( and(search_flags, SEARCH_BLOCK) && selection_type() != NO_SELECTION )
{
save_position()
end_selection()
if ( and(search_flags, SEARCH_FORWARD ) )
goto_mark(selection_mark_top())
else
goto_mark(selection_mark_bottom())
if ( selection_type() == LINE_SELECTION )
goto_bol();
}
if ( argcount() > 1 )
retcode = string_replace( spatt, rpatt )
else
retcode = string_replace( spatt )
if ( selection_type() != NO_SELECTION )
{
restore_position()
remove_selection()
}
return retcode;
}
#
# Search for the next occurrence of spatt and replace it with rpatt.
# The function string_replace() is called to perform
# any incremental or global replacements.
#
global function replace_forward( spatt, rpatt ) #PUBLIC #INT
{
local retcode
local old_sf = search_flags
if ( selection_type() != NO_SELECTION )
search_flags = or( search_flags, SEARCH_BLOCK )
else
search_flags = and( search_flags, not( SEARCH_BLOCK ) )
toggle_search_flags(SEARCH_FORWARD, 1 )
if ( argcount() > 1 )
retcode = sf_replace( spatt, rpatt )
else
retcode = sf_replace( spatt )
search_flags = old_sf
return retcode
}
#
# Search for the previous occurrence of spatt and replace it with rpatt.
# The function string_replace() is called to perform
# any incremental or global replacements.
#
global function replace_backward( spatt, rpatt ) #PUBLIC #INT
{
local rc
local old_sf = search_flags
toggle_search_flags(SEARCH_FORWARD, 0 )
if ( selection_type() != NO_SELECTION )
search_flags = or( search_flags, SEARCH_BLOCK )
else
search_flags = and( search_flags, not( SEARCH_BLOCK ) )
if ( argcount() > 1 )
rc = sf_replace( spatt, rpatt )
else
rc = sf_replace( spatt )
search_flags = old_sf
return rc
}
#
# Begin searching from the current position for the next occurrence of
# search_pattern (the last successful search pattern) and replace it.
#
# Use all of the "search_flags" settings that have been previously defined
#
global function replace_again(noadvance) #PUBLIC #INT
{
local direction, slen, line, last
#
# make sure we have something to search for and something
# to replace it with.
#
if ( search_pattern && replace_pattern )
{
message( "Replacing..." )
if ( replace( search_pattern, replace_pattern,
noadvance ? and(search_flags, not(SEARCH_ADVANCE)) \
: or(search_flags, SEARCH_ADVANCE)))
{
#
# we found it and replaced successfully
#
if (linecommands_enabled && linenumber_width && length(change_mark))
{
save_position()
slen = search_string_length - search_cursor_offset
# goto the beginning of word
goto_buffer_offset( buffer_offset - slen )
last = current_line
# goto end of the word
goto_buffer_offset(buffer_offset + slen)
line = current_line
do {
line_command[line] = change_mark
line--
} while (line > last)
restore_position(1)
}
message( "Replacement complete." )
return TRUE
}
else
warning( "Pattern \"%s\" not found.", search_pattern )
}
else
{
#
# not enough information to do anything
#
warning( "No previous replacement pattern(s)." )
}
return FALSE
}
#
# Replace the "srch" string if found and prompt for multiple (or global)
# replacements.
#
# We need to make sure that if found and replaced, skip of the previous
# replacement so that we don't get into an infinite loop.
#
global function string_replace( srch, repl ) #PUBLIC #INT
{
local changes_made # number of replacement done
local found_replacement # at least one string was found
local save_count
local found
local tmpFlags
local srchFwd = and( search_flags, SEARCH_FORWARD )
local prevMessage
local wrapPass
local wrapOffset
local ch # confirm character
local optype
# save original search_count
#
save_count = search_count
search_count = 0
# make sure search pattern is present
#
if ( !srch )
return 0
# get the replacement string to use
#
if ( argcount() < 2 )
repl = prompt_history("REPLACE", "Replacement: ", replace_pattern, 1, 1, "replace_prompt" )
# Check for ESC to differentiate between a CR and a canceled prompt.
#
if ( !repl && ( current_key == KEYCODE_ESC ))
return 0
# set search and replace variables and add to history
#
replace_pattern = repl
search_pattern = srch
add_prompt_history("REPLACE", replace_pattern)
add_prompt_history("SEARCH", search_pattern)
#
# We have both strings now prepare to perform the replacement
#
# init for wrapping
if ( selection_type() != NO_SELECTION )
wrapPass = 0;
else
wrapPass = !!and( search_flags, SEARCH_WRAPS )
wrapOffset = buffer_offset
tmpFlags = and( search_flags, not( SEARCH_ADVANCE + SEARCH_WRAPS ))
if (linecommands_enabled && linenumber_width && length(change_mark))
tmpFlags = or( tmpFlags, SEARCH_MARK_CHG )
else
tmpFlags = and( tmpFlags, not( SEARCH_MARK_CHG ))
prevMessage = last_message
# save original position
save_position()
#
# continue to replace until the user says no or
# we can't replace any more.
#
save_selection()
while ( TRUE )
{
save_position()
restore_selection()
restore_position(1)
found = search( srch, tmpFlags )
save_selection()
# update_current_view()
display_update()
tmpFlags = and( tmpFlags, not( SEARCH_ADVANCE ))
# check for normal termination and handle wrapping
#
if (( wrapPass == 2 ) && ( buffer_offset >= wrapOffset ))
found = FALSE
if ( !found )
{
if ( wrapPass == 1 )
{
searchWrap( srchFwd )
wrapPass = 2
continue # try again
}
break # we're done
}
# at least one search string was found
found_replacement = TRUE
#
# highlight the search string found and wait for user input
#
if ( save_count > 0 )
ch = "g"
else
{
highlightSearch(1)
ch = tolower( confirm( "Change [Yes|No|Global]? ", "YyNnGg" ))
unhilight_temp_selection()
if ( ch == "g" )
save_count = MAX_SEARCH
}
if ( ch == "y" )
{
# replace and skip over the replacement
replace( srch, repl, tmpFlags )
skipReplaceString( and( tmpFlags, SEARCH_FORWARD ))
changes_made++
}
else if ( ch == "n" )
{
# skip this replacement
skipSearchString( and( tmpFlags, SEARCH_FORWARD ))
tmpFlags = or(tmpFlags, SEARCH_ADVANCE)
}
else if ( ch == "g" )
{
# global replace
search_count = save_count
restore_selection()
changes_made += globalReplace( srch, repl, tmpFlags, srchFwd,
wrapPass, wrapOffset )
break
}
else
{
# replacement was canceled
#
unhilight_temp_selection()
restore_position( 0 )
restore_selection()
message( "Translation complete; %d occurrence%s changed.",
changes_made, changes_made == 1 ? "" : "s" )
return changes_made
}
} # while TRUE
#
# go back to the original starting position
#
restore_position( 1 )
# We found at least one string to replace.
# Display the number that were replaced.
#
message( "Translation complete; %d occurrence%s changed.",
changes_made, \
changes_made == 1 ? "" : "s" )
restore_selection()
return changes_made
}
# Perform a global replace. We will continue until we fail or
# seach_count is satisfied.
#
global function globalReplace( srch, repl, tmpFlags, srchFwd, wrapPass,
wrapOffset )
{
local mark_changes = and(tmpFlags, SEARCH_MARK_CHG)
local remaining = search_count
local attempts = 1
local found
local last
local line
local slen
local totalFound
message( "Replacing..." )
while (TRUE )
{
if ( wrapPass == 2 )
{
# If wrapping, any match after our starting position
# is a failure.
#
search_count = 1
if ( !search( srch, tmpFlags ) || ( buffer_offset >= wrapOffset ))
break
attempts = 1
}
else if (!mark_changes)
{
# We update the screen every 50 replacements
# just to let the user know we're still alive.
#
attempts = (( remaining > 50 ) ? 50 : remaining )
}
search_count = attempts
found = replace( srch, repl, tmpFlags )
if (mark_changes)
{
save_position()
slen = search_string_length - search_cursor_offset
# goto the beginning of word
goto_buffer_offset( buffer_offset - slen )
last = current_line
# goto end of the word
goto_buffer_offset(buffer_offset + slen)
line = current_line
do {
line_command[line] = change_mark
line--
} while (line > last)
restore_position(1)
}
remaining -= found
totalFound += found
# skip over the replacement
#
skipReplaceString( srchFwd )
# check for normal termination and handle wrapping
#
if ( attempts != found )
{
if ( wrapPass == 1 )
{
searchWrap( srchFwd )
wrapPass = 2 # try again
}
else if ( wrapPass == 0 )
break
}
else if ( remaining <= 0 )
break # we're done
}
return totalFound
}
global function skipReplaceString( direction )
{
if ( direction )
{
next_char(( replace_string_length ? replace_string_length : 1 ) + \
( search_string_length ? 0 : 1 ))
}
else
prev_char( 1 )
}
global function skipSearchString( direction )
{
if ( direction )
next_char( search_string_length ? search_string_length : 1 )
else
prev_char( 1 )
}
# wrap at the end of the search region
#
local function searchWrap( direction )
{
if ( direction )
{
goto_buffer_top()
goto_mark( selection_mark_top() )
}
else
{
goto_buffer_bottom()
goto_mark( selection_mark_bottom() )
}
}
#------------------ Incremental search functions --------------------#
#
# Perform an incremental search through the current buffer.
#
# This is accomplished by reading one character at a time from the keyboard
# and appending it to the current search string. If the string is not found
# the character is stripped from the search string and the previous buffer
# position is restored.
#
local reentrant_search_i = 0
local searchi_pattern = ""
global function search_i() #PUBLIC #VOID
{
local char = ""
local ch = 0
local level = 0
local sf = and( search_flags, not(SEARCH_REGEX+SEARCH_ADVANCE) )
# don't allow reentering the search_i if we
# are already in here
if ( reentrant_search_i )
{
# just in case message has disappeared
message( "Incremental-Search for: %s\334",
quote_printf_string( searchi_pattern ))
return;
}
searchi_pattern = ""
reentrant_search_i = 1
optional_function( "enable_status_bar_messages" )
while ( TRUE )
{
# display the prompt message with a fake cursor
message( "Incremental-Search for: %s\334",
quote_printf_string( searchi_pattern ))
# get the next ascii character from the keyboard
# ignore extended character which have an ascii code of 0
ch = getchar()
if ( ch == 0 )
{
# clear the extended character scan code
# out of the keyboard buffer
getchar()
beep()
continue
}
# quit incremental searching when an ESC is pressed
if ( ch == ASCII_ESC || ch == ASCII_ENTER)
break
if ( ch == ASCII_BACKSPACE )
{
#
# remove the last char in the search string and
# restore the previous position
#
searchi_pattern = substr( searchi_pattern, 0, length( searchi_pattern ) - 1 )
if ( level )
{
restore_position( TRUE )
level--
}
}
else
{
#
# It is a normal ascii character.
# Let's search for the new pattern. If we find it,
# save the previous position and advance to the
# newly found string.
#
char = chr( ch )
save_position()
message( "Incremental-Search for: %s\137",
quote_printf_string( searchi_pattern char ))
sf = and( sf, not( SEARCH_BACKWARD ) )
sf = or(sf, SEARCH_MAXIMAL_MATCH+SEARCH_BACKWARD )
# if ( search( searchi_pattern char, SEARCH_MAXIMAL_MATCH+SEARCH_FORWARD ))
if ( search( searchi_pattern char, sf ))
{
searchi_pattern = searchi_pattern char
level++
}
else
{
beep()
restore_position( FALSE )
}
}
display_update()
}
optional_function( "restore_status_bar" )
message( "Incremental-search done." )
while ( level-- )
{
restore_position( FALSE )
}
if (searchi_pattern)
{
# must set global 'search_pattern' so that future calls to prompt_history
# from search_forward display last searchi_pattern. This is required
# since this function calls search() instead of search_forward().
search_pattern = searchi_pattern
add_prompt_history("SEARCH", searchi_pattern);
}
reentrant_search_i = 0
}
#----------- Supporting search and replace functions ------------#
global function toggle_search_flags(mask, value)
{
local msg, suffix = "disabled.";
# If no value supplied, toggle the old value;
if(argcount() < 2)
value = xor(mask, and(search_flags, mask));
if ( value )
{
search_flags = or( search_flags, mask )
suffix = "enabled.";
}
else
search_flags = and( search_flags, not(mask) )
if(mask == SEARCH_ADVANCE)
msg = "Search advance " suffix;
else if(mask == SEARCH_BACKWARD)
msg = "Search backward " suffix;
else if(mask == SEARCH_CASE)
msg = "Search case sensitive " suffix;
else if(mask == SEARCH_CENTER_CURSOR)
msg = "Search centering results " suffix;
else if(mask == SEARCH_FORWARD)
msg = "Search forward " suffix;
else if(mask == SEARCH_MAXIMAL_MATCH)
msg = "Search maximal match " suffix;
else if(mask == SEARCH_REGEX)
msg = "Search regular expressions " suffix;
else if(mask == SEARCH_WHOLE_WORD)
msg = "Search matching whole word " suffix;
else if(mask == SEARCH_WRAPS)
msg = "Search wrapping " suffix;
else
msg = "Search mode " suffix;
message(msg);
return value;
}
#
# toggle the case sensitivity setting in the "search_flags" variable
# and display a message indicating the new default case sensitivity value.
#
#global function toggle_search_case( on ) #PUBLIC #INT
#{
# if ( argcount() < 1 )
# on = !and( search_flags, SEARCH_CASE )
# else
# on = 0+on
#
# #
# # toggle the setting
# #
# if ( on )
# search_flags = or( search_flags, SEARCH_CASE )
# else
# search_flags = and( search_flags, not( SEARCH_CASE ))
#
# message( "Case sensitive search %s.", on ? "on" : "off" )
# return on
#}
#
#
##
## toggle the global search setting in the "search_flags" variable
## and display a message indicating the new default global value.
##
#global function toggle_search_global( on ) #PUBLIC #INT
#{
# if ( argcount() < 1 )
# on = !and( search_flags, SEARCH_GLOBAL )
# else
# on = 0+on
#
# #
# # toggle the setting
# #
# if ( on )
# search_flags = or( search_flags, SEARCH_GLOBAL )
# else
# search_flags = and( search_flags, not( SEARCH_GLOBAL ))
#
# message( "Global search %s.", on ? "on" : "off" )
# return on
#}
#
##
## toggle the all-files search setting in the "search_flags" variable
## and display a message indicating the new default all-files value.
##
#global function toggle_search_all_buffers( on ) #PUBLIC #INT
#{
# if ( argcount() < 1 )
# on = !and( search_flags, SEARCH_ALL_BUFFERS )
# else
# on = 0+on
#
# #
# # toggle the setting
# #
# if ( on )
# search_flags = or( search_flags, SEARCH_ALL_BUFFERS )
# else
# search_flags = and( search_flags, not( SEARCH_ALL_BUFFERS ))
#
# message( "All-Files search %s.", on ? "on" : "off" )
# return on
#}
#
##
## toggle the center search setting in the "search_flags" variable
## and display a message indicating the new default center value.
##
#global function toggle_search_center( on ) #PUBLIC #INT
#{
# if ( argcount() < 1 )
# on = !and( search_flags, SEARCH_CENTER_CURSOR )
# else
# on = 0+on
#
# #
# # toggle the setting
# #
# if ( on )
# search_flags = or( search_flags, SEARCH_CENTER_CURSOR )
# else
# search_flags = and( search_flags, not( SEARCH_CENTER_CURSOR ))
#
# message( "Centering search is %s.", on ? "on" : "off" )
# return on
#}
#
##
## toggle the regular expression setting in the "search_flags" variable
## and display a message indicating the new default regex value.
##
#global function toggle_search_regex( on ) #PUBLIC #INT
#{
# if ( argcount() < 1 )
# on = !and( search_flags, SEARCH_REGEX )
# else
# on = 0+on
#
# #
# # toggle the setting
# #
# if ( on )
# search_flags = or( search_flags, SEARCH_REGEX )
# else
# search_flags = and( search_flags, not( SEARCH_REGEX ))
#
# message( "Regular expression search %s.", on ? "on" : "off" )
# return on
#}
#
##
## toggle the state of the SEARCH_BLOCK flag in search_flags
##
#global function toggle_search_block( on ) #PUBLIC #INT
#{
# if( argcount() < 1 )
# on = !and( search_flags, SEARCH_BLOCK )
# else
# on = 0+on
#
# #
# # toggle the setting
# #
# if ( on )
# search_flags = or( search_flags, SEARCH_BLOCK )
# else
# search_flags = and( search_flags, not( SEARCH_BLOCK ))
#
# message( "Block searching %s.", on ? "on" : "off" )
# return on
#}
#
##
## toggle the state of the SEARCH_WHOLE_WORD flag in search_flags
##
#global function toggle_search_word( on ) #PUBLIC #INT
#{
# if( argcount() < 1 )
# on = !and( search_flags, SEARCH_WHOLE_WORD )
# else
# on = 0+on
#
# #
# # toggle the setting
# #
# if ( on )
# search_flags = or( search_flags, SEARCH_WHOLE_WORD )
# else
# search_flags = and( search_flags, not( SEARCH_WHOLE_WORD ))
#
# message( "Whole word searching is %s.", on ? "on" : "off" )
# return on
#}
#
##
## toggle the search forward setting in the "search_flags" variable
## and display a message indicating the new default forward value.
##
#global function toggle_search_forward( on ) #PUBLIC #INT
#{
# if ( argcount() < 1 )
# on = !and( search_flags, SEARCH_FORWARD )
# else
# on = 0+on
#
# #
# # toggle the setting
# #
# if ( on )
# search_flags = or( search_flags, SEARCH_FORWARD )
# else
# search_flags = and( search_flags, not( SEARCH_FORWARD ))
#
# message( "%s searching is on.", on ? "Forward" : "Backward" )
# return on
#}
#
##
## toggle the search for a maximum match setting in the "search_flags" variable
## and display a message indicating the new default max match value.
##
#global function toggle_search_max_match( on ) #PUBLIC #INT
#{
# if ( argcount() < 1 )
# on = !and( search_flags, SEARCH_MAXIMAL_MATCH )
# else
# on = 0+on
#
# #
# # toggle the setting
# #
# if ( on )
# search_flags = or( search_flags, SEARCH_MAXIMAL_MATCH )
# else
# search_flags = and( search_flags, not( SEARCH_MAXIMAL_MATCH ))
#
# message( "Maximum match searching is %s.", on ? "on" : "off" )
# return on
#}
#
##
## toggle the search wraps setting in the "search_flags" variable
## and display a message indicating the new default wrap value.
##
#global function toggle_search_wrap( on ) #PUBLIC #INT
#{
# if ( argcount() < 1 )
# on = !and( search_flags, SEARCH_WRAPS )
# else
# on = 0+on
#
# #
# # toggle the setting
# #
# if ( on )
# search_flags = or( search_flags, SEARCH_WRAPS )
# else
# search_flags = and( search_flags, not( SEARCH_WRAPS ))
#
# message( "Wrap searching is %s.", on ? "on" : "off" )
# return on
#}
#
##
## toggle the search advance setting in the "search_flags" variable
## and display a message indicating the new default advance value.
##
#global function toggle_search_advance( on ) #PUBLIC #INT
#{
# if ( argcount() < 1 )
# on = !and( search_flags, SEARCH_ADVANCE )
# else
# on = 0+on
#
# #
# # toggle the setting
# #
# if ( on )
# search_flags = or( search_flags, SEARCH_ADVANCE )
# else
# search_flags = and( search_flags, not( SEARCH_ADVANCE ))
#
# message( "Advance search is %s.", on ? "on" : "off" )
# return on
#}
#
##
## toggle the search once per line setting in the "search_flags" variable
## and display a message indicating the new default once per line value.
##
#global function toggle_search_once( on ) #PUBLIC #INT
#{
# if ( argcount() < 1 )
# on = !and( search_flags, SEARCH_ONCE_PER_LINE )
# else
# on = 0+on
#
# #
# # toggle the setting
# #
# if ( on )
# search_flags = or( search_flags, SEARCH_ONCE_PER_LINE )
# else
# search_flags = and( search_flags, not( SEARCH_ONCE_PER_LINE ))
#
# message( "Once per line searching is %s.", on ? "on" : "off" )
# return on
#}
#
##
## toggle the search highlight setting in the "search_flags" variable
## and display a message indicating the new default highlight value.
##
#global function toggle_search_highlight( on ) #PUBLIC #INT
#{
# if ( argcount() < 1 )
# on = !and( search_flags, SEARCH_HIGHLIGHT )
# else
# on = 0+on
#
# #
# # toggle the setting
# #
# if ( on )
# search_flags = or( search_flags, SEARCH_HIGHLIGHT )
# else
# search_flags = and( search_flags, not( SEARCH_HIGHLIGHT ))
#
# message( "Highlight search is %s.", on ? "on" : "off" )
# return on
#}
global function quote_printf_string( str ) #PUBLIC #STR
{
local newstr = str
gsub( "%", "%%", newstr )
return newstr
}
#------------------ Wsearch functions --------------------#
#
# prompt for the search pattern and provide command history
#
local function replace_prompt( str )
{
return prompt_history( "REPLACE", " Replace " str " with: ", replace_pattern, 1, 1, "replace_prompt" )
}
# generic function that does either search or replace accross buffers
global function wsearch_replace( srch, replacement, dlgbox )
{
local priorBuffer = current_buffer
local sentinel
local sf
local found
local n
local orig_search_count = search_count ? search_count : 1
local forward
local replacing = ( argcount() > 1 && replacement ) ? TRUE : FALSE
sf = search_flags
sf = and( sf, not(SEARCH_WRAPS) )
forward = and(sf, SEARCH_FORWARD);
#
# search the remainder of the current buffer
#
save_position()
n = orig_search_count
if ( replacing )
found = replace( srch, replacement, sf)
else
found = search( srch, sf)
if ( found >= n )
{
restore_position( 0 )
if ( and( search_flags, SEARCH_CENTER_CURSOR ))
center_cursor()
highlightSearch()
return orig_search_count # found
}
restore_position( 1 )
#
# search the other buffers
#
forward ? (sentinel = next_buffer("", 0, 1)) : (sentinel = prev_buffer("", 0, 1));
do
{
if ( current_buffer == priorBuffer )
break
if ( replacing )
message( "Replacing in %s...", buffer_filename )
else
message( "Searching %s...", buffer_filename )
save_position()
forward ? goto_buffer_top() : goto_buffer_bottom();
n -= found
search_count = n
if ( replacing )
found = replace( srch, replacement, sf )
else
found = search( srch, sf )
if ( found >= n )
{
restore_position( 0 )
save_position()
message( "" )
create_buf_and_win(buffer_filename, dlgbox)
restore_position( 1 )
if ( and( search_flags, SEARCH_CENTER_CURSOR ))
center_cursor()
highlightSearch()
return orig_search_count # found
}
restore_position( 1 )
forward ? next_buffer("", 0, 1) : prev_buffer("", 0, 1);
}
while ( current_buffer != sentinel )
#
# search the current buffer above the current cursor position
#
current_buffer = priorBuffer
if ( replacing )
message( "Replacing in %s...", buffer_filename )
else
message( "Searching %s...", buffer_filename )
save_position()
begin_selection( INCLUSIVE_SELECTION )
forward ? goto_buffer_top() : goto_buffer_bottom();
n -= found
search_count = n
if ( replacing )
found = replace( srch, replacement, or( sf, SEARCH_BLOCK ))
else
found = search( srch, or( sf, SEARCH_BLOCK ))
remove_selection()
if ( found >= n )
{
restore_position( 0 )
save_position()
message( "" )
create_buf_and_win(buffer_filename, dlgbox)
restore_position( 1 )
if ( and( search_flags, SEARCH_CENTER_CURSOR ))
center_cursor()
highlightSearch()
return orig_search_count # found
}
restore_position( 1 )
# if we're searching globaly, then we know
# we'll get to the "no more found" case
if ( !and(search_flags, SEARCH_GLOBAL) )
warning("Pattern not found")
return orig_search_count - n + found # not found
}
## wsearch() search all buffers for a string
## wsearch_again() repeat prior wsearch in all buffers for a string
#
global function wsearch( srch, dlgbox ) #PUBLIC #INT
{
local sf = search_flags
local rc
# if no search argument given, prompt for one
if ( !srch )
{
srch = search_prompt()
if ( srch == "" )
return
}
search_pattern = srch
sf = or( sf, SEARCH_ALL_BUFFERS )
rc = wsearch_replace( srch, 0, dlgbox )
search_flags = sf
return rc
}
global function wsearch_again( srch, dlgbox ) #PUBLIC #INT
{
search_flags = or( search_flags, SEARCH_ADVANCE )
if ( !srch )
{
if ( search_pattern )
srch = search_pattern
else
return 0
srch = search_pattern
}
return wsearch( srch, dlgbox )
}
#------------------ Wreplace functions --------------------#
global function wreplace( srch, replacement )
{
# if no search argument given, prompt for one
if ( !srch )
{
srch = search_prompt()
if ( srch == "" )
return
}
# if no replacement argument given, prompt for one
if ( argcount() < 2 )
{
replacement = replace_prompt( srch )
if ( !replacement && ( current_key == KEYCODE_ESC ))
return
}
return wsearch_replace( srch, replacement )
}
global function wreplace_again( srch, replacement )
{
search_flags = or(search_flags, SEARCH_ADVANCE)
return wreplace( srch, replacement )
}
# freplace functions
global function background_freplace( srch, replacement, arrayOfFiles )
{
local i
local fn
local fileToOpen
local orig_buffer = current_buffer
local sys_buffer
local title
local dhTemp
local matches
local total_matches
local mode
title = sprintf( "Replace %s with %s", srch, replacement )
dhTemp = create_list_dialog( title, editor_helpfile, "grep_list_callback" )
begin_list_dialog( dhTemp )
for ( i in arrayOfFiles )
{
fileToOpen = arrayOfFiles[i]
if ( (fn = findfirst( fileToOpen )) )
{
do
{
fn = tolower( path_path( fileToOpen ) fn )
set_dialog_window( dhTemp, DWC_STATUSBARTEXT, "Replacing in " fn "..." )
# open the buffer as a system buffer
mode = filemode( fn )
if ( mode == -1 )
continue
if ( and(mode, _READ_ONLY) )
{
add_item_to_list( dhTemp, fn ": READ-ONLY FILE, NO REPLACEMENTS PERFORMED" )
continue
}
sys_buffer = current_buffer = \
create_buffer(fn, fn, BUFFER_SYSTEM + BUFFER_NO_UNDO )
search_count = MAX_SEARCH
matches = replace( srch, replacement, search_flags )
add_item_to_list( dhTemp, fn ": " matches " occurrences replaced", fn )
total_matches = total_matches + matches
write_buffer()
delete_buffer()
sys_buffer = 0
current_buffer = orig_buffer
} while ( (fn = findnext()) )
}
set_dialog_window( dhTemp, DWC_STATUSBARTEXT, total_matches " occurrences replaced" )
# parse the drive:directory from the filename and store in
# last path.
#
lastFReplacePath = path_path(fileToOpen) "*.*"
}
return total_matches
}
local lastFReplacePath
global function freplace( srch, replacement, listOfFiles, recursive )
{
local arrayOfFiles[]
local ret_val
# if no search argument given, prompt for one
if ( !srch )
{
srch = search_prompt()
if ( srch == "" )
return
}
# if no replacement argument given, prompt for one
if ( argcount() < 2 )
{
replacement = replace_prompt( srch )
if ( !replacement && ( current_key == KEYCODE_ESC ))
return
}
if ( !listOfFiles )
listOfFiles = open_dialog( lastFReplacePath, "Select files to freplace" )
if ( listOfFiles )
{
add_prompt_history( "SEARCH", srch )
add_prompt_history( "REPLACE", replacement )
add_prompt_history( "SRCHFILES", listOfFiles )
if ( tolower(confirm("Changes will not be undoable, continue?[yn] ", "yYnN")) != "y" )
return
if ( recursive )
arrayOfFiles = get_recursive_dir_list( listOfFiles )
else
split( listOfFiles, arrayOfFiles, ";" )
process_background( DISABLE_FOREGROUND )
ret_val = background_freplace( srch, replacement, arrayOfFiles )
process_background( END_BACKGROUND )
}
return ret_val
}