/****************************** Module Header ******************************* * * Module Name: locate.e * * Copyright (c) Netlabs EPM Distribution Project 2002 * * $Id$ * * =========================================================================== * * This file is part of the Netlabs EPM Distribution package and is free * software. You can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software * Foundation, in version 2 as it comes in the "COPYING" file of the * Netlabs EPM Distribution. This library is distributed in the hope that it * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * ****************************************************************************/ ; 'xcom l', 'xcom c' and repeatfind: ; ; o 'xcom l ' or ; 'xcom c ' ; can be specified without . Then the internal ; default options are used: +FAE. ; ; o Doubled or exclusive options may be specified. The last option wins. ; ; o 'xcom l' and 'xcom c' store their command line in the same internal var. ; It can be queried with getsearch and be set with setsearch. That var is ; empty on EPM's start. ; ; o repeatfind uses the previous search line of 'xcom l' or 'xcom c', but ; always executes 'xcom l'. It can't be used for repeated change. ; ; o All commands produce a message if nothing is found: "String not found". ; That is unusual for internal commands. That message is also written to ; the message box. ; Undocumented: ; display -8 ==> messages go only to the msg line, not to the msg box. ; display 8 ==> reenables messages from a previous display -8 ; The rest is documented in epmtech.inf. ; Bugs in the original defs, now workarounded: ; ; o Bugs of 'xcom l', 'xcom c' and repeatfind: ; ; - 'xcom l' and 'xcom c' don't move the cursor, repeatfind does. ; ; - With option r (reversed search), it also finds the search string at ; the cursor. ; ; - For search within a mark (option m), the search is restarted from ; the mark begin when the end was reached. ; ; - For search within a char mark, the whole lines where the mark starts ; and ends are searched, not only the marked area. ; ; o Bugs of the original 'Locate' = 'l' and 'Change' = 'c' commands: ; ; - The bugs of 'xcom l', 'xcom c' and repeatfind, except that the ; cursor is moved after 'l' or 'c'. ; ; - The cursor position after a 'c' was wrong: It was moved by the length ; of the search string, not of the replace string. ; ; o Bugs of 'xcom c' and the original 'Change' = 'c' command: ; ; - 'Change' within char mark processes the marked lines, as if ; it were line-marked, independent from the mark begin and end. ; ; - Grep or egrep replace/change within a mark doesn't work. Nothing is ; found when options m and (g or x) are active. It works in the whole ; file. Also search/locate doesn't have this problem. A workaround ; may be added in a later version. ; ; o The above bugs are fixed/workarounded by the current 'Locate' = 'l' ; and 'Change' = 'c' commands. ; ; o Without pre- and postprocessing, 'xcom l', 'xcom c' and repeatfind ; should only be used for forward find (locate) searches and not for ; replace (change). ; Remaining bugs: None. ; ; --------------------------------------------------------------------------- compile if not defined( SMALL) -- If compiled separately EA_comment 'This defines macros for saerch operations.' define INCLUDING_FILE = 'LOCATE.E' include 'stdconst.e' const tryinclude 'mycnf.e' const compile if not defined( NLS_LANGUAGE) NLS_LANGUAGE = 'ENGLISH' compile endif include NLS_LANGUAGE'.e' compile endif ; --------------------------------------------------------------------------- const compile if not defined( LOCATE_CIRCLE_STYLE) --LOCATE_CIRCLE_STYLE = 1 LOCATE_CIRCLE_STYLE = 5 -- filled oval compile endif compile if not defined( LOCATE_CIRCLE_COLOR1) --LOCATE_CIRCLE_COLOR1 = 16777220 -- 0x1000004 LOCATE_CIRCLE_COLOR1 = 16777231 -- 0x100000F complementary compile endif compile if not defined( LOCATE_CIRCLE_COLOR2) -- for styles 2 and 4 only --LOCATE_CIRCLE_COLOR2 = 16777218 -- 0x1000002 LOCATE_CIRCLE_COLOR2 = 16777216 -- 0x1000000 complementary compile endif compile if not defined( INTERNAL_SEARCH_OPTIONS) -- o These options are prepended internally on executing 'xcom l' or -- 'xcom c'. -- o All internal options can be inverted by an existing option letter. -- o The additional options ';', '"', 'v' and 'l' are handled outside of -- the 'xcom' commands, so shouldn't be added here. INTERNAL_SEARCH_OPTIONS = '+fae' compile endif compile if not defined( EXCLUDE_SEARCH_OPTIONS_LIST) -- o This should list all valid option chars. -- o Each word consists of excluding options. -- o Additionally, an option can be disabled by specifying it with a -- preceded '!' char. -- o The last option wins. -- o Unknown option chars are ignored by 'xcom l' and 'xcom c'. 'E.g. -- '/w' is interpreted as 'w'. EXCLUDE_SEARCH_OPTIONS_LIST = '+- fr bt am ecv wgx ^ l * ; " k n' compile endif ; --------------------------------------------------------------------------- defproc GetAllSearchOptions AllOptions = SpaceStr( EXCLUDE_SEARCH_OPTIONS_LIST, 0) return AllOptions ; --------------------------------------------------------------------------- defproc SortSearchOptions( InOptions) OutOptions = InOptions do once = 1 to 1 -- Check parms if InOptions = '' then leave endif InOptionWords = InsertSpaceStr( InOptions, '[^!]') OutOptionWords = '' --dprintf( 'InOptionWords = 'InOptionWords) do w1 = 1 to words( InOptionWords) InOpt = word( InOptionWords, w1) --dprintf( 'w1 = 'w1', InOpt = 'InOpt', OutOptionWords = 'OutOptionWords) fInserted = 0 do w2 = 1 to words( OutOptionWords) OutOpt = word( OutOptionWords, w2) --dprintf( 'w1 = 'w1', InOpt = 'InOpt', OutOptionWords = 'OutOptionWords', w2 = 'w2', OutOpt = 'OutOpt) if strip( InOpt, 'L', '!') << strip( OutOpt, 'L', '!') then --dprintf( 'Insert 'InOpt' before 'OutOpt) -- Insert it if w2 = 1 then OutOptionWords = InOpt OutOptionWords fInserted = 1 leave else LeftWord = subword( OutOptionWords, 1, w2 - 1) RightWord = subword( OutOptionWords, w2) if LeftWord <> '' then OutOptionWords = LeftWord' ' endif OutOptionWords = OutOptionWords''InOpt RightWord fInserted = 1 leave endif endif enddo if not fInserted then -- Append it --dprintf( 'Append 'InOpt) if OutOptionWords <> '' then OutOptionWords = OutOptionWords' ' endif OutOptionWords = OutOptionWords''InOpt endif enddo OutOptions = SpaceStr( OutOptionWords, 0) enddo return OutOptions ; --------------------------------------------------------------------------- ; Normalizes options string and filters out multiple and excluding options. ; Processes '!' prefixes to remove options. ; Syntax: SearchOptions = NormalizeSearchOptions( SearchOptions [, CompleteOptions [, PrependInternal]]) ; CompleteOptions = 0|1 (default = 0) ; Behavior for options starting with '!' (negate options): ; 0 SearchOptions is not a complete option string. Other options ; (except the internal options) will be prepended. Keep all ; negate options in the output string. ; 1 SearchOptions is a complete option string. It will be passed ; to 'xcom l' or 'xcom c'. Remove all negate options in the ; output string, because '!' prefixes are not known by 'xcom l' ; and 'xcom c'. ; PrependInternal = 0|1 (default = 0) ; If 1 is specified, the internal options are prepended. Then the ; output search options are used for menu item check states. defproc NormalizeSearchOptions( SearchOptions) do once = 1 to 1 fCompleteOptions = (arg( 2) = '1') fPrependInternal = (arg( 3) = '1') OptionList = EXCLUDE_SEARCH_OPTIONS_LIST -- See NEWMENU.E:"defc SearchOptionsMenuCmd". OutdatedList = 'uihp1q' -- Prepend internal options if fPrependInternal then SearchOptions = INTERNAL_SEARCH_OPTIONS''SearchOptions endif -- Check parms if SearchOptions = '' then leave endif -- Lowercase SearchOptions = lowcase( SearchOptions) --dprintf( 'NormalizeSearchOptions: SearchOptions = 'SearchOptions) -- Check for valid options AllOpt = '!d'OptionList''OutdatedList vp = verify( SearchOptions, AllOpt) if vp then InvalidOpt = substr( SearchOptions, vp, 1) 'SayError NormalizeSearchOptions: Invalid search option "'InvalidOpt'" specified, SearchOptions = 'SearchOptions return endif -- Convert option chars to words, remove all spaces SearchOptWords = InsertSpaceStr( SearchOptions, '[^!]') --dprintf( 'NormalizeSearchOptions: SearchOptWords = 'SearchOptWords) NewSearchOptionWords = '' do w = 1 to words( SearchOptWords) Opt = word( SearchOptWords, w) --dprintf( 'NormalizeSearchOptions: Opt = 'Opt) -- Ignore outdated additional options - may be specified in history if pos( Opt, OutdatedList) then iterate endif -- Handle ! prefix to negate an option wp1 = wordpos( Opt, NewSearchOptionWords) --dprintf( 'NormalizeSearchOptions: Opt = 'Opt', wp1 = 'wp1) if wp1 then -- Already present - ignore elseif leftstr( Opt, 1) = '!' then RestOpt = substr( Opt, 2) wp2 = wordpos( RestOpt, NewSearchOptionWords) if wp2 then -- Remove matching non-! option NewSearchOptionWords = delword( NewSearchOptionWords, wp2, 1) elseif fCompleteOptions then -- Ignore else -- Append option if NewSearchOptionWords then NewSearchOptionWords = NewSearchOptionWords' ' endif NewSearchOptionWords = NewSearchOptionWords''Opt endif else -- Process excludes of OptionList for Opt do once = 1 to 1 -- Find Opt in OptionList and get OptionWord p4 = pos( Opt, ' 'OptionList' ') --dprintf( 'NormalizeSearchOptions: Opt = 'Opt', wp3 = 'wp3', p4 = 'p4) if not p4 then leave endif p5 = lastpos( ' ', leftstr( ' 'OptionList' ', p4 - 1)) --dprintf( 'NormalizeSearchOptions: Opt = 'Opt', wp3 = 'wp3', p4 = 'p4', p5 = 'p5) if not p5 then leave endif p6 = pos( ' ', substr( ' 'OptionList' ', p4 + 1)) + p4 --dprintf( 'NormalizeSearchOptions: Opt = 'Opt', wp3 = 'wp3', p4 = 'p4', p5 = 'p5', p6 = 'p6) if not p6 then leave endif OptionWord = substr( ' 'OptionList' ', p5 + 1, p6 - p5 - 1) --dprintf( 'NormalizeSearchOptions: Opt = 'Opt', OptionWord = >'OptionWord'<') if not OptionWord then leave endif -- Remove other options of OptionWord from NewSearchOptionWords ExcludeOptWords = InsertSpaceStr( OptionWord, '[^!]') do wp4 = 1 to words( ExcludeOptWords) -- Next word ExcludeOpt = subword( ExcludeOptWords, wp4, 1) -- Ignore same as Opt if ExcludeOpt = Opt then iterate endif -- Search and remove it wp5 = wordpos( ExcludeOpt, NewSearchOptionWords) if not wp5 then iterate endif NewSearchOptionWords = delword( NewSearchOptionWords, wp5, 1) --dprintf( 'NormalizeSearchOptions: Opt = 'Opt', NewSearchOptionWords = >'NewSearchOptionWords'<') enddo enddo wp3 = wordpos( '!'Opt, NewSearchOptionWords) if wp3 then -- Remove matching ! option NewSearchOptionWords = delword( NewSearchOptionWords, wp3, 1) else -- Append option if NewSearchOptionWords then NewSearchOptionWords = NewSearchOptionWords' ' endif NewSearchOptionWords = NewSearchOptionWords''Opt endif endif enddo SearchOptions = SpaceStr( NewSearchOptionWords, 0) -- Sort SearchOptions = SortSearchOptions( SearchOptions) enddo return SearchOptions ; --------------------------------------------------------------------------- defproc GetCombindSearchOptions( UserOptions) --dprintf( 'GetCombindSearchOptions: UserOptions = 'UserOptions', LastOptions = 'GetLastSearchOptions()) -- For a search from the Search dialog, prepend nagated options available -- in the Search dialog (without !l!;!" to keep them from last search) UserOptions = '!t!b!w!g!x!^!k!*'UserOptions LastSearchOptions = GetLastSearchOptions() MenuOnlyOptions = '' if not pos( 'l', LastSearchOptions) then MenuOnlyOptions = MenuOnlyOptions'!l' endif if not pos( ';', LastSearchOptions) then MenuOnlyOptions = MenuOnlyOptions'!;' endif if not pos( '"', LastSearchOptions) then MenuOnlyOptions = MenuOnlyOptions'!"' endif CombinedSearchOptions = INTERNAL_SEARCH_OPTIONS || GetDefaultSearchOptions() || LastSearchOptions || MenuOnlyOptions || UserOptions return CombinedSearchOptions ; --------------------------------------------------------------------------- ; Preprocessor 1 for Find and Change. It's called before the search and ; o combines the internal and default search options with the user search ; options. ; o normalizes the search options (lowercase, remove doubled and excluding, ; remove negated). ; o removes the M option from the default search options when the current ; file is not marked. ; Returns: SearchOptions defproc ProcessSearchOptions( UserOptions) UserOptions = lowcase( UserOptions) fStoreLastSearchOptions = (arg( 2) = 1) SearchOptions = GetCombindSearchOptions( UserOptions) --dprintf( 'ProcessSearchOptions 1: SearchOptions = 'SearchOptions', UserOptions = 'UserOptions) fCompleteOptions = 1 SearchOptions = NormalizeSearchOptions( SearchOptions, fCompleteOptions) --dprintf( 'ProcessSearchOptions 2: SearchOptions = 'SearchOptions) -- Remove 'd' option added by the Search dialog if pos( 'd', UserOptions) then SearchOptions = RemoveSearchOptions( 'd', SearchOptions) endif -- Remove prior additional options that are not supported anymore SearchOptions = RemoveSearchOptions( 'uihp1q', SearchOptions) -- Switch to All if Mark is default and no text marked, but don't disable -- 'm' from UserOptions to make it work as expected. if not FileIsMarked() then -- Remove 'm' from DefaultOptions SearchOptions = RemoveSearchOptions( 'm', SearchOptions) endif if fStoreLastSearchOptions then -- Store as new LastSearchOptions --dprintf( 'ProcessSearchOptions 3: SetLastSearchOptions( 'SearchOptions')') SetLastSearchOptions( SearchOptions) endif -- For option 'v', determine case-sentitiveness from mode setting Mode = GetMode() fCaseSensitive = QueryModeKey( Mode, 'CaseSensitive') if fCaseSensitive then SearchOptions = ChangeStr( 'v', SearchOptions, 'e') else SearchOptions = ChangeStr( 'v', SearchOptions, 'c') endif -- If option 'm' (marked area) is set, set 'CurrentFile' instead of -- 'LoadedFiles', because only one file can be marked. if pos( 'm', SearchOptions) then SearchOptions = RemoveSearchOptions( 'l', SearchOptions) endif SearchOptions = NormalizeSearchOptions( SearchOptions) return SearchOptions ; --------------------------------------------------------------------------- ; Ensure that lastsearchpos is reset on relink definit universal lastsearchpos lastsearchpos = '' ; --------------------------------------------------------------------------- ; Preprocessor 2 for Find and Change. It's called before the search and ; o determines fSameSearch (find next, when file id, search string, search ; options and last cursor pos. haven't changed) ; o deletes previosly saved temp. search args on fSameSearch ; o removes T and B options on fSameSearch (find next). (Also the Search ; dialog doesn't switch automatically from Top or Bottom to Cursor then.) ; o determines fSearch (if search should really be executed) ; o corrects the cursor position before a search action, when required as a ; workaround for 'xcom l' bugs to avoid finding false strings. ; Returns: FilteredSearchOptions defproc ProcessSearchPos( SearchOptions, PrevSearchOptions, SearchString, PrevSearchString, fid, SearchMode, var Flags) -- All flags in one var to save args universal lastsearchpos --dprintf( ' ProcessSearchPos: SearchOptions = 'SearchOptions', PrevSearchOptions = 'PrevSearchOptions) do once = 1 to 1 -- Init output vars FilteredSearchOptions = SearchOptions Flags = '' parse value lastsearchpos with PrevFid'|'PrevPos'|'PrevStartPos'|'FirstFid'|'FirstStartPos'|'RestSearchPos parse value RestSearchPos with FirstFoundFid'|'FirstFoundPos'|'FirstChangedFid'|'FirstChangedPos'|'RestSearchPos parse value RestSearchPos with FirstFileEndReached'|'FileSwitchedBySearch'|'RestSearchPos parse value RestSearchPos with PrevFoundFid'|'PrevFoundPos'|'PrevChangedFid'|'PrevChangedPos'|'RestSearchPos parse value RestSearchPos with PrevMarkPos'|'PrevSearchMode'|'PrevDirection'|'PrevSearchRc'|'PrevSearchLen'|'PrevCounters parse value PrevPos with PrevLine PrevCol . fLoadedFiles = (pos( 'l', SearchOptions) > 0) -- Get Direction Direction = GetSearchDirection( SearchOptions) fDirectionChanged = (Direction <> PrevDirection & PrevDirection) -- Check if cursor pos. has changed fCursorPosChanged = not (.line = PrevLine & .col = PrevCol) -- Determine fSameSearch (find next) -- For the Find after fRepeat, option D is removed from SearchOptions. fSameSearchString = (SearchString = PrevSearchString) fSameOptions = (RemoveSearchOptions( 'd+f-rtb', SearchOptions) = RemoveSearchOptions( 'd+f-rtb', PrevSearchOptions)) --dprintf( ' ProcessSearchPos: FileSwitchedBySearch = 'FileSwitchedBySearch) fSameFile = (fid = PrevFid) fSameMark = (GetMarkPos() = PrevMarkPos) fSameSearch = 0 --dprintf( ' ProcessSearchPos: fSameSearchString = 'fSameSearchString', fSameOptions = 'fSameOptions', fSameFile = 'fSameFile', fSameMark = 'fSameMark) do once2 = 1 to 1 if not fSameSearchString then --dprintf( ' ProcessSearchPos: fSameSearch = 0 because: not fSameSearchString') leave elseif not fSameOptions then --dprintf( ' ProcessSearchPos: fSameSearch = 0 because: not fSameOptions') leave elseif not fSameFile & not FileSwitchedBySearch then --dprintf( ' ProcessSearchPos: fSameSearch = 0 because: not fSameFile & not FileSwitchedBySearch') leave elseif not fSameMark & not fLoadedFiles then --dprintf( ' ProcessSearchPos: fSameSearch = 0 because: not fSameMark & not fLoadedFiles') leave elseif fCursorPosChanged & not FileSwitchedBySearch then --dprintf( ' ProcessSearchPos: fSameSearch = 0 because: fCursorPosChanged & not FileSwitchedBySearch') leave endif fSameSearch = 1 enddo -- Determine fFirstChange for undo fFirstChange = 0 if not fSameSearch & SearchMode = 'c' then fFirstChange = 1 endif -- Determine fChangeAll fChangeAll = 0 if pos( '*', SearchOptions) & SearchMode = 'c' then fChangeAll = 1 endif -- Get mark data mktype = marktype() pGetMark( mkfirstline, mklastline, mkfirstcol, mklastcol, mkfid) if fSameSearch then -- fSameSearch: Remove 't' and 'b' for the search execution -- (not from PrevSearchArgs) --dprintf( ' ProcessSearchPos: Removing t and b') FilteredSearchOptions = RemoveSearchOptions( 'tbd', FilteredSearchOptions) else lastsearchpos = '' --dprintf( '## ProcessSearchPos: Reset lastsearchpos, fSameSearch = 'fSameSearch) if pos( 'm', SearchOptions) & mktype = 'CHAR' & Direction = '+' then -- New search: Place cursor before the mark .lineg = mkfirstline -- .lineg suppresses scrolling .col = mkfirstcol -- New search: Remove option 't' (not present for 'Start at cursor') FilteredSearchOptions = RemoveSearchOptions( 't', FilteredSearchOptions) elseif pos( 'm', SearchOptions) & mktype = 'CHAR' & Direction = '-' then -- New search: Place cursor after the mark .lineg = mklastline -- .lineg suppresses scrolling .col = mklastcol + 1 -- New search: Remove option 'b' (not present for 'Start at cursor') FilteredSearchOptions = RemoveSearchOptions( 'b', FilteredSearchOptions) else -- New search: Don't remove an option FilteredSearchOptions = SearchOptions endif endif -- Remove '*' (change all) FilteredSearchOptions = RemoveSearchOptions( '*', FilteredSearchOptions) -- Disable further search if the previous search with the same fid, -- SearchString, SearchOptions and SearchPos wasn't successfull. -- o This is required for t and b to prevent looping after a -- single search stop at the end. -- o This is required for after a failed search to not move the cursor -- again. fSearch = 1 if fSameSearch & not fDirectionChanged & PrevSearchRc then fSearch = 0 --dprintf( ' ProcessSearchPos 1: fSearch = 0') endif if not fSearch then leave endif -- Determine cursor move before the following 'xcom l' or 'xcom c' -- Change should process the string at cursor. The cursor pos may result -- from a previous locate. -- If there is no string to change at the cursor, it processes the next -- string. For that no cursor move is required. -- If the cursor was moved manually after the last search, don't move it -- before the next search. -- Move only after a successful last search to not find the same string -- again. fMoveCursor = 0 if not (SearchMode = 'c' & PrevSearchMode = 'l') & fid = PrevFid & not fDirectionChanged & not fCursorPosChanged & not PrevSearchRc then fMoveCursor = 1 endif -- Move cursor to not find the string at cursor (again) if fMoveCursor then if Direction = '+' then -- Forward: move amount of PrevSearchLen right if PrevSearchLen = '' then PrevSearchLen = 0 endif next = .col + PrevSearchLen if next >= length( textline( .line)) + 1 then if .line < .last then down .col = 1 else fSearch = 0 -- can't move down at the bottom --dprintf( ' ProcessSearchPos 2: fSearch = 0') endif else .col = next endif else -- Backward: move 1 char left next = .col - 1 if next < 1 then if .line > 1 then up end_line else fSearch = 0 -- can't move up at the top --dprintf( ' ProcessSearchPos 3: fSearch = 0') endif else .col = next endif endif endif if not fSearch then leave endif -- Check if cursor is after or before the mark for start from cursor if pos( 'm', SearchOptions) & not pos( 't', SearchOptions) & not pos( 'b', SearchOptions) then if Direction = '+' then -- Forward if .line > mklastline then fSearch = 0 --dprintf( ' ProcessSearchPos 4: M, C, F: fSearch = 0') elseif .line = mklastline & .col > mklastcol then fSearch = 0 --dprintf( ' ProcessSearchPos 5: M, C, F: fSearch = 0') endif else -- Backward if .line < mkfirstline then fSearch = 0 --dprintf( ' ProcessSearchPos 6: M, C, B: fSearch = 0') elseif .line = mkfirstline & .col < mkfirstcol then fSearch = 0 --dprintf( ' ProcessSearchPos 7: M, C, B: fSearch = 0') endif endif endif if not fSearch then leave endif enddo --dprintf( ' ProcessSearchPos: fDirectionChanged = 'fDirectionChanged', Direction = 'Direction', PrevDirection = 'PrevDirection', PrevSearchRc = 'PrevSearchRc', PrevSearchLen = 'PrevSearchLen) --dprintf( ' ProcessSearchPos: fCursorPosChanged = 'fCursorPosChanged', fMoveCursor = 'fMoveCursor', fSearch = 'fSearch', fSameSearch = 'fSameSearch) -- Reset it after processing if FileSwitchedBySearch then FileSwitchedBySearch = 0 -- Save FileSwitchedBySearch lastsearchpos = PrevFid'|'PrevPos'|'PrevStartPos'|' || FirstFid'|'FirstStartPos'|' || FirstFoundFid'|'FirstFoundPos'|'FirstChangedFid'|'FirstChangedPos'|' || FirstFileEndReached'|'FileSwitchedBySearch'|' || PrevFoundFid'|'PrevFoundPos'|'PrevChangedFid'|'PrevChangedPos'|' || PrevMarkPos'|'PrevSearchMode'|'PrevDirection'|'PrevSearchRc'|'PrevSearchLen'|' || PrevCounters endif -- Assemble flags Flags = fSearch fSameSearch fFirstChange fChangeAll return FilteredSearchOptions ; --------------------------------------------------------------------------- ; Postprocessor 3 for Find. It determines fRepeat and is called ; o for char mark or ; o if comments or literals should be excluded. defproc ProcessPostFind( fCharMark, fIncludeComments, fIncludeLiterals, fSameSearch, var fRepeat) Mode = GetMode() --dprintf( ' ProcessPostFind: fIncludeComments = 'fIncludeComments', fIncludeLiterals = 'fIncludeLiterals) do once = 1 to 1 -- Init output var fRepeat = 0 lrc = 0 -- Check if inside of mark if fCharMark then -- Check if found string is fully marked SearchLen = getpminfo( EPMINFO_LSLENGTH) if not InMark( .line, .col, SearchLen) then -- Found string is not completely in mark if fSameSearch then -- After mark lrc = -273 --dprintf( ' ProcessPostFind: lrc = 'lrc) leave -- once else -- Before mark fRepeat = 1 --dprintf( ' ProcessPostFind: fRepeat = 'fRepeat) leave -- once endif endif --dprintf( ' ProcessPostFind: lrc = 'lrc', at '.line','.col', fSameSearch = 'fSameSearch', fRepeat = 'fRepeat) endif -- Check if inside of comment if not fIncludeComments then if InsideComment( Mode) then fRepeat = 1 --dprintf( ' ProcessPostFind: ### Inside comment, mode = 'Mode) leave -- once endif endif -- Check if inside of literal if not fIncludeLiterals then if InsideLiteral( Mode) then fRepeat = 1 --dprintf( ' ProcessPostFind: ### Inside literal, mode = 'Mode) leave -- once endif endif enddo -- once rc = lrc return ; --------------------------------------------------------------------------- ; Preprocessor 4 for Change. It's called before Change ; o for grep or egrep change to determine OldLineLen or ; o for char mark or ; o if comments or literals should be excluded. ; Sets rc = 0 found ; -273 not found ; -1 endless loop recognition (should not happen) defproc ProcessFindBeforeChange( TempFindArgs, fGrepChange, fCharMark, fIncludeComments, fIncludeLiterals, fSameSearch, var OldLineLen) OldLineLen = 0 Mode = GetMode() SavedLine = 0 SavedCol = 0 display -15 'xcom l 'TempFindArgs display 15 lrc = rc --dprintf( '# ProcessFindBeforeChange: TempFindArgs = 'TempFindArgs', lrc = 'lrc', at '.line','.col) do forever if lrc then -- Not found leave -- forever endif fRepeatFind = 0 do once = 1 to 1 -- Check if inside of mark if fCharMark then -- Check if found string is fully marked SearchLen = getpminfo( EPMINFO_LSLENGTH) if not InMark( .line, .col, SearchLen) then -- Found string is not completely in mark if fSameSearch then -- After mark lrc = -273 --dprintf( '# ProcessFindBeforeChange: lrc = 'lrc', at '.line','.col' - not marked, after mark, stop') leave -- once else -- Before mark fRepeatFind = 1 --dprintf( '# ProcessFindBeforeChange: lrc = 'lrc', at '.line','.col' - not marked, before mark, fRepeat') leave -- once endif endif endif -- Check if inside of comment if not fIncludeComments then if InsideComment( Mode) then fRepeatFind = 1 --dprintf( '# ProcessFindBeforeChange: lrc = 'lrc', at '.line','.col' - ### Inside comment, mode = 'Mode) leave -- once endif endif -- Check if inside of literal if not fIncludeLiterals then if InsideLiteral( Mode) then fRepeatFind = 1 --dprintf( '# ProcessFindBeforeChange: lrc = 'lrc', at '.line','.col' - ### Inside literal, mode = 'Mode) leave -- once endif endif --dprintf( '# ProcessFindBeforeChange: lrc = 'lrc', at '.line','.col) -- Found: Go back and let Change process this OldLineLen = length( textline( .line)) --dprintf( 'OldLineLen = 'OldLineLen', .line = '.line) enddo -- once --dprintf( '# ProcessFindBeforeChange: lrc = 'lrc', at '.line','.col' - fRepeatFind = 'fRepeatFind) if fRepeatFind then -- Found, but not valid (outside of mark or comment or -- literal, if activated) display -15 repeatfind display 15 lrc = rc -- Recognize an infinite loop (required for postprocessing) -- This happens at the end of a loop, when repeatfind has found the -- last occurence, which is an excluded comment or literal. Then -- the cursor remains at the last pos. if .line = SavedLine & .col = SavedCol then --dprintf( '## ProcessFindBeforeChange: lrc = 'lrc', endless loop at '.line','.col) lrc = -273 leave -- forever endif SavedLine = .line SavedCol = .col elseif not lrc then -- Found leave -- forever endif enddo -- forever rc = lrc return ; --------------------------------------------------------------------------- ; This sets rc = -18 if FirstStartPos is reached. It is processed only for ; fLoadedFiles, not for normal find and change in current file. In other ; cases rc = 0 is set. defproc ProcessPostSearchPos( SearchOptions, FirstFid, FirstStartPos, FirstFileEndReached) -- For LoadedFiles: Stop if FirstStartPos is reached. do once = 1 to 1 lrc = 0 getfileid fid fLoadedFiles = (pos( 'l', SearchOptions) > 0) if not fLoadedFiles then leave elseif fid <> FirstFid then leave elseif not FirstFileEndReached then leave endif parse value FirstStartPos with FirstStartLine FirstStartCol . if .line > FirstStartLine | (.line = FirstStartLine & .col >= FirstStartCol) then lrc = -18 endif enddo rc = lrc return ; --------------------------------------------------------------------------- ; LastFindArgs and LastChangeArgs are no longer universals. To make them ; global across all EPM windows, they are saved in NEPMD.INI only. ; --------------------------------------------------------------------------- defproc GetLastFindArgs KeyPath = '\NEPMD\Var\Search\LastFindArgs' LastFindArgs = QueryConfigKey( KeyPath) --dprintf( 'GetLastFindArgs: LastFindArgs = 'LastFindArgs) return LastFindArgs ; --------------------------------------------------------------------------- defproc GetLastChangeArgs KeyPath = '\NEPMD\Var\Search\LastChangeArgs' LastChangeArgs = QueryConfigKey( KeyPath) return LastChangeArgs ; --------------------------------------------------------------------------- defproc GetDefaultSearchOptions KeyPath = '\NEPMD\User\Search\DefaultOptions' DefaultSearchOptions = QueryConfigKey( KeyPath) --dprintf( 'GetDefaultSearchOptions: DefaultSearchOptions = 'DefaultSearchOptions) return DefaultSearchOptions ; --------------------------------------------------------------------------- defproc GetLastSearchOptions KeyPath = '\NEPMD\Var\Search\LastOptions' LastSearchOptions = QueryConfigKey( KeyPath) -- Handle case when LastSearchOptions is unset if LastSearchOptions = '' then LastSearchOptions = GetDefaultSearchOptions() endif --dprintf( 'GetLastSearchOptions: LastSearchOptions = 'LastSearchOptions) return LastSearchOptions ; --------------------------------------------------------------------------- defproc SetLastFindArgs KeyPath = '\NEPMD\Var\Search\LastFindArgs' LastFindArgs = arg( 1) call WriteConfigKey( KeyPath, LastFindArgs) --dprintf( 'SetLastFindArgs: LastFindArgs = 'LastFindArgs) return ; --------------------------------------------------------------------------- defproc SetLastChangeArgs KeyPath = '\NEPMD\Var\Search\LastChangeArgs' LastChangeArgs = arg( 1) call WriteConfigKey( KeyPath, LastChangeArgs) return ; --------------------------------------------------------------------------- ; This is usually called by ProcessSearchOptions with arg( 2) = 1. defproc SetLastSearchOptions KeyPath = '\NEPMD\Var\Search\LastOptions' LastSearchOptions = NormalizeSearchOptions( arg( 1)) call WriteConfigKey( KeyPath, LastSearchOptions) --dprintf( 'SetLastSearchOptions: LastSearchOptions = 'LastSearchOptions) -- Sync. with LastFindArgs LastFindArgs = GetLastFindArgs() if LastFindArgs <> '' then ParseFindArgs( LastFindArgs, Delim, SearchString, UserOptions) NewLastFindArgs = Delim''SearchString''Delim''LastSearchOptions --dprintf( 'SetLastSearchOptions: SetLastFindArgs( 'NewLastFindArgs')') SetLastFindArgs( NewLastFindArgs) endif -- Sync. with LastChangeArgs LastChangeArgs = GetLastChangeArgs() if LastChangeArgs <> '' then ParseChangeArgs( LastChangeArgs, Delim, SearchString, ReplaceString, UserOptions) NewLastChangeArgs = Delim''SearchString''Delim''ReplaceString || Delim''LastSearchOptions SetLastChangeArgs( NewLastChangeArgs) endif return ; --------------------------------------------------------------------------- defproc SetDefaultSearchOptions KeyPath = '\NEPMD\Var\Search\DefaultOptions' DefaultSearchOptions = NormalizeSearchOptions( arg( 1)) call WriteConfigKey( KeyPath, DefaultSearchOptions) --dprintf( 'SetDefaultSearchOptions: DefaultSearchOptions = 'DefaultSearchOptions) return ; --------------------------------------------------------------------------- defc SetDefaultSearchOptions SetDefaultSearchOptions( strip( arg( 1))) ; --------------------------------------------------------------------------- ; Configures 'Restore search options on EPM startup'. L = last | D = default. ; RegDefaults value is L. defc RestoreSearchOptionsCmd RestoreType = upcase( strip( leftstr( arg( 1), 1))) KeyPath = '\NEPMD\User\AutoRestore\SearchOptions' call WriteConfigKey( KeyPath, RestoreType) SetMenuAttribute( 'restoredefaultsearchoptions', MIA_CHECKED, RestoreType <> 'D') SetMenuAttribute( 'restorelastsearchoptions', MIA_CHECKED, RestoreType <> 'L') ; --------------------------------------------------------------------------- ; Sets rc = -257 if invalid number of parameters ; 0 otherwise defproc ParseFindArgs( Args, var Delim, var SearchString, var UserOptions) do once = 1 to 1 rc = 0 fHandleEmptyArgs = (arg( 5) = 1) -- If 'd' is in UserOptions, the search stems from SearchDlg. -- Filter out \1\1\1\1'd' arg from search dialog for RepeatFind fDialogRepeat = 0 if Args = \1\1\1\1'd' then fDialogRepeat = 1 Args = '' endif -- Handle RepeatFind if fHandleEmptyArgs & Args = '' then -- If no args, query args LastFindArgs = GetLastFindArgs() TmpDelim = substr( LastFindArgs, 1, 1) -- get 1st delimiter parse value LastFindArgs with (TmpDelim) SearchString (TmpDelim) UserOptions -- Ensure that option d is removed if not coming from the search dialog UserOptions = RemoveSearchOptions( 'd', UserOptions) if fDialogRepeat then -- Ensure that option d is added UserOptions = UserOptions'd' endif -- Assemble Args Args = TmpDelim''SearchString''TmpDelim''UserOptions -- Process the parsing of Args again to recognize a possible change of -- DefaultSearchOptions in the meantime. endif -- Parse Args SearchString = '' UserOptions = '' Delim = substr( Args, 1, 1) -- get 1st delimiter if not wordpos( count( Delim, Args), '1 2') then rc = -257 -- Invalid number of parameters leave endif parse value Args with (Delim) SearchString (Delim) UserOptions UserOptions = SortSearchOptions( strip( UserOptions, 'T', Delim)) --dprintf( 'ParseFindArgs: Args = 'Args) enddo return ; --------------------------------------------------------------------------- ; Sets rc = -257 if invalid number of parameters ; 0 otherwise defproc ParseChangeArgs( Args, var Delim, var SearchString, var ReplaceString, var UserOptions) do once = 1 to 1 rc = 0 LastChangeArgs = GetLastChangeArgs() fHandleEmptyArgs = (arg( 6) = 1) -- If 'd' is in UserOptions, the search stems from SearchDlg. -- Filter out 'd' arg from search dialog for RepeatFind fDialogRepeat = 0 if Args = \1\1\1\1'd' then fDialogRepeat = 1 Args = '' endif -- Handle RepeatChange if fHandleEmptyArgs & Args = '' then -- If no args, query args LastChangeArgs = GetLastChangeArgs() TmpDelim = substr( LastChangeArgs, 1, 1) -- get 1st delimiter parse value LastChangeArgs with (TmpDelim) SearchString (TmpDelim) ReplaceString (TmpDelim) UserOptions -- Ensure that option d is removed if not coming from the search dialog UserOptions = RemoveSearchOptions( 'd', UserOptions) if fDialogRepeat then -- Ensure that option d is added UserOptions = UserOptions'd' endif -- Assemble Args Args = TmpDelim''SearchString''TmpDelim''ReplaceString''TmpDelim''UserOptions endif -- Parse Args SearchString = '' ReplaceString = '' UserOptions = '' Delim = substr( Args, 1, 1) -- get 1st delimiter if not wordpos( count( Delim, Args), '2 3') then rc = -257 -- Invalid number of parameters leave endif parse value Args with (Delim) SearchString (Delim) ReplaceString (Delim) UserOptions UserOptions = SortSearchOptions( strip( UserOptions, 'T', Delim)) enddo return ; --------------------------------------------------------------------------- ; Syntax: locate ![!] ; The first char will be taken as delimitter, in this case '!'. ; o New: Without args, a FindNext will be executed. ; o Added a new search option: '!t!b'. This overrides any occurance of ; 't' and 'b' in DefaultSearchOptions. ; o Added a new search option: 'v'. This enables automatic case, dependant ; on current mode. It sets 'c' or 'e' internally. ; o This DEFC also gets executed by the slash ('/') command and by the ; search dialog. The search dialog adds option 'D'. ; o Executing 'Change, then find' from the Search dialog executes first a ; Change (change next, incl. current pos.) and then a Find. defc RepeatFind, L, Locate Args = strip( arg( 1)) --dprintf( ' ') --dprintf( overlay( ' RepeatFind ', copies( '-', 60), 4)) if Args = '' | lowcase( Args) = \1\1\1\1'd' then -- Find next CheckArgs = GetLastFindArgs() else -- New args specified CheckArgs = Args endif --dprintf( 'RepeatFind: Args = 'Args', PrevFindArgs = 'GetLastFindArgs()', CheckArgs = 'CheckArgs) fLoadedFiles = 0 if CheckArgs <> '' then -- Parse UserOptions from CheckArgs call ParseFindArgs( CheckArgs, Delim, SearchString, UserOptions) -- Must save UserOptions if <> '' for the case that empty Args are passed. -- Prepend internal and default options and normalize search options. CheckOptions = GetCombindSearchOptions( UserOptions) fCompleteOptions = 1 CheckOptions = NormalizeSearchOptions( CheckOptions, fCompleteOptions) -- Determine fLoadedFiles fLoadedFiles = (pos( 'l', CheckOptions) > 0) endif --dprintf( 'RepeatFind: fLoadedFiles = 'fLoadedFiles', SearchOptions = 'SearchOptions) -- Depending on fLoadedFiles, execute the suited cmd if fLoadedFiles then 'RepeatFindAllFiles 'Args else 'RepeatFindThisFile 'Args endif ; --------------------------------------------------------------------------- ; Similar to RepeatFindThisFileQuiet, but puts out Msg. defc RepeatFindThisFile Msg = RepeatFindThisFileQuiet( arg( 1)) if Msg then 'SayError 'Msg endif ; --------------------------------------------------------------------------- ; Finds next occurence in current file. Sets Msg if not found. Returns Msg. defproc RepeatFindThisFileQuiet universal lastsearchpos universal lastcommand universal nodismiss universal vepm_pointer do once = 1 to 1 lastcommand = 'Locate' sayerror 0 -- delete previous message from messageline PrevFindArgs = GetLastFindArgs() PrevChangeArgs = GetLastChangeArgs() --dprintf( 'RepeatFindThisFileQuiet: PrevFindArgs = 'PrevFindArgs) SearchLen = 0 fRepeat = 0 fStop = 0 Msg = '' SearchMode = 'l' pSave_Pos( BeforeSearchPos) mouse_setpointer WAIT_POINTER Args = strip( arg( 1)) --dprintf( overlay( ' RepeatFindThisFileQuiet ', copies( '-', 60), 4)) --dprintf( 'RepeatFindThisFileQuiet: Args = 'Args) -- Parse Args. The 5th parm activates: If Args is empty, use -- PrevFindArgs instead. fUsePrevIfArgsEmpty = 1 call ParseFindArgs( Args, Delim, SearchString, UserOptions, fUsePrevIfArgsEmpty) UserOptions = NormalizeSearchOptions( UserOptions) --dprintf( 'RepeatFindThisFileQuiet: SearchString = 'SearchString', UserOptions = 'UserOptions', Args = 'Args) -- Build list of search args with options, last option wins. -- Save the universal var here. Later ProcessSearchPos changes -- SearchOptions if required. FindArgs = Delim''SearchString''Delim''UserOptions fSearchDialog = (pos( 'd', UserOptions)) --dprintf( '--- FindArgs = 'FindArgs', arg( 1) = 'arg( 1)) --dprintf( 'PrevFindArgs = 'PrevFindArgs) -- Save current args as last args --dprintf( 'RepeatFindThisFileQuiet: SetLastFindArgs( 'FindArgs')') call SetLastFindArgs( FindArgs) -- Parse PrevFindArgs call ParseFindArgs( PrevFindArgs, PrevDelim, PrevSearchString, PrevUserOptions) -- Parse PrevChangeArgs -- The current SearchString is compared with that of PrevChangeArgs. -- If another string was specified, then PrevChangeArgs is reset to ''. call ParseChangeArgs( PrevChangeArgs, TmpDelim, ChgSearchString, ChgReplaceString, ChgUserOptions) if SearchString = ChgSearchString then -- Reset the SearchOptions in PrevChangeArgs for the next Change while -- keeping the previous ReplaceString. ChangeArgs = Delim''ChgSearchString''Delim''ChgReplaceString''Delim''UserOptions call SetLastChangeArgs( ChangeArgs) else -- Reset LastChangeArgs when a new search string was specified. call SetLastChangeArgs( '') endif getfileid fid -- Prepend internal and default options and normalize search options. -- Remove 'm' if file not marked. Resolve 'v' and replace with 'e' or -- 'c'. Remove negated options. fStoreLastSearchOptions = 1 SearchOptions = ProcessSearchOptions( UserOptions, fStoreLastSearchOptions) PrevSearchOptions = ProcessSearchOptions( PrevUserOptions) --dprintf( 'RepeatFindThisFile after ProcessSearchOptions: SearchOptions = 'SearchOptions) --dprintf( '--- FindArgs = 'FindArgs', arg( 1) = 'arg( 1)) --dprintf( 'PrevFindArgs = 'PrevFindArgs) -- Ensure that the 'd' option is removed before adding it to history. -- Otherwise FindNext would cause another entry. HistoryEntry = Delim''SearchString''Delim''RemoveSearchOptions( 'd', SearchOptions) 'AddToHistory SEARCH' HistoryEntry -- Get Direction Direction = GetSearchDirection( SearchOptions) -- Refresh dialog controls or menu item check states if fSearchDialog then if GetAVar( 'searchdlgopened') then -- Possible improvement: Refresh only if fBackward or fLoadedFiles changed -- Menu items if nodismiss then 'RefreshMenuSearchText' endif endif else -- Search dialog if GetAVar( 'searchdlgopened') then SetSearchDlgOption( Direction) endif endif --dprintf( 'RepeatFindThisFileQuiet: before ProcessSearchPos: SearchOptions = 'SearchOptions', PrevSearchOptions = 'PrevSearchOptions) -- Maybe move cursor and remove T and B search options for a FindNext FilteredSearchOptions = ProcessSearchPos( SearchOptions, PrevSearchOptions, SearchString, PrevSearchString, fid, SearchMode, Flags) -- Flags are set parse value Flags with fSearch fSameSearch . --dprintf( 'RepeatFindThisFileQuiet: after ProcessSearchPos: SearchOptions = 'SearchOptions', FilteredSearchOptions = 'FilteredSearchOptions', PrevSearchOptions = 'PrevSearchOptions) --dprintf( 'RepeatFindThisFileQuiet: after ProcessSearchPos: fSearch = 'fSearch', fSameSearch = 'fSameSearch) -- Query vars from previous search parse value lastsearchpos with PrevFid'|'PrevPos'|'PrevStartPos'|'FirstFid'|'FirstStartPos'|'RestSearchPos parse value RestSearchPos with FirstFoundFid'|'FirstFoundPos'|'FirstChangedFid'|'FirstChangedPos'|'RestSearchPos parse value RestSearchPos with FirstFileEndReached'|'FileSwitchedBySearch'|'RestSearchPos parse value RestSearchPos with PrevFoundFid'|'PrevFoundPos'|'PrevChangedFid'|'PrevChangedPos'|'RestSearchPos parse value RestSearchPos with PrevMarkPos'|'PrevSearchMode'|'PrevDirection'|'PrevSearchRc'|'PrevSearchLen'|'PrevCounters if PrevCounters = '' | Direction <> PrevDirection then PrevCounters = '0 0 0 0 0 0' endif parse value PrevCounters with PrevNum PrevLines PrevFiles PrevChgNum PrevChgLines PrevChgFiles if PrevFoundPos = '' then PrevFoundPos = BeforeSearchPos endif -- Init vars parse value PrevCounters with FoundNum FoundLines FoundFiles ChgNum ChgLines ChgFiles if PrevStartPos then StartPos = PrevStartPos else StartPos = BeforeSearchPos endif if FirstFid = '' then FirstFid = fid endif if FirstStartPos = '' then FirstStartPos = StartPos endif --dprintf( 'RepeatFindThisFileQuiet: lastsearchpos prev. = 'lastsearchpos) if not fSearch then -- Set by ProcessSearchPos -- Leave after parsing and init vars for msg fStop = 1 if PrevSearchRc then lrc = PrevSearchRc else lrc = -273 endif --dprintf( '>>>>> 1) fStop = 'fStop', lrc = 'lrc) leave endif -- Build args for xcom l FilteredSearchArgs = Delim''SearchString''Delim''FilteredSearchOptions fCharMark = (pos( 'm', SearchOptions) > 0 & MarkTypeOfFile() = 'CHAR') fLoadedFiles = (pos( 'l', SearchOptions) > 0) fIncludeComments = (pos( ';', SearchOptions) > 0) fIncludeLiterals = (pos( '"', SearchOptions) > 0) --dprintf( 'RepeatFindThisFileQuiet: SearchOptions = 'SearchOptions', fIncludeComments = 'fIncludeComments', fIncludeLiterals = 'fIncludeLiterals) --dprintf( ' FilteredSearchOptions = 'FilteredSearchOptions) --dprintf( ' UserOptions = 'UserOptions) --dprintf( 'RepeatFindThisFileQuiet: FilteredSearchArgs = 'FilteredSearchArgs) display -14 'xcom l 'FilteredSearchArgs lrc = rc SearchLine = .line SearchCol = getpminfo( EPMINFO_SEARCHPOS) -- = .col SearchLen = getpminfo( EPMINFO_LSLENGTH) -- This is correct, also for grep display 14 fStop = (lrc <> 0) if lrc then --dprintf( '>>>>> 2) fStop = 'fStop', lrc = 'lrc) --dprintf( '>> Restore pos from '.line','.col' to PrevFoundPos = 'PrevFoundPos', lrc after xcom l = 'lrc) pRestore_Pos( PrevFoundPos) leave endif -- Determine fRepeat. This is required -- o for char mark or -- o if comments or literals should be excluded. -- Sets rc = -273 if found string is after char mark. -- Returns fRepeat = 1 if before char mark or within a comment -- or literal. if fCharMark | not fIncludeComments | not fIncludeLiterals then ProcessPostFind( fCharMark, fIncludeComments, fIncludeLiterals, fSameSearch, fRepeat) lrc = rc fStop = (lrc <> 0) if lrc then --dprintf( '>>>>> 3) fStop = 'fStop', lrc = 'lrc) --dprintf( '>> Restore pos from '.line','.col' to PrevFoundPos = 'PrevFoundPos', lrc after ProcessPostLocate = 'lrc) pRestore_Pos( PrevFoundPos) endif --dprintf( '* fRepeat = 'fRepeat', fStop = 'fStop', lrc = 'lrc' at '.line','.col', StartPos = 'subword( StartPos, 1, 2)', FirstStartPos = 'subword( FirstStartPos, 1, 2)', PrevFoundPos = 'subword( PrevFoundPos, 1, 2)) endif enddo -- once -- For LoadedFiles: Stop if FirstStartPos is reached. if not lrc then ProcessPostSearchPos( SearchOptions, FirstFid, FirstStartPos, FirstFileEndReached) lrc = rc if lrc = -18 then pRestore_Pos( FirstStartPos) fStop = 1 --dprintf( 'FirstFileEndReached = 'FirstFileEndReached', fid = 'fid', FirstFid = 'FirstFid', .line = '.line', .col = '.col', FirstStartPos = 'FirstStartPos) endif endif pSave_Pos( ThisPos) if not lrc & not fRepeat then -- Eventually scroll to cursor pos -- Must scroll before the pos. is saved call ScrollAfterSearch( BeforeSearchPos, ThisPos, SearchLen) pSave_Pos( ThisPos) endif -- Counters if lrc then Counters = PrevCounters elseif fRepeat then Counters = PrevCounters else -- Count found occurences FoundNum = PrevNum + 1 -- Count lines with found occurences FoundLines = PrevLines FirstFoundLine = word( FirstFoundPos, 1) if FirstFoundLine then PrevFoundLine = word( PrevFoundPos, 1) else -- PrevFoundPos is initialized to BeforeSearchPos. Therefore handle -- that case different. PrevFoundLine = '' endif if SearchLine <> PrevFoundLine & not (fid = FirstFoundFid & SearchLine = FirstFoundLine) then FoundLines = PrevLines + 1 endif --dprintf( '** FoundNum = PrevNum + 1 = 'FoundNum', SearchLine = 'SearchLine', PrevFoundLine = 'PrevFoundLine', PrevFoundPos = 'PrevFoundPos', FirstFoundLine = 'FirstFoundLine) -- Count files with found occurences FoundFiles = PrevFiles if fid <> PrevFoundFid & fid <> FirstFoundFid then FoundFiles = PrevFiles + 1 endif --dprintf( '** fid = 'fid', PrevFoundFid = 'PrevFoundFid', FoundFiles = 'FoundFiles', FoundLines = 'FoundLines) Counters = FoundNum FoundLines FoundFiles ChgNum ChgLines ChgFiles PrevFoundFid = fid PrevFoundPos = ThisPos endif -- Set universals ThisMarkPos = GetMarkPos() --dprintf( 'Store current pos as lastsearchpos: 'ThisPos', PrevSearchRc = 'PrevSearchRc) lastsearchpos = fid'|'ThisPos'|'StartPos'|' || FirstFid'|'FirstStartPos'|' || FirstFoundFid'|'FirstFoundPos'|'FirstChangedFid'|'FirstChangedPos'|' || FirstFileEndReached'|'FileSwitchedBySearch'|' || PrevFoundFid'|'PrevFoundPos'|'PrevChangedFid'|'PrevChangedPos'|' || ThisMarkPos'|'SearchMode'|'Direction'|'lrc'|'SearchLen'|' || Counters --dprintf( 'Current search pos = 'lastsearchpos) -- If the search was executed from the search dialog, the focus is usually -- set to it again after this action. The following switches it back to -- the edit window and allows to use key defs for the next actions without -- having to manually activate the edit window. if fSearchDialog then if GetAVar( 'searchdlgopened') then KeyPath = '\NEPMD\User\SearchDialog\FocusToEditWindow' on = QueryConfigKey( KeyPath) if on then hWndClient = getpminfo( EPMINFO_EDITCLIENT) 'PostMe SetFocus' hWndClient endif endif endif --dprintf( 'fRepeat = 'fRepeat', fStop = 'fStop', ThisPos = 'ThisPos', PrevPos = 'PrevPos', fSameSearch = 'fSameSearch) if fRepeat then -- Process fRepeat --dprintf( 'RepeatFindThisFileQuiet: Process fRepeat +++++++++++++++++') -- The position must be advanced before the next search. -- RepeatFind -> ProcessSearchPos does that by checking -- lastsearchpos. -- Recursive call, doesn't use the correct rc with a cmd Msg = RepeatFindThisFileQuiet() return -- Important to keep the correct rc elseif fStop then if fSameSearch & PrevSearchRc then -- Don't override previous message else -- Give message if fSameSearch then if PrevChgNum then if fLoadedFiles then Msg = ChgNum' of 'FoundNum' occurence(s) changed on 'ChgLines' of 'FoundLines' line(s) in 'ChgFiles' of 'FoundFiles' file(s)' else Msg = ChgNum' of 'FoundNum' occurence(s) changed on 'ChgLines' of 'FoundLines' line(s) in this file' endif else if fLoadedFiles then Msg = FoundNum' occurence(s) found on 'FoundLines' line(s) in 'FoundFiles' file(s)' else Msg = FoundNum' occurence(s) found on 'FoundLines' line(s) in this file' endif endif MsgAdd = '' if not fIncludeComments & not fIncludeLiterals then MsgAdd = ' - comments and literals excluded' elseif not fIncludeComments then MsgAdd = ' - comments excluded' elseif not fIncludeLiterals then MsgAdd = ' - literals excluded' endif Msg = Msg''MsgAdd'.' else Msg = sayerrortext( -273)'.' endif endif -- The posted SetFocus above requires the PostMe here 'PostMe HighlightCursor' else -- Highlight it -- The posted SetFocus above requires the PostMe here 'PostMe HighlightMatch 'SearchLine SearchCol SearchLen endif mouse_setpointer vepm_pointer rc = lrc --dprintf( 'RepeatFindThisFileQuiet: rc = 'rc', Msg = 'Msg) return Msg ; --------------------------------------------------------------------------- -- o If last occurence is commented and comments are excluded, it stops at -- the forelast occurence and doesn't switch to next file. -- Instead of stop it should switch to the next file. -- o Stops where it started, gives Msg, but then starts searching again. -- o After a file is searched, its StartPos is not restored. Get it from -- PrevStartPos? Now always restores 1,1. defc RepeatFindAllFiles universal lastsearchpos do once = 1 to 1 Msg = '' Args = strip( arg( 1)) PrevFindArgs = GetLastFindArgs() --dprintf( overlay( ' RepeatFindAllFiles ', copies( '-', 60), 4)) -- Parse Args fUsePrevIfArgsEmpty = 1 call ParseFindArgs( Args, Delim, SearchString, UserOptions, fUsePrevIfArgsEmpty) UserOptions = NormalizeSearchOptions( UserOptions) --dprintf( 'Args = 'Args', Delim = 'Delim', SearchString = 'SearchString', UserOptions = 'UserOptions', PrevFindArgs = 'PrevFindArgs) -- Parse PrevFindArgs call ParseFindArgs( PrevFindArgs, PrevDelim, PrevSearchString, PrevUserOptions) PrevUserOptions = NormalizeSearchOptions( PrevUserOptions) parse value lastsearchpos with PrevFid'|'PrevPos'|'PrevStartPos'|'FirstFid'|'FirstStartPos'|'RestSearchPos parse value RestSearchPos with FirstFoundFid'|'FirstFoundPos'|'FirstChangedFid'|'FirstChangedPos'|'RestSearchPos parse value RestSearchPos with FirstFileEndReached'|'FileSwitchedBySearch'|'RestSearchPos parse value RestSearchPos with PrevFoundFid'|'PrevFoundPos'|'PrevChangedFid'|'PrevChangedPos'|'RestSearchPos parse value RestSearchPos with PrevMarkPos'|'PrevSearchMode'|'PrevDirection'|'PrevSearchRc'|'PrevSearchLen'|'PrevCounters parse value PrevPos with PrevLine PrevCol . getfileid fid -- Prepend internal and default options and normalize search options. -- Remove 'm' if file not marked. Resolve 'v' and replace with 'e' or -- 'c'. Remove negated options. fStoreLastSearchOptions = 1 SearchOptions = ProcessSearchOptions( UserOptions, fStoreLastSearchOptions) --dprintf( '1 RepeatFindAllFiles: UserOptions = 'UserOptions', SearchOptions = 'SearchOptions) PrevSearchOptions = ProcessSearchOptions( PrevUserOptions) --dprintf( '2 RepeatFindAllFiles: PrevUserOptions = 'PrevUserOptions', PrevSearchOptions = 'PrevSearchOptions) -- Get Direction Direction = GetSearchDirection( SearchOptions) -- Check if cursor pos. has changed fCursorPosChanged = not (.line = PrevLine & .col = PrevCol) -- Determine fSameSearch (find next) -- For the Find after fRepeat, option D is removed from SearchOptions. fSameSearchString = (SearchString = PrevSearchString) fSameOptions = (RemoveSearchOptions( 'd+f-rtb', SearchOptions) = RemoveSearchOptions( 'd+f-rtb', PrevSearchOptions)) fSameFile = (fid = PrevFid) --dprintf( ' RepeatFindAllFiles: fSameSearchString = 'fSameSearchString', fSameOptions = 'fSameOptions) --dprintf( ' RepeatFindAllFiles: FileSwitchedBySearch = 'FileSwitchedBySearch', fSameFile = 'fSameFile', fCursorPosChanged = 'fCursorPosChanged) fSameSearch = 0 do once2 = 1 to 1 if not fSameSearchString then leave elseif not fSameOptions then leave elseif not fSameFile & not FileSwitchedBySearch then leave elseif fCursorPosChanged & not FileSwitchedBySearch then leave endif fSameSearch = 1 enddo --dprintf( '>> RepeatFindAllFiles: fSameSearch = 'fSameSearch) -- Always search in whole files, not in mark UserOptions = RemoveSearchOptions( 'ma', UserOptions) -- Ensure that a possible 'M' in default_user_options is overridden UserOptions = UserOptions'a' --dprintf( '3 RepeatFindAllFiles: UserOptions = 'UserOptions) -- Uncheck 'Marked area' of search dialog if GetAVar( 'searchdlgopened') then SetSearchDlgOption( 'a') endif if fSameSearch then -- Current file: start from cursor. Next file: start from top or bottom -- For next file, the move to the top or bottom is processed below UserOptions = RemoveSearchOptions( 'tb', UserOptions) -- Ensure that a possible 't' or 'b' in default_user_options is overridden -- '!t!b' doesn't exist in standard EPM UserOptions = UserOptions'!t!b' -- Normalize UserOptions UserOptions = NormalizeSearchOptions( UserOptions) --dprintf( '4 RepeatFindAllFiles: UserOptions = 'UserOptions) -- Write PrevFindArgs to config PrevFindArgs = Delim''SearchString''Delim''UserOptions --dprintf( 'RepeatFindAllFiles: SetLastFindArgs( 'PrevFindArgs')') call SetLastFindArgs( PrevFindArgs) --dprintf( '# RepeatFindAllFiles: SetLastFindArgs( 'PrevFindArgs')') else -- This is a new search - reset lastsearchpos lastsearchpos = '' -- Parse again after reset parse value lastsearchpos with PrevFid'|'PrevPos'|'PrevStartPos'|'FirstFid'|'FirstStartPos'|'RestSearchPos parse value RestSearchPos with FirstFoundFid'|'FirstFoundPos'|'FirstChangedFid'|'FirstChangedPos'|'RestSearchPos parse value RestSearchPos with FirstFileEndReached'|'FileSwitchedBySearch'|'RestSearchPos parse value RestSearchPos with PrevFoundFid'|'PrevFoundPos'|'PrevChangedFid'|'PrevChangedPos'|'RestSearchPos parse value RestSearchPos with PrevMarkPos'|'PrevSearchMode'|'PrevDirection'|'PrevSearchRc'|'PrevSearchLen'|'PrevCounters parse value PrevPos with PrevLine PrevCol . -- Save FirstFid, FirstStartLine and FirstStartCol getfileid FirstFid pSave_Pos( FirstStartPos) PrevStartPos = FirstStartPos FirstFileEndReached = 0 -- Save FirstFid, FirstStartPos, PrevStartPos, FirstFileEndReached lastsearchpos = PrevFid'|'PrevPos'|'PrevStartPos'|' || FirstFid'|'FirstStartPos'|' || FirstFoundFid'|'FirstFoundPos'|'FirstChangedFid'|'FirstChangedPos'|' || FirstFileEndReached'|'FileSwitchedBySearch'|' || PrevFoundFid'|'PrevFoundPos'|'PrevChangedFid'|'PrevChangedPos'|' || PrevMarkPos'|'PrevSearchMode'|'PrevDirection'|'PrevSearchRc'|'PrevSearchLen'|' || PrevCounters --dprintf( '# RepeatFindAllFiles 1: lastsearchpos = 'lastsearchpos) --dprintf( ' RepeatFindAllFiles: Stored FirstFid = 'FirstFid', FirstStartLine = '.line', FirstStartCol = '.col) --dprintf( '#* RepeatFindAllFiles: Init StartPos = 'FirstStartPos' for '.filename) endif 'VSyncCursor' do forever -- Search first file from cursor and next file from top or bottom getfileid fid -- Find next - call RepeatFindThisFileQuiet rc = 0 Msg = RepeatFindThisFileQuiet( Args) lrc = rc --dprintf( overlay( ' Back to RepeatFindAllFiles ', copies( '-', 60), 4)) --dprintf( '# RepeatFindAllFiles: RepeatFindThisFileQuiet, rc = 'lrc', pos = '.line','.col', '.filename) -- Parse again after RepeatFindThisFileQuiet parse value lastsearchpos with PrevFid'|'PrevPos'|'PrevStartPos'|'FirstFid'|'FirstStartPos'|'RestSearchPos parse value RestSearchPos with FirstFoundFid'|'FirstFoundPos'|'FirstChangedFid'|'FirstChangedPos'|'RestSearchPos parse value RestSearchPos with FirstFileEndReached'|'FileSwitchedBySearch'|'RestSearchPos parse value RestSearchPos with PrevFoundFid'|'PrevFoundPos'|'PrevChangedFid'|'PrevChangedPos'|'RestSearchPos parse value RestSearchPos with PrevMarkPos'|'PrevSearchMode'|'PrevDirection'|'PrevSearchRc'|'PrevSearchLen'|'PrevCounters parse value PrevPos with PrevLine PrevCol . parse value FirstStartPos with FirstStartLine FirstStartCol . if not lrc & FirstFoundFid = '' then FirstFoundFid = fid pSave_Pos( FirstFoundPos) endif if lrc then -- Restore StartPos if fid = FirstFid then pRestore_Pos( FirstStartPos) --dprintf( '#* RepeatFindAllFiles: Restore FirstStartPos = 'FirstStartPos' for '.filename', lrc = 'lrc', FirstFileEndReached = 'FirstFileEndReached) if FirstFileEndReached = 1 then -- Start reached - stop searching lrc = -18 --dprintf( '#* RepeatFindAllFiles: Stop at '.line','.col', lrc = 'lrc', '.filename) endif else pRestore_Pos( PrevStartPos) --dprintf( '#* RepeatFindAllFiles: Restore PrevStartPos = 'PrevStartPos' for '.filename) endif if lrc = -18 then -- Don't search in next file when FirstStartPos is reached again. leave -- forever else -- Not found - pos. in current file already restored by RepeatFindThisFileQuiet, -- but that is after going to top or bottom if fid = FirstFid then FirstFileEndReached = 1 endif -- Next file if Direction = '+' then nextfile else prevfile endif getfileid fid --dprintf( '# RepeatFindAllFiles: Switched to next file, fid = 'fid', FirstFid = 'FirstFid', .filename = '.filename) if fid = FirstFid then PrevStartPos = FirstStartPos else pSave_Pos( PrevStartPos) --dprintf( '# RepeatFindAllFiles: Saved PrevStartPos to '.line .col', .filename = '.filename) endif -- Start from top or bottom of file if Direction = '+' then top .col = 1 else bottom endline endif -- Reset pos. counters after switching files to get lines counter right PrevFoundPos = '' PrevChangedPos = '' endif PrevSearchRc = 0 FileSwitchedBySearch = 1 -- This is reset by ProcessSearchPos endif -- Save FirstFileEndReached, PrevSearchRc, PrevStartPos, FileSwitchedBySearch lastsearchpos = PrevFid'|'PrevPos'|'PrevStartPos'|' || FirstFid'|'FirstStartPos'|' || FirstFoundFid'|'FirstFoundPos'|'FirstChangedFid'|'FirstChangedPos'|' || FirstFileEndReached'|'FileSwitchedBySearch'|' || PrevFoundFid'|'PrevFoundPos'|'PrevChangedFid'|'PrevChangedPos'|' || PrevMarkPos'|'PrevSearchMode'|'PrevDirection'|'PrevSearchRc'|'PrevSearchLen'|' || PrevCounters --dprintf( '# RepeatFindAllFiles 2: lastsearchpos = 'lastsearchpos) if not lrc then -- Found - let RepeatFindThisFileQuiet highlight the occurence leave endif enddo -- forever enddo -- once rc = lrc if Msg then 'SayError 'Msg endif ; --------------------------------------------------------------------------- ; o Executing 'Change, then find' from the Search dialog executes first a ; Change (change next, incl. current pos.) and then a Find. defc RepeatChange, C, Change Args = strip( arg( 1)) --dprintf( ' ') --dprintf( overlay( ' RepeatChange ', copies( '-', 60), 4)) if Args = '' | lowcase( Args) = \1\1\1\1'd'then -- Change next CheckArgs = GetLastChangeArgs() else -- New args specified CheckArgs = Args endif --dprintf( 'RepeatChange: Args = 'Args', PrevChangeArgs = 'GetLastChangeArgs()', CheckArgs = 'CheckArgs) fLoadedFiles = 0 if CheckArgs <> '' then -- Parse UserOptions from CheckArgs call ParseChangeArgs( CheckArgs, TmpDelim, SearchString, ReplaceString, UserOptions) -- Prepend internal and default options and normalize search options. CheckOptions = GetCombindSearchOptions( UserOptions) fCompleteOptions = 1 CheckOptions = NormalizeSearchOptions( CheckOptions, fCompleteOptions) -- Determine fLoadedFiles fLoadedFiles = (pos( 'l', CheckOptions) > 0) endif --dprintf( 'RepeatChange: fLoadedFiles = 'fLoadedFiles', SearchOptions = 'SearchOptions) if fLoadedFiles then 'RepeatChangeAllFiles 'Args else 'RepeatChangeThisFile 'Args endif ; --------------------------------------------------------------------------- ; Similar to RepeatChangeThisFileQuiet, but puts out Msg. defc RepeatChangeThisFile Msg = RepeatChangeThisFileQuiet( arg( 1)) if Msg then 'SayError 'Msg endif ; --------------------------------------------------------------------------- ; Changes next occurence in current file. Sets Msg if not found. Returns Msg. defproc RepeatChangeThisFileQuiet universal lastsearchpos universal stay -- if 1, then restore pos even after a successful change universal lastcommand universal nodismiss universal vepm_pointer do once = 1 to 1 lastcommand = 'Change' sayerror 0 -- delete previous message from messageline PrevFindArgs = GetLastFindArgs() PrevChangeArgs = GetLastChangeArgs() SearchLen = 0 ReplaceLen = 0 fRepeat = 0 fStop = 0 Msg = '' SearchMode = 'c' pSave_Pos( BeforeSearchPos) mouse_setpointer WAIT_POINTER Args = strip( arg( 1)) --dprintf( overlay( ' RepeatChangeThisFileQuiet ', copies( '-', 60), 4)) -- Parse Args. The 6th parm activates: If Args is empty, use -- PrevChangeArgs instead. fUsePrevIfArgsEmpty = 1 call ParseChangeArgs( Args, Delim, SearchString, ReplaceString, UserOptions, fUsePrevIfArgsEmpty) UserOptions = NormalizeSearchOptions( UserOptions) --dprintf( 'RepeatChangeThisFileQuiet: SearchString = 'SearchString', ReplaceString = 'ReplaceString', UserOptions = 'UserOptions', Args = 'Args) -- Build list of change args with options, last option wins. -- Save the universal var here. Later ProcessSearchPos changes -- SearchOptions if required. ChangeArgs = Delim''SearchString''Delim''ReplaceString''Delim''UserOptions -- Set PrevFindArgs as well, to use first Ctrl+F and then Ctrl+C for to -- operate on the same SearchString. Even a ChangeNext should synchronize it. FindArgs = Delim''SearchString''Delim''UserOptions fSearchDialog = (pos( 'd', UserOptions)) --dprintf( '--- ChangeArgs = 'ChangeArgs', arg( 1) = 'arg( 1)) --dprintf( '--- FindArgs = 'FindArgs', arg( 1) = 'arg( 1)) --dprintf( 'PrevChangeArgs = 'PrevChangeArgs', PrevFindArgs = 'PrevFindArgs) -- Save current args as last args call SetLastChangeArgs( ChangeArgs) --dprintf( 'RepeatChangeThisFileQuiet: SetLastFindArgs( 'FindArgs')') call SetLastFindArgs( FindArgs) call ParseFindArgs( PrevFindArgs, TmpDelim, PrevFindSearchString, PrevFindUserOptions) -- If PrevChangeArgs was reset by the last search ... if PrevChangeArgs = '' then -- ... get args from last search, not from last change PrevChangeArgs = Delim''PrevFindSearchString''Delim''ReplaceString''Delim''PrevFindUserOptions endif call ParseChangeArgs( PrevChangeArgs, TmpDelim, PrevSearchString, PrevReplaceString, PrevUserOptions) getfileid fid -- Prepend default options and normalize search options fStoreLastSearchOptions = 1 SearchOptions = ProcessSearchOptions( UserOptions, fStoreLastSearchOptions) PrevSearchOptions = ProcessSearchOptions( PrevUserOptions) -- Ensure that the 'd' option is removed before adding it to history. -- Otherwise FindNext would cause another entry. HistoryEntry = Delim''SearchString''Delim''ReplaceString''Delim''RemoveSearchOptions( 'd', SearchOptions) 'AddToHistory SEARCH' HistoryEntry -- Get Direction Direction = GetSearchDirection( SearchOptions) -- Refresh dialog controls or menu item check states if fSearchDialog then if GetAVar( 'searchdlgopened') then -- Possible improvement: Refresh only if fBackward or fLoadedFiles changed -- Menu items if nodismiss then 'RefreshMenuSearchText' endif endif else -- Search dialog if GetAVar( 'searchdlgopened') then SetSearchDlgOption( Direction) endif endif --dprintf( 'RepeatChangeThisFileQuiet: before ProcessSearchPos: SearchOptions = 'SearchOptions', PrevSearchOptions = 'PrevSearchOptions) -- Maybe move cursor and remove T and B search options for a FindNext FilteredSearchOptions = ProcessSearchPos( SearchOptions, PrevSearchOptions, SearchString, PrevSearchString, fid, SearchMode, Flags) -- Flags are set parse value Flags with fSearch fSameSearch fFirstChange fChangeAll --dprintf( 'RepeatChangeThisFileQuiet: after ProcessSearchPos: SearchOptions = 'SearchOptions', FilteredSearchOptions = 'FilteredSearchOptions', PrevSearchOptions = 'PrevSearchOptions) --dprintf( 'RepeatChangeThisFileQuiet: after ProcessSearchPos: fSearch = 'fSearch', fSameSearch = 'fSameSearch', fFirstChange = 'fFirstChange', fChangeAll = 'fChangeAll) -- Query vars from previous search parse value lastsearchpos with PrevFid'|'PrevPos'|'PrevStartPos'|'FirstFid'|'FirstStartPos'|'RestSearchPos parse value RestSearchPos with FirstFoundFid'|'FirstFoundPos'|'FirstChangedFid'|'FirstChangedPos'|'RestSearchPos parse value RestSearchPos with FirstFileEndReached'|'FileSwitchedBySearch'|'RestSearchPos parse value RestSearchPos with PrevFoundFid'|'PrevFoundPos'|'PrevChangedFid'|'PrevChangedPos'|'RestSearchPos parse value RestSearchPos with PrevMarkPos'|'PrevSearchMode'|'PrevDirection'|'PrevSearchRc'|'PrevSearchLen'|'PrevCounters if PrevCounters = '' | Direction <> PrevDirection then PrevCounters = '0 0 0 0 0 0' endif parse value PrevCounters with PrevNum PrevLines PrevFiles PrevChgNum PrevChgLines PrevChgFiles if PrevFoundPos = '' then PrevFoundPos = BeforeSearchPos endif -- Init vars parse value PrevCounters with FoundNum FoundLines FoundFiles ChgNum ChgLines ChgFiles StartPos = '' if fid = PrevFid then if PrevStartPos <> '' then StartPos = PrevStartPos endif endif if StartPos = '' then StartPos = BeforeSearchPos endif if FirstFid = '' then FirstFid = fid endif if FirstStartPos = '' then FirstStartPos = StartPos endif --dprintf( 'RepeatChangeThisFileQuiet: lastsearchpos prev. = 'lastsearchpos) if not fSearch then -- Set by ProcessSearchPos -- Leave after parsing and init vars for msg fStop = 1 lrc = -273 leave endif OldLineLen = 0 NewLineLen = 0 fGrepChange = (verify( SearchOptions, 'gx', 'M') <> 0) fCharMark = (pos( 'm', SearchOptions) > 0 & MarkTypeOfFile() = 'CHAR') fLoadedFiles = (pos( 'l', SearchOptions) > 0) fIncludeComments = (pos( ';', SearchOptions) > 0) fIncludeLiterals = (pos( '"', SearchOptions) > 0) --dprintf( 'RepeatChangeThisFileQuiet: SearchOptions = 'SearchOptions', fIncludeComments = 'fIncludeComments', fIncludeLiterals = 'fIncludeLiterals) -- Check if Find must be executed before Change. That's the case -- o for grep or egrep change to determine OldLineLen or -- o for char mark or -- o if comments or literals should be excluded. -- Sets rc = 0 found -- -273 not found -- -1 endless loop recognition (should not happen) -- Different from ProcessPostFind, the fRepeat loop is here processed -- for the preprocessor Find and not for the Change cmd. Processing -- these checks here after Change would come too late. if fGrepChange | fCharMark | not fIncludeComments | not fIncludeLiterals then TempFindArgs = Delim''SearchString''Delim''FilteredSearchOptions ProcessFindBeforeChange( TempFindArgs, fGrepChange, fCharMark, fIncludeComments, fIncludeLiterals, fSameSearch, OldLineLen) lrc = rc fStop = (lrc <> 0) if lrc then --dprintf( '>> Restore pos from '.line','.col' to PrevFoundPos = 'PrevFoundPos', lrc after ProcessFindBeforeChange = 'lrc) pRestore_Pos( PrevFoundPos) leave -- once else -- Must remove t and b from SearchOptions if ProcessFindBeforeChange -- has found a string. Then it stops at that pos. 'xcom c' should -- then process the string at that pos. FilteredSearchOptions = RemoveSearchOptions( 'tb', FilteredSearchOptions) endif endif -- Build args for xcom c FilteredChangeArgs = Delim''SearchString''Delim''ReplaceString''Delim''FilteredSearchOptions --dprintf( 'RepeatChangeThisFileQuiet: FilteredChangeArgs = 'FilteredChangeArgs) if fFirstChange then call NextCmdAltersText() endif display -14 'xcom c 'FilteredChangeArgs lrc = rc SearchLine = .line SearchCol = .col -- <> getpminfo( EPMINFO_SEARCHPOS) SearchLen = getpminfo( EPMINFO_LSLENGTH) -- This is the length of the search -- string, not of the replace string if SearchLen = '' then SearchLen = 0 endif ReplaceLen = length( ReplaceString) -- This isn't correct for grep NewLineLen = length( textline( .line)) display 14 fStop = (lrc <> 0) if lrc then --dprintf( '>> Restore pos from '.line','.col' to PrevFoundPos = 'PrevFoundPos', lrc after xcom c = 'lrc) pRestore_Pos( PrevFoundPos) leave endif -- Determining SearchLen (or ReplaceLen) for the next search -- For a repeated search, the start pos. will be moved by SearchLen to avoid -- finding the same string multiple times. -- GetPmInfo queries the length right, also for the grep or egrep search. -- SearchLen can be queried for a Search action by getpminfo( EPMINFO_LSLENGTH). -- But getpminfo( EPMINFO_LSLENGTH) gives the value for the search string, -- not for the change string. -- While for a non-grep search the length of the replacement string -- is known, it has to be calculated with the line length from before -- the change for a grep search. if fGrepChange then -- OldLineLen is determined by ProcessFindBeforeChange ReplaceLen = NewLineLen - OldLineLen + SearchLen --dprintf( 'ReplaceLen = 'ReplaceLen', NewLineLen = 'NewLineLen', OldLineLen = 'OldLineLen', SearchLen = 'SearchLen) endif enddo -- once -- Eventually change col in saved FirstStartPos if not lrc then if fid = FirstFid then FirstStartLine = word( FirstStartPos, 1) FirstStartCol = word( FirstStartPos, 2) if SearchLine = FirstStartLine & SearchCol < FirstStartCol then -- Change works line-wise, so only col may have changed NewStartCol = FirstStartCol + ReplaceLen - SearchLen --SavedFirstStartPos = FirstStartPos FirstStartPos = FirstStartLine NewStartCol NewStartCol subword( FirstStartPos, 4) --dprintf( 'Changed FirstStartPos from 'SavedFirstStartPos' to 'FirstStartPos) endif endif endif -- For LoadedFiles: Stop if FirstStartPos is reached. if not lrc then ProcessPostSearchPos( SearchOptions, FirstFid, FirstStartPos, FirstFileEndReached) lrc = rc if lrc = -18 then SavedRc = rc -- Restore line before the last change -- 'xcom c' with reversed strings is used, because it preserves bookmarks -- Cursor is still at the last change pos. UndoChangeOptions = RemoveSearchOptions( 'l*', FilteredSearchOptions) UndoChangeArgs = Delim''ReplaceString''Delim''SearchString''Delim''UndoChangeOptions display -14 'xcom c 'UndoChangeArgs display 14 -- Restore pos pRestore_Pos( FirstStartPos) rc = SavedRc fStop = 1 --dprintf( 'FirstFileEndReached = 'FirstFileEndReached', fid = 'fid', FirstFid = 'FirstFid', .line = '.line', .col = '.col', FirstStartPos = 'FirstStartPos) endif endif pSave_Pos( ThisPos) if not lrc then -- Eventually scroll to cursor pos -- Must scroll before the pos. is saved call ScrollAfterSearch( BeforeSearchPos, ThisPos, ReplaceLen) pSave_Pos( ThisPos) endif -- Counters if lrc then Counters = PrevCounters elseif fRepeat then Counters = PrevCounters else -- Count changes ChgNum = PrevChgNum + 1 -- Count found occurences, already included if PrevSearchMode = 'l' if PrevSearchMode <> 'l' then FoundNum = PrevNum + 1 endif -- Count changed lines ChgLines = PrevChgLines PrevChangedLine = word( PrevChangedPos, 1) FirstChangedLine = word( FirstChangedPos, 1) if SearchLine <> PrevChangedLine & not (fid = FirstChangedFid & SearchLine = FirstChangedLine) then ChgLines = PrevChgLines + 1 endif -- Count lines with found occurences FoundLines = PrevLines FirstFoundLine = word( FirstFoundPos, 1) if FirstFoundLine then PrevFoundLine = word( PrevFoundPos, 1) else -- PrevFoundPos is initialized to BeforeSearchPos. Therefore handle -- that case different. PrevFoundLine = '' endif if SearchLine <> PrevFoundLine & not (fid = FirstFoundFid & SearchLine = FirstFoundLine) then FoundLines = PrevLines + 1 endif --dprintf( '** FoundNum = PrevNum + 1 = 'FoundNum', SearchLine = 'SearchLine', PrevFoundLine = 'PrevFoundLine', PrevFoundPos = 'PrevFoundPos', FirstFoundLine = 'FirstFoundLine) -- Count changed files ChgFiles = PrevChgFiles if fid <> PrevChangedFid & fid <> FirstChangedFid then ChgFiles = PrevChgFiles + 1 endif -- Count files with found occurences FoundFiles = PrevFiles if fid <> PrevFoundFid & fid <> FirstFoundFid then FoundFiles = PrevFiles + 1 endif --dprintf( '** fid = 'fid', PrevFoundFid = 'PrevFoundFid', FoundFiles = 'FoundFiles', FoundLines = 'FoundLines) Counters = FoundNum FoundLines FoundFiles ChgNum ChgLines ChgFiles PrevChangedFid = fid PrevChangedPos = ThisPos PrevFoundFid = fid PrevFoundPos = ThisPos endif -- Set universal ThisMarkPos = GetMarkPos() --dprintf( 'Store current pos as lastsearchpos: 'ThisPos', PrevSearchRc = 'PrevSearchRc) lastsearchpos = fid'|'ThisPos'|'StartPos'|' || FirstFid'|'FirstStartPos'|' || FirstFoundFid'|'FirstFoundPos'|'FirstChangedFid'|'FirstChangedPos'|' || FirstFileEndReached'|'FileSwitchedBySearch'|' || PrevFoundFid'|'PrevFoundPos'|'PrevChangedFid'|'PrevChangedPos'|' || ThisMarkPos'|'SearchMode'|'Direction'|'lrc'|'ReplaceLen'|' || Counters --dprintf( 'Current search pos = 'lastsearchpos) -- If the search was executed from the search dialog, the focus is usually -- set to it again after this action. The following switches it back to -- the edit window and allows to use key defs for the next actions without -- having to manually activate the edit window. if fSearchDialog then if GetAVar( 'searchdlgopened') then KeyPath = '\NEPMD\User\SearchDialog\FocusToEditWindow' on = QueryConfigKey( KeyPath) if on then hWndClient = getpminfo( EPMINFO_EDITCLIENT) 'PostMe SetFocus' hWndClient endif endif endif -- Restore pos after change command if stay = 1 if stay & (not fChangeAll | lrc) then --dprintf( '>> Restore pos from '.line','.col' to FirstStartPos = 'FirstStartPos', stay = 'stay', lrc = 'lrc) pRestore_Pos( BeforeSearchPos) endif --dprintf( 'fStop = 'fStop', ThisPos = 'ThisPos', PrevPos = 'PrevPos', fSameSearch = 'fSameSearch) if fStop then if fSameSearch & PrevSearchRc then -- Don't override previous message else -- Give message if fSameSearch then if fLoadedFiles then Msg = ChgNum' of 'FoundNum' occurence(s) changed on 'ChgLines' of 'FoundLines' line(s) in 'ChgFiles' of 'FoundFiles' file(s)' else Msg = ChgNum' of 'FoundNum' occurence(s) changed on 'ChgLines' of 'FoundLines' line(s) in this file' endif MsgAdd = '' if not fIncludeComments & not fIncludeLiterals then MsgAdd = ' - comments and literals excluded' elseif not fIncludeComments then MsgAdd = ' - comments excluded' elseif not fIncludeLiterals then MsgAdd = ' - literals excluded' endif Msg = Msg''MsgAdd'.' else Msg = sayerrortext( -273)'.' endif endif -- The posted SetFocus above requires the PostMe here 'PostMe HighlightCursor' elseif fChangeAll & not lrc then -- Execute this again -- If executed by RepeatChangeAllFiles, the following may loop: --'RepeatChange' -- Endless loop --'RepeatChangeThisFileQuiet' -- No endless loop --Msg = RepeatChangeThisFileQuiet() 'RepeatChangeThisFile' return -- Important to keep the correct rc else -- Highlight it -- The posted SetFocus above requires the PostMe here --dprintf( 'PostMe HighlightMatch 'SearchLine SearchCol ReplaceLen) 'PostMe HighlightMatch 'SearchLine SearchCol ReplaceLen endif -- fStop else mouse_setpointer vepm_pointer rc = lrc --dprintf( 'RepeatChangeThisFileQuiet: rc = 'rc', Msg = 'Msg) return Msg ; --------------------------------------------------------------------------- defc RepeatChangeAllFiles universal lastsearchpos do once = 1 to 1 Msg = '' Args = strip( arg( 1), 'L') PrevChangeArgs = GetLastChangeArgs() --dprintf( overlay( ' RepeatChangeAllFiles ', copies( '-', 60), 4)) -- Parse Args fUsePrevIfArgsEmpty = 1 call ParseChangeArgs( Args, Delim, SearchString, ReplaceString, UserOptions, fUsePrevIfArgsEmpty) UserOptions = NormalizeSearchOptions( UserOptions) --dprintf( 'Args = 'Args', Delim = 'Delim', SearchString = 'SearchString', ReplaceString = 'ReplaceString', UserOptions = 'UserOptions) -- Parse PrevChangeArgs call ParseChangeArgs( PrevChangeArgs, PrevDelim, PrevSearchString, PrevReplaceString, PrevUserOptions) PrevUserOptions = NormalizeSearchOptions( PrevUserOptions) parse value lastsearchpos with PrevFid'|'PrevPos'|'PrevStartPos'|'FirstFid'|'FirstStartPos'|'RestSearchPos parse value RestSearchPos with FirstFoundFid'|'FirstFoundPos'|'FirstChangedFid'|'FirstChangedPos'|'RestSearchPos parse value RestSearchPos with FirstFileEndReached'|'FileSwitchedBySearch'|'RestSearchPos parse value RestSearchPos with PrevFoundFid'|'PrevFoundPos'|'PrevChangedFid'|'PrevChangedPos'|'RestSearchPos parse value RestSearchPos with PrevMarkPos'|'PrevSearchMode'|'PrevDirection'|'PrevSearchRc'|'PrevSearchLen'|'PrevCounters parse value PrevPos with PrevLine PrevCol . getfileid fid -- Prepend internal and default options and normalize search options. -- Remove 'm' if file not marked. Resolve 'v' and replace with 'e' or -- 'c'. Remove negated options. fStoreLastSearchOptions = 1 SearchOptions = ProcessSearchOptions( UserOptions, fStoreLastSearchOptions) --dprintf( '1 RepeatChangeAllFiles: UserOptions = 'UserOptions', SearchOptions = 'SearchOptions', ReplaceString = 'ReplaceString) PrevSearchOptions = ProcessSearchOptions( PrevUserOptions) --dprintf( '2 RepeatChangeAllFiles: PrevUserOptions = 'PrevUserOptions', PrevSearchOptions = 'PrevSearchOptions', PrevReplaceString = 'PrevReplaceString) -- Get Direction Direction = GetSearchDirection( SearchOptions) -- Check if cursor pos. has changed fCursorPosChanged = not (.line = PrevLine & .col = PrevCol) -- Determine fSameSearch (change next) -- For the Change after fRepeat, option D is removed from SearchOptions. fSameSearchString = (SearchString = PrevSearchString) fSameOptions = (RemoveSearchOptions( 'd+f-rtb', SearchOptions) = RemoveSearchOptions( 'd+f-rtb', PrevSearchOptions)) fSameFile = (fid = PrevFid) --dprintf( ' RepeatChangeAllFiles: fSameSearchString = 'fSameSearchString', fSameOptions = 'fSameOptions) --dprintf( ' RepeatChangeAllFiles: FileSwitchedBySearch = 'FileSwitchedBySearch', fSameFile = 'fSameFile', fCursorPosChanged = 'fCursorPosChanged) fSameSearch = 0 do once2 = 1 to 1 if not fSameSearchString then leave elseif not fSameOptions then leave elseif not fSameFile & not FileSwitchedBySearch then leave elseif fCursorPosChanged & not FileSwitchedBySearch then leave endif fSameSearch = 1 enddo --dprintf( '>> RepeatChangeAllFiles: fSameSearch = 'fSameSearch) -- Always search in whole files, not in mark UserOptions = RemoveSearchOptions( 'ma', UserOptions) -- Ensure that a possible 'M' in default_user_options is overridden UserOptions = UserOptions'a' --dprintf( '3 RepeatChangeAllFiles: UserOptions = 'UserOptions) -- Uncheck 'Marked area' of search dialog if GetAVar( 'searchdlgopened') then SetSearchDlgOption( 'a') endif if fSameSearch then -- Current file: start from cursor. Next file: start from top or bottom -- For next file, the move to the top or bottom is processed below UserOptions = RemoveSearchOptions( 'tb', UserOptions) -- Ensure that a possible 't' or 'b' in default_user_options is overridden -- '!t!b' doesn't exist in standard EPM UserOptions = UserOptions'!t!b' -- Normalize UserOptions UserOptions = NormalizeSearchOptions( UserOptions) --dprintf( '4 RepeatChangeAllFiles: UserOptions = 'UserOptions) -- Write PrevChangeArgs to config PrevChangeArgs = Delim''SearchString''Delim''ReplaceString''Delim''UserOptions call SetLastChangeArgs( PrevChangeArgs) --dprintf( '# RepeatChangeAllFiles: SetLastChangeArgs( 'PrevChangeArgs')') else -- This is a new search - reset lastsearchpos lastsearchpos = '' -- Parse again after reset parse value lastsearchpos with PrevFid'|'PrevPos'|'PrevStartPos'|'FirstFid'|'FirstStartPos'|'RestSearchPos parse value RestSearchPos with FirstFoundFid'|'FirstFoundPos'|'FirstChangedFid'|'FirstChangedPos'|'RestSearchPos parse value RestSearchPos with FirstFileEndReached'|'FileSwitchedBySearch'|'RestSearchPos parse value RestSearchPos with PrevFoundFid'|'PrevFoundPos'|'PrevChangedFid'|'PrevChangedPos'|'RestSearchPos parse value RestSearchPos with PrevMarkPos'|'PrevSearchMode'|'PrevDirection'|'PrevSearchRc'|'PrevSearchLen'|'PrevCounters parse value PrevPos with PrevLine PrevCol . -- Save FirstFid, FirstStartLine and FirstStartCol getfileid FirstFid pSave_Pos( FirstStartPos) PrevStartPos = FirstStartPos FirstFileEndReached = 0 -- Save FirstFid, FirstStartPos, PrevStartPos, FirstFileEndReached lastsearchpos = PrevFid'|'PrevPos'|'PrevStartPos'|' || FirstFid'|'FirstStartPos'|' || FirstFoundFid'|'FirstFoundPos'|'FirstChangedFid'|'FirstChangedPos'|' || FirstFileEndReached'|'FileSwitchedBySearch'|' || PrevFoundFid'|'PrevFoundPos'|'PrevChangedFid'|'PrevChangedPos'|' || PrevMarkPos'|'PrevSearchMode'|'PrevDirection'|'PrevSearchRc'|'PrevSearchLen'|' || PrevCounters --dprintf( '# RepeatChangeAllFiles 1: lastsearchpos = 'lastsearchpos) --dprintf( ' RepeatChangeAllFiles: Stored FirstFid = 'FirstFid', FirstStartLine = '.line', FirstStartCol = '.col) --dprintf( '#* RepeatChangeAllFiles: Init StartPos = 'FirstStartPos' for '.filename) endif -- Sort UserOptions UserOptions = NormalizeSearchOptions( UserOptions) -- Write PrevChangeArgs to ini PrevChangeArgs = Delim''SearchString''Delim''ReplaceString''Delim''UserOptions call SetLastChangeArgs( PrevChangeArgs) -- Get Direction Direction = GetSearchDirection( SearchOptions) 'VSyncCursor' do forever -- Search first file from cursor and next file from top or bottom getfileid fid -- Change next - call RepeatChangeThisFileQuiet rc = 0 Msg = RepeatChangeThisFileQuiet( Args) lrc = rc --dprintf( overlay( ' Back to RepeatChangeAllFiles ', copies( '-', 60), 4)) --dprintf( '# RepeatChangeAllFiles: RepeatChangeThisFileQuiet, rc = 'lrc', pos = '.line','.col', '.filename) -- Parse again after RepeatChangeThisFileQuiet parse value lastsearchpos with PrevFid'|'PrevPos'|'PrevStartPos'|'FirstFid'|'FirstStartPos'|'RestSearchPos parse value RestSearchPos with FirstFoundFid'|'FirstFoundPos'|'FirstChangedFid'|'FirstChangedPos'|'RestSearchPos parse value RestSearchPos with FirstFileEndReached'|'FileSwitchedBySearch'|'RestSearchPos parse value RestSearchPos with PrevFoundFid'|'PrevFoundPos'|'PrevChangedFid'|'PrevChangedPos'|'RestSearchPos parse value RestSearchPos with PrevMarkPos'|'PrevSearchMode'|'PrevDirection'|'PrevSearchRc'|'PrevSearchLen'|'PrevCounters parse value PrevPos with PrevLine PrevCol . parse value FirstStartPos with FirstStartLine FirstStartCol . if not lrc & FirstFoundFid = '' then FirstFoundFid = fid pSave_Pos( FirstFoundPos) endif if not lrc & FirstChangedFid = '' then FirstChangedFid = fid pSave_Pos( FirstChangedPos) endif if lrc then -- Restore StartPos if fid = FirstFid then pRestore_Pos( FirstStartPos) --dprintf( '#* RepeatChangeAllFiles: Restore FirstStartPos = 'FirstStartPos' for '.filename', lrc = 'lrc', FirstFileEndReached = 'FirstFileEndReached) if FirstFileEndReached = 1 then -- Start reached - stop searching lrc = -18 --dprintf( '#* RepeatChangeAllFiles: Stop at '.line','.col', lrc = 'lrc', '.filename) endif else pRestore_Pos( PrevStartPos) --dprintf( '#* RepeatChangeAllFiles: Restore PrevStartPos = 'PrevStartPos' for '.filename) endif if lrc = -18 then -- Don't search in next file when FirstStartPos is reached again. leave -- forever else -- Not found - pos. in current file already restored by RepeatChangeThisFileQuiet, -- but that is after going to top or bottom if fid = FirstFid then FirstFileEndReached = 1 endif -- Next file if Direction = '+' then nextfile else prevfile endif getfileid fid --dprintf( '# RepeatChangeAllFiles: Switched to next file, fid = 'fid', FirstFid = 'FirstFid', .filename = '.filename) if fid = FirstFid then PrevStartPos = FirstStartPos else pSave_Pos( PrevStartPos) --dprintf( '# RepeatChangeAllFiles: Saved PrevStartPos to '.line .col', .filename = '.filename) endif -- Start from top or bottom of file if Direction = '+' then top .col = 1 else bottom endline endif -- Reset pos. counters after switching files to get lines counter right PrevFoundPos = '' PrevChangedPos = '' -- Create a new undo state for each file separately call NextCmdAltersText() endif PrevSearchRc = 0 FileSwitchedBySearch = 1 -- This is reset by ProcessSearchPos endif -- Save FirstFileEndReached, PrevSearchRc, PrevStartPos, FileSwitchedBySearch lastsearchpos = PrevFid'|'PrevPos'|'PrevStartPos'|' || FirstFid'|'FirstStartPos'|' || FirstFoundFid'|'FirstFoundPos'|'FirstChangedFid'|'FirstChangedPos'|' || FirstFileEndReached'|'FileSwitchedBySearch'|' || PrevFoundFid'|'PrevFoundPos'|'PrevChangedFid'|'PrevChangedPos'|' || PrevMarkPos'|'PrevSearchMode'|'PrevDirection'|'PrevSearchRc'|'PrevSearchLen'|' || PrevCounters --dprintf( '# RepeatChangeAllFiles 2: lastsearchpos = 'lastsearchpos) if not lrc then -- Found - let RepeatChangeThisFileQuiet highlight the occurence leave endif enddo -- forever enddo -- once rc = lrc if Msg then 'SayError 'Msg endif ; --------------------------------------------------------------------------- ; Highlight a "hit" after a Locate command or Repeat_find operation. ; Never used its previous arg( 1) = search_len in 6.03b. ; Syntax: Highlight_Match( [line col len]) ; Highlight_Match( [line col len], [fStripBlanks]) ; Specify fStripBlanks = 1 to strip spaces and tab chars before highlighting. ; - lastcommand ensures that HighlightMatch is executed as last command ; after opening a file. Usually HighlightCursor is executed then. ; The highlight command is executed then again to make sure that the ; circle stays after opening. ; - On file opening and executing a command, the cursor is sometimes off the ; screen. In that case, the window is centered here before the circle is ; drawn. defproc Highlight_Match universal lastcommand savedrc = rc do once = 1 to 1 if rc then -- if not found; rc was set from last 'c'|'l'|repeat_find leave endif PosData = arg( 1) fStripBlanks = (arg( 2) = 1) if PosData <> '' then parse value PosData with line col len . if line > .last then leave endif if col = '' then -- This must be the previously used syntax: arg( 1) = search_len PosData = '' endif endif if PosData = '' then line = .line col = getpminfo( EPMINFO_SEARCHPOS) len = getpminfo( EPMINFO_LSLENGTH) endif if col = 0 then col = .col endif -- Ensure that the cursor is within the window area if not OnScreen() then 'CenterLine' 'Refresh' -- sometimes required after file opening to place the cursor on current line endif if fStripBlanks then LineStr = textline( line) HighlightStr = substr( LineStr, col, len) THighlightStr = translate( HighlightStr, ' ', \t) LStrippedStr = strip( THighlightStr, 'L') StrippedStr = strip( LStrippedStr, 'T') NewCol = col + len - length( LStrippedStr) NewLen = length( StrippedStr) col = NewCol len = NewLen endif -- Ensure that len is > 0 len = Max( 1, len) lastcommand = 'highlightmatch' line col len -- Draw a circle around the found string circleit LOCATE_CIRCLE_STYLE, line, col, col + len - 1, LOCATE_CIRCLE_COLOR1, LOCATE_CIRCLE_COLOR2 enddo rc = savedrc return ; --------------------------------------------------------------------------- ; Callable with 'postme'. Required for GlobalFind. defc HighlightMatch call Highlight_Match( arg( 1)) ; --------------------------------------------------------------------------- defc CircleIt parse arg line startcol endcol circleit LOCATE_CIRCLE_STYLE, line, startcol, endcol, LOCATE_CIRCLE_COLOR1, LOCATE_CIRCLE_COLOR2 ; --------------------------------------------------------------------------- ; Syntax: ScrollAfterSearch( [savedpos [, lpos [, HiliteLen ; [, ScrollToTopBot [, ScrollSpace]]]]]) ; savedpos = pos before the search ; If not specified, then current pos. is used and ; ScrollToTopBot is set to 'T', if not specified. ; lpos = pos after the search, at the found string (optional) ; If not specified, than then current pos. is used. ; HiliteLen = length of the string to make visible ; If not specified, then 0 is used. ; ScrollToTopBot = 'T' or 'B' (optional) ; 'T' means that the top position within the ScrollSpace ; is used, if the cursor is outside of it. 'B' means that ; the bottommost defined position is used in that case. ; The default behavior is that either top or bottom ; depends on the pos. before the search. That is to ; minimize scrolling in between multiple searches. If ; the search direction was forward, then the top pos. ; is used, if outside of ScrollSpace. If it was backward, ; then the bottom pos. is used. If the found pos. is ; within the ScrollSpace, no scrolling takes place. ; ScrollSpace = space or window line values as 'top bot' (optional) ; Negative values are handled as vertical space, ; positive values are handled as window height line number, ; where the topmost visible line is 1 and the bottommost ; visible line is .windowheight. ; Example: '26 -4' means: ; topmost window line to scroll to = 26 ; (the vertical space between 1 and 25 can be used ; for the search dialog) ; bottom minimum space = 4 lines ; If possible, vertical window scrolling is avoided. ; Then the loacate pos must be within the specified ; scroll area. ; Special values are 'K K' and 'C C': ; 'K K' means: Keep scroll pos. from before the ; search. ; 'C C' means: Center found line. ; The default values for ScrollSpace can be configured ; via Preferences -> Special keys and mouse. defproc ScrollAfterSearch ScrollToTopBot = upcase( arg( 4)) savedpos = arg( 1) if savedpos = '' then call pSave_Pos( savedpos) if ScrollToTopBot = '' then ScrollToTopBot = 'T' endif else parse value savedpos with svline svcol svcx svcy . endif lpos = arg( 2) if lpos = '' then lline = .line lcol = .col lcx = .cursorx lcy = .cursory else parse value lpos with lline lcol lcx lcy . endif if ScrollToTopBot = 'T' then -- Assist: inverted arg to sroll to the bottom after a downward search fBackward = 1 elseif ScrollToTopBot = 'B' then -- Assist: inverted arg to sroll to the top after an upward search fBackward = 0 else -- Get search direction from previous search options getsearch CurSearch parse value CurSearch with 'xcom' SearchMode rest rest = strip( rest) Delim = leftstr( rest, 1) if SearchMode = 'c' then ParseChangeArgs( rest, Delim, SearchString, ReplaceString, SearchOptions) else ParseFindArgs( rest, Delim, SearchString, SearchOptions) endif fBackward = lastpos( '+', SearchOptions) >= lastpos( '-', SearchOptions) endif ScrollSpace = arg( 5) if ScrollSpace = '' then KeyPath = '\NEPMD\User\CursorPos\VPosAfterSearch' ScrollType = QueryConfigKey( KeyPath) if ScrollType = 'K' then ScrollSpace = 'K K' elseif ScrollType = 'C' then ScrollSpace = 'C C' else KeyPath = '\NEPMD\User\CursorPos\ScrollAfterSearch' ScrollSpace = QueryConfigKey( KeyPath) endif endif topline = svline - svcy + 1 botline = svline - svcy + .windowheight leftcol = svcol - svcx + 1 rightcol = svcol - svcx + .windowwidth topheight = word( ScrollSpace, 1) botheight = word( ScrollSpace, 2) do once = 1 to 1 if wordpos( topheight, 'K C') then leave endif if wordpos( botheight, 'K C') then leave endif if not IsNum( topheight) then topheight = 'K' -- 'K' = keep cursory leave elseif topheight < 0 then -- Minus: topheight is vspace in lines from top, set absolute value + 1 topheight = -1 * topheight + 1 endif if not IsNum( botheight) then botheight = 'K' -- 'K' = keep cursory leave elseif botheight < 0 then -- Minus: botheight is vspace in lines from bottom, calc with absolute value botheight = .windowheight + botheight endif -- Ensure that area is at least 1 line height if IsNum( topheight) & IsNum( botheight) then if botheight - topheight < 0 then topheight = .windowheight % 2 botheight = topheight endif endif enddo HiliteLen = arg( 3) if not IsUInt( HiliteLen) then HiliteLen = 0 endif --dprintf( 'ScrollAfterSearch: topheight = 'topheight', botheight = 'botheight', HiliteLen = 'HiliteLen) if topheight = 'K' | botheight = 'K' then -- Keep .cursory from before the search .cursory = svcy .line = lline elseif topheight = 'C' | botheight = 'C' then -- Center found line .cursory = .windowheight % 2 .line = lline else fInScrollArea = 0 x = lcol y = lline if y < topline + topheight then elseif y > botline - .windowheight + botheight then -- Don't scroll if only horizontally outside --elseif x < leftcol then --elseif x > rightcol then else fInScrollArea = 1 endif -- Minimize scrolling for ScrollSpace = '0 0' if topheight = 0 & botheight = 0 then fInArea = OnScreen() /* -- Minimize scrolling if line number hasn't changed elseif lline = svline then fInArea = OnScreen() */ else fInArea = fInScrollArea endif if fInArea then call pRestore_Pos( savedpos) -- Set line to lline without scrolling .cursory = svcy + lline - svline else -- Reposition cursor call pRestore_Pos( lpos) oldline = .line if fBackward then .cursory = topheight else .cursory = botheight endif .line = oldline endif endif -- Horizontal scrolling -- Show left edge if possible .col = 1 -- Show full string, not only start col .col = lcol + HiliteLen -- Go to start col .col = lcol ; --------------------------------------------------------------------------- ; Syntax: SearchDlg [F | C | S | B] ; F repeat find ; C repeat change ; S (search mode) clears replace entry field ; B (blank) clears both search and replace entry fields ; R (replace mode) recognized by PostSearchDlgOptions ; Any other arg or no arg: Keep entry field texts, if dialog was opened ; once. /* 旼컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴커 � what's it called: searchdlg syntax: searchdlg [next] � � � � what does it do : ask EPM.EXE to pop up its internal search & replace dlg. � � This is done by posting a EPM_POPCHANGEDLG message to the� � EPM Book window. � � if the [next] param = 'F' a find next will take place � � if the [next] param = 'C' a change next will take place � � � � (All EPM_EDIT_xxx messages are defined in the ETOOLKT � � PACKAGE available on PCTOOLS.) � � � � who and when : Jerry C. 2/27/89 � 읕컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴켸 */ defc SearchDlg universal lastcommand parse value upcase( arg( 1)) with uparg . if uparg = 'C' then 'RepeatChange '\1\1\1\1'd' elseif uparg = 'F' then 'RepeatFind '\1\1\1\1'd' else lastcommand = 'SearchDlg' arg( 1) -- Determine if option should be restored fRestoreOptions = 0 if uparg then -- e.g. 'SearchDlg S', 'SearchDlg R' or 'SearchDlg 'B' fRestoreOptions = 1 elseif not GetAVar( 'searchdlgopened') then fRestoreOptions = 1 endif -- The application will free the buffer allocated by this macro Options = NormalizeSearchOptions( GetDefaultSearchOptions()''GetLastSearchOptions()) call windowmessage( 0, getpminfo( APP_HANDLE), 5128, -- EPM_POPCHANGEDLG 0, Put_In_Buffer( Options)) -- Restore options if fRestoreOptions then if not uparg then uparg = 'S' endif 'PostMe PostSearchDlgOptions' uparg -- PostMe required endif endif ; --------------------------------------------------------------------------- ; This must be posted, otherwise the handles are 0 after startup. ; Syntax: PostSearchDlgOptions [dialogtype] ; with dialogtype ; S (search mode) clears replace entry field, restores search entry ; field ; R (replace mode) restores both search and replace entry fields ; B (blank) clears both search and replace entry fields ; Any other arg or no arg: Keep entry field texts, if dialog was opened ; once. ; Note: F and C are already used by SearchDlg itself for FindNext and ; ChangeNext. defc PostSearchDlgOptions parse value upcase( arg( 1)) with DialogType . if GetAVar( 'searchdlgopened') then -- Opened before -- Get last search options SearchOptions = GetLastSearchOptions() -- Let the search dialog keep its options, except the corrections below: else -- On opening the search dialog, start with last used options. -- This is not required after the dialog was once open after EPM start, -- because the dialog keeps its options. -- Query restore type ('L' = 'Last', 'D' = 'Default') KeyPath = '\NEPMD\User\AutoRestore\SearchOptions' RestoreType = QueryConfigKey( KeyPath) if RestoreType = 'L' then -- Get last search options SearchOptions = GetLastSearchOptions() else -- Get default search options SearchOptions = GetDefaultSearchOptions() endif -- Restore all dialog checkbox states SetSearchDlgOptions( SearchOptions) endif hWndParent = WindowFromId( 5300) -- Ensure that search dialog is fully visible on the desktop MoveWindowToDesktop( hWndParent) -- Set Ignore case check box for automatic case-sensitiveness fAutoCaseSentive = (pos( 'v', SearchOptions) > 0) if fAutoCaseSentive then Mode = GetMode() fCaseSensitive = QueryModeKey( Mode, 'CaseSensitive') SetCheckValue( hWndParent, 5302, not fCaseSensitive) -- Option: Ignore case endif -- Uncheck 'Marked area' if 'Loaded files' is active fLoadedFiles = (pos( 'l', SearchOptions) > 0) if fLoadedFiles then SetSearchDlgOption( 'a') else -- If file is marked, activate search in mark -- and from top, if b or t is not already set. KeyPath = '\NEPMD\User\SearchDialog\SearchMarkIfMarked' on = QueryConfigKey( KeyPath, 1) -- Check if a multi-line mark exists getmark firstline, lastline, firstcol, lastcol, markfid if FileIsMarked() & on & lastline > firstline then SetCheckValue( hWndParent, 5303, 1) -- Options: Marked area fTopIsDefault = (pos( 't', SearchOptions) > 0) fBottomIsDefault = (pos( 'b', SearchOptions) > 0) if not fTopIsDefault & not fBottomIsDefault then SetCheckValue( hWndParent, 5318, 1) -- Start at: Top endif elseif not FileIsMarked() | lastline = firstline then SetCheckValue( hWndParent, 5303, 0) -- Options: Marked area endif -- If words are marked, overtake them as search string for the search dialog KeyPath = '\NEPMD\User\SearchDialog\SearchMarkedWords' on = QueryConfigKey( KeyPath, 1) -- Check if a multi-line mark exists getmark firstline, lastline, firstcol, lastcol, markfid if FileIsMarked() & on & lastline = firstline then MarkedString = substr( textline( firstline), firstcol, lastcol - firstcol + 1) SetDlgItemText( hWndParent, 5301, MarkedString) -- Search entry field endif endif -- Set font KeyPath = '\NEPMD\User\Fonts\Text' TextFont = QueryConfigKey( KeyPath, '12.System VIO') SetWindowFont( hWndParent, 5301, TextFont) -- Search entry field SetWindowFont( hWndParent, 5310, TextFont) -- Replace entry field -- Set text if empty or if S specified -- The dialog restores the entry fields itself after the first search in a -- session, but not the search type. LastFindArgs = GetLastFindArgs() LastChangeArgs = GetLastChangeArgs() SearchString = QueryDlgItemText( hWndParent, 5301) ReplaceString = QueryDlgItemText( hWndParent, 5310) NewSearchString = '' NewReplaceString = '' -- S (search mode) clears replace entry field, restores search entry field -- R (replace mode) restores both search and replace entry fields -- B (blank) clears both search and replace entry fields if DialogType = 'B' then -- Blank elseif DialogType = 'S' then -- Search mode if NewSearchString = '' then ParseFindArgs( LastFindArgs, Delim, NewSearchString, UserOptions) NewReplaceString = '' endif if NewSearchString = '' then ParseChangeArgs( LastChangeArgs, Delim, NewSearchString, NewReplaceString, UserOptions) endif elseif DialogType = 'R' | not GetAVar( 'searchdlgopened') then -- Replace mode ParseChangeArgs( LastChangeArgs, Delim, NewSearchString, NewReplaceString, UserOptions) if NewSearchString = '' then ParseFindArgs( LastFindArgs, Delim, NewSearchString, UserOptions) NewReplaceString = '' endif endif SearchOptions = ProcessSearchOptions( UserOptions) if (SearchString = '' & NewSearchString <> '') | DialogType = 'B' then SetDlgItemText( hWndParent, 5301, NewSearchString) -- Search entry field endif if (ReplaceString = '' & NewReplaceString <> '') | (ReplaceString <> '' & NewReplaceString = '') | DialogType = 'B' then SetDlgItemText( hWndParent, 5310, NewReplaceString) -- Replace entry field endif -- Select text SetEntryFieldSelect( hWndParent, 5301) -- Search entry field -- Set focus SetFocus( WindowFromId( hWndParent, 5301)) -- Search entry field -- Set flag that the dialog was opened SetAVar( 'searchdlgopened', 1) ; --------------------------------------------------------------------------- ; This sets search dialog options dependant on the passed option string. defc SetSearchDlgOptions SetSearchDlgOptions( strip( arg( 1))) defproc SetSearchDlgOptions -- This also filters out negated options OptStr = NormalizeSearchOptions( arg( 1), 1) --dprintf( 'SetSearchDlgOptions: OptStr = 'OptStr) hWndParent = WindowFromId( 5300) do o = 1 to length( OptStr) -- Set check states for all passed option chars ThisOpt = substr( OptStr, o, 1) if ThisOpt = 'v' then Mode = GetMode() fCaseSensitive = QueryModeKey( Mode, 'CaseSensitive') SetCheckValue( hWndParent, 5302, not fCaseSensitive) -- Option: Ignore case elseif ThisOpt = 'e' then SetCheckValue( hWndParent, 5302, 0) -- Option: Ignore case elseif ThisOpt = 'c' then SetCheckValue( hWndParent, 5302, 1) -- Option: Ignore case elseif ThisOpt = '+' | ThisOpt = 'f' then SetCheckValue( hWndParent, 5304, 0) -- Option: Reverse search elseif ThisOpt = '-' | ThisOpt = 'r' then SetCheckValue( hWndParent, 5304, 1) -- Option: Reverse search elseif ThisOpt = 'm' then SetCheckValue( hWndParent, 5303, 1) -- Option: Marked area elseif ThisOpt = 'a' then SetCheckValue( hWndParent, 5303, 0) -- Option: Marked area elseif ThisOpt = '*' then SetCheckValue( hWndParent, 5311, 1) -- Option: Change all elseif ThisOpt = 'k' then SetCheckValue( hWndParent, 5322, 1) -- Option: Match case elseif ThisOpt = '^' then SetCheckValue( hWndParent, 5323, 1) -- Option: Negate search elseif ThisOpt = 'w' then SetCheckValue( hWndParent, 5315, 1) -- Option: Word elseif ThisOpt = 'g' then SetCheckValue( hWndParent, 5305, 1) -- Option: GREP elseif ThisOpt = 'x' then SetCheckValue( hWndParent, 5308, 1) -- Option: EGREP elseif ThisOpt = 't' then SetCheckValue( hWndParent, 5318, 1) -- Option: Top elseif ThisOpt = 'b' then SetCheckValue( hWndParent, 5319, 1) -- Option: Bottom endif enddo -- Set check states for omitted options if not pos( '*', OptStr) then SetCheckValue( hWndParent, 5311, 0) -- Option: Change all endif if not pos( 'k', OptStr) then SetCheckValue( hWndParent, 5322, 0) -- Option: Match case endif if not pos( '^', OptStr) then SetCheckValue( hWndParent, 5323, 0) -- Option: Negate search endif if not pos( 'w', OptStr) & not pos( 'g', OptStr) & not pos( 'x', OptStr) then SetCheckValue( hWndParent, 5316, 1) -- Option: Normal endif if not pos( 't', OptStr) & not pos( 'b', OptStr) then SetCheckValue( hWndParent, 5317, 1) -- Option: Cursor endif return ; --------------------------------------------------------------------------- ; This sets a single search dialog option to a specified value. It supports ; negation with '!'. The default value for Val is 1. ; For radio button states without option chars (Normal and Cursor), specify ; a combined option: !g!w!x resp. !b!t (or any combination) as Opt. Val is ; ignored for radio buttons. defc SetSearchDlgOption Val = '' parse value arg( 1) with Opt Val Opt = strip( Opt) Val = strip( Val) SetSearchDlgOption( Opt, Val) defproc SetSearchDlgOption Opt = lowcase( arg( 1)) Val = arg( 2) if not wordpos( Val, '0 1') then Val = 1 endif hWndParent = WindowFromId( 5300) -- Check boxes if Opt = 'v' then Mode = GetMode() fCaseSensitive = QueryModeKey( Mode, 'CaseSensitive') SetCheckValue( hWndParent, 5302, not fCaseSensitive) -- Option: Ignore case elseif Opt = 'e' | Opt = '!c' then SetCheckValue( hWndParent, 5302, not Val) -- Option: Ignore case elseif Opt = 'c' | Opt = '!e' then SetCheckValue( hWndParent, 5302, Val) -- Option: Ignore case elseif Opt = '+' | Opt = 'f' then SetCheckValue( hWndParent, 5304, not Val) -- Option: Reverse search elseif Opt = '-' | Opt = 'r' then SetCheckValue( hWndParent, 5304, Val) -- Option: Reverse search elseif Opt = 'm' | Opt = '!a' then SetCheckValue( hWndParent, 5303, not Val) -- Option: Marked area elseif Opt = 'a' | Opt = '!m' then SetCheckValue( hWndParent, 5303, not Val) -- Option: Marked area elseif Opt = '*' then SetCheckValue( hWndParent, 5311, Val) -- Option: Change all elseif Opt = '!*' then SetCheckValue( hWndParent, 5311, not Val) -- Option: Change all elseif Opt = 'k' then SetCheckValue( hWndParent, 5322, Val) -- Option: Match case elseif Opt = '!k' then SetCheckValue( hWndParent, 5322, not Val) -- Option: Match case elseif Opt = '^' then SetCheckValue( hWndParent, 5323, Val) -- Option: Negate search elseif Opt = '!^' then SetCheckValue( hWndParent, 5323, not Val) -- Option: Negate search -- Radio buttons: Val is ignored elseif pos( '!g', Opt) & pos( '!w', Opt) & pos( '!x', Opt) then SetCheckValue( hWndParent, 5316, 1) -- Option: Normal elseif Opt = 'w' then SetCheckValue( hWndParent, 5315, 1) -- Option: Word elseif Opt = 'g' then SetCheckValue( hWndParent, 5305, 1) -- Option: GREP elseif Opt = 'x' then SetCheckValue( hWndParent, 5308, 1) -- Option: EGREP elseif pos( '!b', Opt) & pos( '!t', Opt) then SetCheckValue( hWndParent, 5317, 1) -- Option: Cursor elseif Opt = 't' then SetCheckValue( hWndParent, 5318, 1) -- Option: Top elseif Opt = 'b' then SetCheckValue( hWndParent, 5319, 1) -- Option: Bottom endif return ; --------------------------------------------------------------------------- defproc GetSearchDlgOption OptText = upcase( arg( 1)) hWndParent = WindowFromId( 5300) fSet = '' if GetAVar( 'searchdlgopened') then -- required to make this return empty -- before the search dialog was opened if OptText = 'IGNORE CASE' then fSet = QueryCheckValue( hWndParent, 5302) elseif OptText = 'REVERSE SEARCH' then fSet = QueryCheckValue( hWndParent, 5304) elseif OptText = 'MARKED AREA' then fSet = QueryCheckValue( hWndParent, 5303) elseif OptText = 'CHANGE ALL' then fSet = QueryCheckValue( hWndParent, 5311) elseif OptText = 'MATCH CASE' then fSet = QueryCheckValue( hWndParent, 5322) elseif OptText = 'NEGATE SEARCH' then fSet = QueryCheckValue( hWndParent, 5323) elseif OptText = 'NORMAL' then fSet = QueryCheckValue( hWndParent, 5316) elseif OptText = 'WORD' then fSet = QueryCheckValue( hWndParent, 5315) elseif OptText = 'GREP' then fSet = QueryCheckValue( hWndParent, 5305) elseif OptText = 'EGREP' then fSet = QueryCheckValue( hWndParent, 5308) elseif OptText = 'CURSOR' then fSet = QueryCheckValue( hWndParent, 5317) elseif OptText = 'TOP' then fSet = QueryCheckValue( hWndParent, 5318) elseif OptText = 'BOTTOM' then fSet = QueryCheckValue( hWndParent, 5319) endif endif return fSet ; --------------------------------------------------------------------------- defc RestoreSearchHistory NewSearchArgs = arg( 1) -- Parse args Delim = leftstr( NewSearchArgs, 1) if count( Delim, NewSearchArgs) = 2 then ParseFindArgs( NewSearchArgs, Delim, SearchString, SearchOptions) ReplaceString = '' -- Last find args --dprintf( 'RestoreSearchHistory: SetLastFindArgs( 'NewSearchArgs')') SetLastFindArgs( NewSearchArgs) -- Last find else ParseChangeArgs( NewSearchArgs, Delim, SearchString, ReplaceString, SearchOptions) -- Last change args SetLastChangeArgs( NewSearchArgs) -- Last change endif -- Normalize SearchOptions = NormalizeSearchOptions( SearchOptions, 1) -- Set 'Search' menu options -- Set 'Preferences' -> 'Search options' popup menu options and text -- Set Search dialog options 'SearchOptionsMenuCmd 'SearchOptions hWndParent = WindowFromId( 5300) -- Set dialog strings SetDlgItemText( hWndParent, 5301, SearchString) -- Search entry field SetDlgItemText( hWndParent, 5310, ReplaceString) -- Replace entry field -- Select dialog text SetEntryFieldSelect( hWndParent, 5301) -- Search entry field -- Set dialog options SetSearchDlgOptions( SearchOptions) ; --------------------------------------------------------------------------- defc ExchangeSearchStrings hWndParent = WindowFromId( 5300) -- Query strings SearchString = QueryDlgItemText( hWndParent, 5301) ReplaceString = QueryDlgItemText( hWndParent, 5310) -- Restore exchanged SetDlgItemText( hWndParent, 5301, ReplaceString) -- Search entry field SetDlgItemText( hWndParent, 5310, SearchString) -- Replace entry field -- Select text SetEntryFieldSelect( hWndParent, 5301) -- Search entry field -- Last change args -- Get Delim and SearchOptions LastChangeArgs = GetLastChangeArgs() ParseChangeArgs( LastSearchArgs, LastDelim, LastSearchString, LastReplaceString, LastSearchOptions) -- Restore exchanged NewSearchArgs = LastDelim''ReplaceString''LastDelim''SearchString''LastDelim''LastSearchOptions SetLastChangeArgs( NewSearchArgs) -- Last change ; --------------------------------------------------------------------------- ; Returns '+' or '-'. defproc GetSearchDirection SearchOptions = arg( 1) if SearchOptions = '' then -- LastSearchOptions is usually stored by ProcessSearchOptions SearchOptions = GetLastSearchOptions() endif MinusPos = lastpos( '-', SearchOptions) PlusPos = lastpos( '+', SearchOptions) Direction = '+' if MinusPos > PlusPos then Direction = '-' endif return Direction ; --------------------------------------------------------------------------- ; Returns '+' or '-'. The current option of the Search dialog is read. ; If it can't be queried from it, empty is returned by GetSearchDlgOption ; and then the return value here is determined from the last search args. defproc GetSearchDlgDirection fBackward = GetSearchDlgOption( 'reverse search') if fBackward = '' then fBackward = (GetSearchDirection() = '-') endif Direction = '+' if fBackward then Direction = '-' endif -- Store value in LastFindArgs and LastChangeArgs 'SetSearchDirection 'Direction' norefresh' return Direction ; --------------------------------------------------------------------------- ; From EPMSMP\REVERSE.E ; Search options for specifying the direction: ; f start searching from the start of line ; r start searching from the end of line ; + start searching from the start of text ; - start searching from the end of text ; The relevant options are + and -, F or R is set automatically. ; ; Original by Larry Margolis: ; Repeat the previous Locate, but in the reverse direction. ; E.g., if you search for a string that you know exists, but ; it's not found before the end of the file, press Ctrl+minus ; to repeat the search for the same string looking from the ; cursor position to the beginning of the file. ; Changed: ; Toggles the search direction (options +F or -R) without any ; following locate action. ; Doesn't produce an error msg anymore if oldsearch = empty. ; This toggles also 'Reverse search' of the Search dialog. defc ToggleSearchDirection universal nodismiss PrevDirection = GetSearchDirection() fPrevBackward = (PrevDirection = '-') -- Toggle value fBackward = not fPrevBackward if PrevDirection = '-' then Direction = '+' ForwardBackward = 'forward' else Direction = '-' ForwardBackward = 'backward' endif -- Append +f or -r to LastFindArgs, refresh menu texts posted 'SetSearchDirection 'Direction --dprintf( 'ToggleSearchDirection: Changed search direction to: 'ForwardBackward'.') 'SayHint Changed search direction to: 'ForwardBackward'.' -- 'Backward' menu item if nodismiss then SetMenuAttribute( 'searchbackward', MIA_CHECKED, not fBackward) --dprintf( 'ToggleSearchDirection: Changed "Backward" menu item to 'fBackward'.') endif -- Search dialog if GetAVar( 'searchdlgopened') then SetSearchDlgOption( Direction) endif ; --------------------------------------------------------------------------- ; Set SearchDirection to forward (arg = 'f' or '+') or backward (arg = 'r' ; or '-'). defc SetSearchDirection universal nodismiss do once = 1 to 1 Args = lowcase( arg( 1)) --dprintf( 'SetSearchDirection: Args = 'Args) wp = wordpos( 'norefresh', Args) fRefresh = (wp = 0) if wp then Args = delword( Args, wp, 1) endif Direction = strip( Args) AppendOptions = '' if Direction = '' then leave elseif Direction = '+' | Direction = 'f' then AppendOptions = '+f' elseif Direction = '-' | Direction = 'r' then AppendOptions = '-r' endif -- Options will be normalized by ProcessSearchOptions. Therefore it's -- possible to simply append options. (The last option wins.) -- But here previous direction options are removed first with RemoveOption. -- LastFindArgs LastFindArgs = GetLastFindArgs() ParseFindArgs( LastFindArgs, Delim, SearchString, UserOptions) NewOptions = SortSearchOptions( RemoveSearchOptions( '+f-r', UserOptions)''AppendOptions) NewFindArgs = Delim''SearchString''Delim''NewOptions --dprintf( 'SetSearchDirection: SetLastFindArgs( 'NewFindArgs')') SetLastFindArgs( NewFindArgs) --dprintf( 'SetSearchDirection: Changed LastFindArgs = 'GetLastFindArgs()) -- LastChangeArgs LastChangeArgs = GetLastChangeArgs() if LastChangeArgs then ParseChangeArgs( LastChangeArgs, Delim, SearchString, ReplaceString, UserOptions) NewOptions = SortSearchOptions( RemoveSearchOptions( '+f-r', UserOptions)''AppendOptions) NewChangeArgs = Delim''SearchString''Delim''ReplaceString''Delim''NewOptions SetLastChangeArgs( NewChangeArgs) endif -- LastSearchOptions NewLastOptions = RemoveSearchOptions( '+f-r', GetLastSearchOptions()) NewLastOptions = NewLastOptions''lowcase( AppendOptions) NewLastOptions = NormalizeSearchOptions( NewLastOptions, 1) SetLastSearchOptions( NewLastOptions) --dprintf( 'SetSearchDirection: Changed LastSearchOptions to 'NewLastOptions) if fRefresh then if nodismiss then -- Menu items --dprintf( 'SetSearchDirection: Execute: PostMe RefreshMenuSearchText') 'PostMe RefreshMenuSearchText' -- PostMe required to avoid a loop --dprintf( 'SetSearchDirection: Execute: PostMe SearchOptionsMenuCmd') 'PostMe SearchOptionsMenuCmd' -- PostMe required to process all menu items endif -- Search dialog if GetAVar( 'searchdlgopened') then SetSearchDlgOption( Direction) endif endif enddo return ; --------------------------------------------------------------------------- defproc RemoveSearchOptions( RemoveOptions, OptionStr) do once = 1 to 1 -- Check parms if RemoveOptions = '' then leave endif if OptionStr = '' then leave endif -- Handle ! prefix in both strings RemoveOptWords = InsertSpaceStr( RemoveOptions, '[^!]') OptionWords = InsertSpaceStr( OptionStr, '[^!]') do w = 1 to words( RemoveOptWords) RemoveOpt = word( RemoveOptWords, w) do forever wp = wordpos( RemoveOpt, OptionWords) if not wp then leave endif OptionWords = delword( OptionWords, wp, 1) enddo enddo OptionStr = SpaceStr( OptionWords, 0) enddo return OptionStr ; --------------------------------------------------------------------------- defproc RemoveSearchOptionFromLast DelOpt = lowcase( arg( 1)) -- LastFindArgs LastFindArgs = GetLastFindArgs() ParseFindArgs( LastFindArgs, Delim, SearchString, UserOptions) NewOptions = SortSearchOptions( RemoveSearchOptions( DelOpt, UserOptions)) NewFindArgs = Delim''SearchString''Delim''NewOptions --dprintf( 'RemoveSearchOptionFromLast: SetLastFindArgs( 'NewFindArgs')') SetLastFindArgs( NewFindArgs) -- LastChangeArgs LastChangeArgs = GetLastChangeArgs() if LastChangeArgs then ParseChangeArgs( LastChangeArgs, Delim, SearchString, ReplaceString, UserOptions) NewOptions = SortSearchOptions( RemoveSearchOptions( DelOpt, UserOptions)) NewChangeArgs = Delim''SearchString''Delim''ReplaceString''Delim''NewOptions SetLastChangeArgs( NewChangeArgs) endif return ; --------------------------------------------------------------------------- defc FindNext 'SetSearchDirection + NOREFRESH' 'RepeatFind' ; --------------------------------------------------------------------------- defc FindPrev 'SetSearchDirection - NOREFRESH' 'RepeatFind' ; --------------------------------------------------------------------------- defc ChangeFindNext 'SetSearchDirection + NOREFRESH' 'RepeatChange' if not rc then 'RepeatFind' endif ; --------------------------------------------------------------------------- defc ChangeFindPrev 'SetSearchDirection - NOREFRESH' 'RepeatChange' if not rc then 'RepeatFind' endif ; --------------------------------------------------------------------------- defc FindNextAllFiles 'SetSearchDirection + NOREFRESH' 'RepeatFindAllFiles' ; --------------------------------------------------------------------------- defc FindPrevAllFiles 'SetSearchDirection - NOREFRESH' 'RepeatFindAllFiles' ; --------------------------------------------------------------------------- defc FindMark if FileIsMarked() then -- Get active mark coordinates and fileid getmark FirstLine, LastLine, FirstCol, LastCol, MarkFileid if LastLine <> FirstLine then -- Take up to one line LastLine = FirstLine endline LastCol = .col endif SearchString = substr( textline( FirstLine ), FirstCol, LastCol - FirstCol + 1) if SearchString <> '' then 'l '\1''SearchString endif else 'SayError -280' -- Text not marked endif ; --------------------------------------------------------------------------- ; Find word under cursor -- if arg( 1): -- under pointer. defc FindWord -- If arg( 1) specified and > 0: Set cursor to pos of pointer. if arg( 1) then 'MH_GoToLastClick' endif lrc = 1 StartLine = .line StartCol = .col call pEnd_Word() LastCol = .col call pBegin_Word() FirstCol = .col -- Start search after current word .col = LastCol + 1 SearchString = substr( textline( StartLine), FirstCol, LastCol - FirstCol + 1) if SearchString <> '' then 'l '\1''SearchString lrc = rc endif if lrc <> 0 then .col = StartCol endif ; --------------------------------------------------------------------------- ; Find identifier under cursor -- if arg( 1) > 0: -- under pointer. defc FindToken, FindIdentifier -- If arg( 1) specified and > 0: Set cursor to pos of pointer. if arg( 1) then 'MH_GoToLastClick' endif lrc = 1 call pSave_Pos( savedpos) if Find_Token( startcol, endcol) then -- find_token returns first and last col of the found string. -- Therefore search shall start from 1 col after it. .col = endcol + 1 -- The standard cmd 'locate' won't set standard rc. The standard -- 'Locate' always returns rc = ''. -- Standard commands that don't change rc (are there more?): -- 'locate', 'edit' -- This is fixed in NEPMD. -- The standard commands 'Quit', 'Save', 'Name',... do change rc. -- Therefore 'Locate' now calls the proc locate, that sets rc -- correctly. rc is the rc from 'xcom locate'. -- (rc is a universal var, that doesn't need the universal definition.) -- 'w' activates word search for the 'l' command, not only for the -- string under the cursor. SavedLastFindArgs = GetLastFindArgs() SearchString = substr( textline( .line), startcol, (endcol - startcol) + 1) -- Use standard 'Locate' instead of 'xcom l' to keep current user -- options, highlight it or give a message if not found. 'l '\1''SearchString''\1'w' lrc = rc endif --sayerror 'defc findword: lrc = 'lrc if lrc <> 0 then -- if not found call pRestore_Pos( savedpos) endif ; --------------------------------------------------------------------------- ; Find a token around the cursor. ; Syntax: rc = Find_Token( startcol, endcol [, seps [, diads [, trailingseps]]]) ; o startcol and endcol are returned and must be specified as vars. ; o To specify an empty value for seps, diads or trailingseps, 'NONE:' ; must be specified. An empty value uses the default value. ; o diads must be a space-separated list of strings of any length. The ; original definition allows only for 2-char strings. ; o trailingseps was added to handle the end of a token specially. ; o rc = '' cursor is on a separator ; o rc = 1 cursor is on a token ; o rc = 2 cursor is on a diad defproc Find_Token( var startcol, var endcol) startcol = 0 endcol = 0 if arg( 3) == '' then token_separators = ' ~`!%^&*()-+=][{}|\:;?/><,''"'\t elseif upcase( arg( 3)) = 'NONE:' then token_separators = '' else token_separators = arg( 3) endif if arg( 4) == '' then diads = '-> ++ -- << >> <= >= && || += -= *= /= %= �= &= |= :: /* */' elseif upcase( arg( 4)) = 'NONE:' then diads = '' else diads = arg( 4) endif if arg( 5) == '' then trailing_token_separators = '.:,;!?' elseif upcase( arg( 5)) = 'NONE:' then trailing_token_separators = '' else trailing_token_separators = arg( 5) endif getline LineStr len = length( LineStr) if .col > len | pos( substr( LineStr, .col, 1), ' '\t) then -- Past end of line, or over whitespace return endif pstart = .col sepcol = verify( LineStr, token_separators, 'M', pStart) diadcol = 0 diad = '' do w = 1 to words( diads) next = word( diads, w) nextlen = length( next) pstart = .col -- The cursor may be placed within a diad do l = 1 to nextlen p = pos( next, LineStr, pStart) if p > 0 & (p < diadcol | diadcol = 0) then diadcol = p diad = next leave -- l endif if pstart < 2 then leave -- l else pstart = pstart - 1 endif enddo enddo diadlen = length( diad) do l = 1 to diadlen if .col = diadcol + l - 1 then startcol = diadcol endcol = diadcol + diadlen - 1 return 2 endif enddo if .col = sepcol then startcol = sepcol endcol = sepcol return 2 endif if sepcol > 1 & (sepcol <= diadcol | diadcol = 0) then endcol = sepcol - 1 elseif diadcol > 1 & (diadcol < sepcol | sepcol = 0) then endcol = diadcol - 1 else endcol = len endif if pos( substr( LineStr, endcol, 1), trailing_token_separators) then endcol = endcol - 1 endif RevLineStr = reverse( LineStr) pStart = len - .col + 1 sepcol = verify( RevLineStr, token_separators, 'M', pStart) diadcol = 0 diad = '' do w = 1 to words( diads) next = word( diads, w) p = pos( next, RevLineStr, pStart) if p > diadcol then diadcol = p diad = next endif enddo if sepcol > 1 & (sepcol <= diadcol | diadcol = 0) then startcol = len - sepcol + 2 elseif diadcol > 1 & (diadcol < sepcol | sepcol = 0) then startcol = len - diadcol + 2 else startcol = 1 endif return 1 ; --------------------------------------------------------------------------- ; Symtax: CurWord = GetWordUnderCursor( [Seps, [Diads [, TrailSeps]]]) ; Default values if empty or no args specified: ; Seps = ' '\9 (space and tab), Diads = 'NONE:', TrailSeps = 'NONE:' defproc GetWordUnderCursor do once = 1 to 1 Seps = arg( 1) if Seps == '' then Seps = ' '\9 endif Diads = arg( 2) if Diads == '' then Diads = 'NONE:' endif TrailSeps = arg( 3) if TrailSeps == '' then TrailSeps = 'NONE:' endif CurWord = '' --dprintf( 'Seps = >'Seps'<, Diads = >'Diads'<, TrailSeps = >'TrailSeps'<') if not Find_Token( StartCol, EndCol, Seps, Diads, TrailSeps) then leave endif getline LineStr CurWord = substr( LineStr, StartCol, EndCol - StartCol + 1) enddo return CurWord ; --------------------------------------------------------------------------- ; Symtax: CurIdentifier = GetIdentifierUnderCursor() ; This uses the default values of Find_Token for to parse a C identifier. defproc GetIdentifierUnderCursor do once = 1 to 1 CurWord = '' if not Find_Token( StartCol, EndCol) then leave endif getline LineStr CurIdentifier = substr( LineStr, StartCol, EndCol - StartCol + 1) enddo return CurIdentifier ; --------------------------------------------------------------------------- ; The is a short cmd for xcom L without a msg and with centering and ; highlighting. It uses case-sensitiveness of the current file's mode. ; This can't be used repeatedly. It always starts at the top of current file. defc FindTop parse arg SearchStr SearchStr = strip( SearchStr) if SearchStr <> '' then Mode = GetMode() fCaseSensitive = QueryModeKey( Mode, 'CaseSensitive') if fCaseSensitive then Options = 't' else Options = 'tc' endif display -14 -- disables all messsage output 'xcom L '\1''SearchStr''\1''Options display 14 if not rc then 'CenterLine' 'PostMe PostMe HighlightMatch' endif endif ; --------------------------------------------------------------------------- ; The is a short cmd for xcom L without a msg and with centering and ; highlighting. It uses case-sensitiveness of the current file's mode. ; This can't be used repeatedly without moving the cursor in between. ; It always starts at the current cursor position. defc Find parse arg SearchStr SearchStr = strip( SearchStr) if SearchStr <> '' then Mode = GetMode() fCaseSensitive = QueryModeKey( Mode, 'CaseSensitive') if fCaseSensitive then Options = '' else Options = 'c' endif display -14 -- disables all messsage output 'xcom L '\1''SearchStr''\1''Options display 14 if not rc then 'CenterLine' 'PostMe PostMe HighlightMatch' endif endif ; --------------------------------------------------------------------------- defc ShowSearch getsearch CurSearch Next = 'Last search = ['cursearch'], last search args = ['GetLastFindArgs()']' || ', last change args = ['GetLastChangeArgs()']' 'SayHint' Next dprintf( Next) ; --------------------------------------------------------------------------- ; Set vertical scroll position. This is useful after a locate action to ; keep the cursor in a defined area of the window. ; Syntax: SetScrollAfterSearch topval botval ; positive values mean scroll space from top (in lines) ; negative values mean scroll space from bottom (in lines) defc SetScrollAfterSearch KeyPath = '\NEPMD\User\CursorPos\ScrollAfterSearch' DefaultValue = '26 -4' -- if executed with a num as arg parse value arg( 1) with topval botval if IsNum( topval) & IsNum( botval) then call WriteConfigKey( KeyPath, arg( 1)) if isadefproc( 'MenuText_scrollafterlocate') then MenuText_scrollafterlocate() endif return endif -- else open entrybox Title = 'Configure line position on screen after locate' Text = 'Enter number of lines from top and from bottom (negative values for vspace).' IniValue = QueryConfigKey( KeyPath) If IniValue = 0 | IniValue = '' then DefaultButton = 3 elseif IniValue < 0 then DefaultButton = 2 else DefaultButton = 1 endif -- strip + or - IniValue = strip( IniValue) parse value EntryBox( Title, '/'OK__MSG'/~Reset/'CANCEL__MSG, -- max. 4 buttons IniValue, '', 260, atoi( DefaultButton) || atoi( 0000) || -- help id GethWndC( APP_HANDLE) || Text) with Button 2 NewValue \0 -- strip + or - NewValue = strip( NewValue) if Button = \1 then 'SetScrollAfterSearch' NewValue return elseif Button = \2 then 'SetScrollAfterSearch 'DefaultValue return elseif Button = \3 then return endif ; --------------------------------------------------------------------------- defc GotoLineDlg Title = 'Go to line' Text = 'Enter line number and optionally a column number:' --Text = Text''copies( ' ', max( 100 - length(Text), 0)) Entry = '' parse value EntryBox( Title, '', Entry, 0, 240, atoi(1) || atoi(0) || atol(0) || Text) with button 2 NewLine \0 NewLine = strip( NewLine) if button = \1 & NewLine <> '' then 'GoTo' NewLine endif ; --------------------------------------------------------------------------- const compile if not defined( EGREP_METACHARACTERS) -- JBSQ: This may need to changed if the grep code ever supports {, } -- and possibly other egrep metacharacters EGREP_METACHARACTERS = '\[]()?*+^$.:|~#@&' compile endif ; --------------------------------------------------------------------------- ; This routine takes a "search-for-this" search string and it inserts escape ; characters in front of any extended grep metacharacters. ; For example, if the search string is "(abc)" (i.e. find "(abc)"), this ; routine returns "\(abc\)" because "(" and ")" are extended grep ; metacharacters and so they must be "escaped" with "\". defproc EscapeSearchChars( SearchStr) pStart = 1 do forever if SearchStr == '' then leave endif pFound = verify( SearchStr, EGREP_METACHARACTERS, 'M', pStart) if not pFound then leave else SearchStr = leftstr( SearchStr, pFound - 1)'\'substr( SearchStr, pFound) pStart = pFound + 2 endif enddo return SearchStr ; --------------------------------------------------------------------------- ; Syntax: rcx = SearchReplaceLine( SearchStr, ReplaceStr, ReplaceTimes ; [, SearchOpt [, Line , [StartCol [, EndCol]]]]) ; Returns: ; rcx = 0 line changed ; rcx = 1 line not changed ; Default values for the optional args: ; SearchOpt = '' ; Line = current line ; StartCol = current column ; EndCol = line end ; o If '' is specified as SearchStr, the entire string from StartCol to ; EndCol is replaced. ; o Replaces a search mask on one line only. ; o Found SearchStr is replaced ReplaceTimes times. ; o If ReplaceTimes is empty or 0, all occurrences between StartCol and ; EndCol are replaced. ; o If StartCol is empty, the current .col is used. ; o If EndCol is empty or -1, the rest of the line is searched. ; o Any output is suppressed. Cursor and scroll pos. and previous search ; args are restored after processing. ; o This can be used instead of the replaceline statement to preserve ; attributes (e.g. bookmarks). defproc SearchReplaceLine( SearchStr, ReplaceStr, ReplaceTimes) if ReplaceTimes = '' then ReplaceTimes = 0 endif SearchOpt = arg( 4) Line = arg( 5) if Line = '' then Line = .line endif -- Ensure that Line exists LastLine = .last if Line > LastLine then do l = 1 to Line - LastLine insertline '', .last + 1 enddo endif StartCol = arg( 6) if StartCol = '' then StartCol = .col endif EndCol = arg( 7) if EndCol = '' then EndCol = -1 -- -1 means: search until end of line endif rcx = 1 fGrep = 0 if pos( 'g', lowcase( SearchOpt)) | pos( 'x', lowcase( SearchOpt)) then fGrep = 1 endif pSave_Pos( savepos) getsearch savesearch if SearchStr = '' then LineStr = textline( Line) if EndCol = -1 | EndCol >= 1599 then SearchStr = substr( LineStr, StartCol) else SearchStr = substr( LineStr, StartCol, Max( 0, EndCol - StartCol + 1)) endif endif --dprintf( 'SearchReplaceLine: SearchStr = ['SearchStr']') if SearchStr == '' then LineStr = textline( Line) if LineStr == '' then -- Insert a space to make xcom l and xcom c work OldLine = .line .lineg = Line TypeChars( ' ') .lineg = OldLine SearchStr = ' ' else SearchStr = LineStr endif endif .col = StartCol .lineg = Line ProcessCount = 0 do forever ProcessCount = ProcessCount + 1 -- Check processing number if ReplaceTimes > 0 then if ProcessCount > ReplaceTimes then leave endif endif display -14 -- Search 'xcom l '\1''SearchStr''\1''SearchOpt display 14 -- Check rc lrc = rc if lrc then leave endif -- Check pos. if .line <> Line then leave endif if EndCol > -1 then if .col > EndCol then leave endif endif -- Get line length before replace if fGrep then LineStr = textline( .line) LineLen = length( LineStr) endif display -14 -- Replace 'xcom c '\1''SearchStr''\1''ReplaceStr''\1''SearchOpt display 14 -- Check rc crc = rc if crc then leave endif rcx = 0 -- line changed -- Move cursor after replace, adapt EndCol if fGrep then NewLineStr = textline( .line) NewLineLen = length( NewLineStr) DiffLen = NewLineLen - LineLen else DiffLen = length( ReplaceStr) - length( SearchStr) endif .col = .col + DiffLen if EndCol > -1 then EndCol = EndCol + DiffLen endif -- Check pos. if EndCol > -1 then if .col > EndCol then leave endif endif enddo setsearch savesearch pRestore_Pos( savepos) return rcx ; --------------------------------------------------------------------------- ; Syntax: pReplaceLine( ReplaceStr [, LineNum [, FileId]]) ; o This can be used instead of the replaceline statement to preserve ; attributes (e.g. bookmarks). It has the same args. defproc pReplaceLine( ReplaceStr) LineNum = arg( 2) if LineNum = '' then LineNum = .line endif getfileid StartFid fSwitchFile = 0 ReplaceFid = arg( 3) if ReplaceFid = '' then -- nop elseif ReplaceFid <> StartFid then fSwitchFile = 1 endif if fSwitchFile then activatefile ReplaceFid endif --dprintf( 'ReplaceStr = ['ReplaceStr'], LineNum = 'LineNum) rcx = SearchReplaceLine( '', ReplaceStr, 1, '', LineNum, 1) if fSwitchFile then activatefile StartFid endif return ; --------------------------------------------------------------------------- ; This is used by Alt+1. It ignores comments. defc FindStringInCode SearchString = arg( 1) Mode = GetMode() call pSave_Pos( savedpos) --dprintf( 'FindStringInCode: arg( 1) = 'arg( 1)', .filename = '.filename) fCaseSensitive = QueryModeKey( Mode, 'CaseSensitive') if fCaseSensitive = 0 then CaseOpt = 'c' -- ignore else CaseOpt = 'e' -- exact endif Delim = \1 SearchOptions = SortSearchOptions( 'wt+fa'CaseOpt) fWordOption = 1 FindArgs = Delim''SearchString''Delim''SearchOptions -- First try word search display -11 -- Enable only errors to the messageline 'xcom l 'FindArgs lrc = rc display 11 --dprintf( 'FindStringInCode: xcom l 'FindArgs', rc = 'rc) -- If nothing found, try normal search if lrc then SearchOptions = SortSearchOptions( 't+fa'CaseOpt) fWordOption = 0 FindArgs = Delim''SearchString''Delim''SearchOptions display -11 -- Enable only errors to the messageline 'xcom l 'FindArgs lrc = rc display 11 endif PrevPos = .line .col do forever -- Check for comments. Strings are valid if a cmd is searched. if InsideComment( Mode) then -- Search again display -11 -- Enable only errors to the messageline repeatfind -- FindArgs are saved at the end, so this works lrc = rc -- also for xcom l and option t display 11 if lrc then leave -- Recognize an infinite loop elseif .line .col = PrevPos then leave endif PrevPos = .line .col iterate endif leave enddo call pSave_Pos( lpos) if lrc then -- Report the error message of xcom l or repeatfind here --'SayError 'sayerrortext( lrc) -- Try normal search if xcom l or repeatfind were not successful 'FindString 'SearchString else line = .line col = .col len = length( SearchString) PosData = line col len -- 'xcom l' was used instead of 'l'. Make F3 (FindNext) work for this. --dprintf( 'FindStringInCode: SetLastFindArgs( 'FindArgs')') call SetLastFindArgs( FindArgs) -- This proc is often used for newly-loaded files. It opens the file -- without a dialog in the way. Therefore better center the found -- line. call ScrollAfterSearch( savedpos, lpos, len, '', 'C C') -- 'xcom l' was used instead of 'l'. Explicitely highlight found string. 'PostMe HighlightMatch' PosData endif ; --------------------------------------------------------------------------- defc FindString FindString = arg( 1) Mode = GetMode() call pSave_Pos( savedpos) --dprintf( 'SearchString: arg( 1) = 'arg( 1)', .filename = '.filename) fCaseSensitive = QueryModeKey( Mode, 'CaseSensitive') if fCaseSensitive = 0 then CaseOpt = 'c' -- ignore else CaseOpt = 'e' -- exact endif Delim = \1 SearchOptions = SortSearchOptions( 'wt+fa'CaseOpt) fWordOption = 1 FindArgs = Delim''FindString''Delim''SearchOptions -- First try word search display -11 -- Enable only errors to the messageline 'xcom l 'FindArgs lrc = rc display 11 --dprintf( 'FindString: xcom l 'FindArgs', rc = 'rc) -- If nothing found, try normal search if lrc then SearchOptions = SortSearchOptions( 't+fa'CaseOpt) fWordOption = 0 FindArgs = Delim''FindString''Delim''SearchOptions display -11 -- Enable only errors to the messageline 'xcom l 'FindArgs lrc = rc display 11 endif call pSave_Pos( lpos) if lrc then -- Report the error message of xcom l or repeatfind here 'SayError 'sayerrortext( lrc) else line = .line col = .col len = length( FindString) PosData = line col len -- 'xcom l' was used instead of 'l'. Make F3 (FindNext) work for this. --dprintf( 'FindString: SetLastFindArgs( 'FindArgs')') call SetLastFindArgs( FindArgs) -- This proc is often used for newly-loaded files. It opens the file -- without a dialog in the way. Therefore better center the found -- line. call ScrollAfterSearch( savedpos, lpos, len, '', 'C C') -- 'xcom l' was used instead of 'l'. Explicitely highlight found string. 'PostMe HighlightMatch' PosData endif