home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / p2demo21.exe / PEL / SEARCH.PEL < prev    next >
Text File  |  1995-04-19  |  51KB  |  1,890 lines

  1. # $Header:   P:\source\wmacros\search.pev   1.99   19 Apr 1995 18:29:50   PFHDWM0  $
  2. # $Tabs:4 7$
  3.  
  4. ##############################################################################
  5. #
  6. #       Compuware Corporation
  7. #         31440 Northwestern Highway
  8. #           Farmington Hills, Michigan 48334-2564
  9. #
  10. #   This source code listing contains information that is
  11. #   proprietary to Compuware Corporation and may not be copied
  12. #   duplicated, translated, transmitted, stored, retrieved
  13. #   or in any manner or by any method conveyed or disclosed
  14. #   to a third party or parties without express written
  15. #   permission from Compuware Corporation.
  16. #
  17. #  
  18. ##############################################################################
  19.  
  20. #### $Workfile:   search.pel  $: support for search/replace
  21.  
  22. ## search flag settings used by search and replace
  23. #
  24.         # primitive flags:
  25.  
  26. global SEARCH_MAXIMAL_MATCH     = 0x0001
  27. global SEARCH_BLOCK             = 0x0002
  28. global SEARCH_FORWARD           = 0x0004  # backwards = 0
  29. global SEARCH_BACKWARD          = 0x0000
  30. global SEARCH_WRAPS             = 0x0008
  31.  
  32. global SEARCH_REGEX             = 0x0010
  33. global SEARCH_CASE              = 0x0020
  34. global SEARCH_ADVANCE           = 0x0040
  35. global SEARCH_WHOLE_WORD        = 0x0080
  36.  
  37. global SEARCH_ONCE_PER_LINE     = 0x0100
  38.  
  39. # The follow globals are only used here
  40. global SEARCH_HIGHLIGHT         = 0x0200  # Highlight after the search.
  41. global SEARCH_CENTER_CURSOR     = 0x0400  # normalize after search
  42. global SEARCH_GLOBAL            = 0x0800  # global search
  43. global SEARCH_MARK_CHG          = 0x1000  # mark changed lines (in lc area)
  44. global SEARCH_ALL_BUFFERS       = 0x2000  # search all buffers
  45.  
  46.         # Initial setting for search_flags. However,
  47.         # each keymap modifies to its own default settings.
  48.         
  49. # max_match, block, forward, regex, center
  50. global SEARCH_DEFAULT           = SEARCH_FORWARD+SEARCH_MAXIMAL_MATCH+ \
  51.                                   SEARCH_REGEX+SEARCH_CENTER_CURSOR+   \
  52.                                   SEARCH_HIGHLIGHT+SEARCH_WRAPS
  53.  
  54.         # case sensitive combos:
  55.  
  56. global SEARCH_FWD_REGEX_MAX     = SEARCH_CASE+SEARCH_FORWARD+SEARCH_REGEX+SEARCH_MAXIMAL_MATCH
  57. global SEARCH_BKWD_REGEX_MAX    = SEARCH_CASE+SEARCH_REGEX+SEARCH_MAXIMAL_MATCH
  58. global SEARCH_FWD_REGEX         = SEARCH_CASE+SEARCH_FORWARD+SEARCH_REGEX
  59. global SEARCH_BKWD_REGEX        = SEARCH_CASE+SEARCH_REGEX
  60. global SEARCH_FWD_ADV           = SEARCH_CASE+SEARCH_FORWARD+SEARCH_ADVANCE
  61. global SEARCH_FWD_REGEX_ADV     = SEARCH_CASE+SEARCH_FORWARD+SEARCH_REGEX+SEARCH_ADVANCE
  62. global SEARCH_BKWD_REGEX_ADV    = SEARCH_CASE+SEARCH_REGEX+SEARCH_ADVANCE
  63.  
  64.         # ignore case combos:
  65.  
  66. global SEARCH_FWD_REGEX_MAX_IG  = SEARCH_FORWARD+SEARCH_REGEX+SEARCH_MAXIMAL_MATCH
  67. global SEARCH_BKWD_REGEX_MAX_IG = SEARCH_REGEX+SEARCH_MAXIMAL_MATCH
  68. global SEARCH_FWD_REGEX_IG      = SEARCH_FORWARD+SEARCH_REGEX
  69. global SEARCH_BKWD_REGEX_IG     = SEARCH_REGEX
  70. global SEARCH_FWD_IG            = SEARCH_FORWARD
  71.  
  72. ## initial search settings
  73. #
  74. global  search_flags = SEARCH_DEFAULT                           #PUBLIC #INT
  75. global  search_pattern = ""
  76. global  replace_pattern = ""
  77.  
  78. ## Misc. vars:
  79.  
  80. global   MAX_SEARCH      = 0x7FFFFFFF    # search global search count
  81.  
  82. global   find_mark                       # string to mark finds with.
  83. global   change_mark                     # string to mark changes with.
  84.  
  85. #------------------ Search functions --------------------#
  86.  
  87. #
  88. # Search forward from the current position.  This function may also match
  89. # the current position.  The user is prompted for a search string.
  90. #
  91. function search_forward( patt )                          #PUBLIC #INT
  92. {
  93.    local rc
  94.  
  95.    toggle_search_flags(SEARCH_FORWARD, 1 )
  96.  
  97.    if ( selection_type() != NO_SELECTION )
  98.       search_flags = or( search_flags, SEARCH_BLOCK )
  99.    else
  100.       search_flags = and( search_flags, not( SEARCH_BLOCK ) )
  101.  
  102.    rc = sf_search( patt )
  103.  
  104.    return rc
  105. }
  106.  
  107. function context_search( )
  108. {
  109.    search_pattern = symbol_under_cursor()
  110.    search_forward( search_pattern )
  111. }
  112.  
  113. #
  114. # Search backward from the current position.  This function may also match
  115. # the current position.  The user is prompted for a search string.
  116. #
  117. global function search_backward( patt )                         #PUBLIC #INT
  118. {
  119.    local rc
  120.  
  121.    toggle_search_flags(SEARCH_FORWARD, 0 )
  122.  
  123.    if ( selection_type() != NO_SELECTION )
  124.       search_flags = or( search_flags, SEARCH_BLOCK )
  125.    else
  126.       search_flags = and( search_flags, not( SEARCH_BLOCK ) )
  127.  
  128.    rc = sf_search( patt )
  129.  
  130.    return rc
  131. }
  132.  
  133. #
  134. # Search from the current position using the current search_flag settings.
  135. # This function may also match the current position.  The user is
  136. # prompted for a search string.
  137. #
  138. function sf_search( patt, flags )                               #PUBLIC #INT
  139. {
  140.    local status;
  141.    local temp = search_flags
  142.  
  143.    # Turn off all-files and advance bits before search
  144.    #
  145.    search_flags = and(search_flags, not(SEARCH_ADVANCE+SEARCH_ALL_BUFFERS))
  146.  
  147.    if (argcount() > 1)
  148.       search_flags = flags;
  149.    
  150.    if ( !patt )
  151.       if ( (patt = search_prompt()) )
  152.          search_pattern = patt
  153.  
  154.    status = string_search( patt )
  155.  
  156.    # Turn advance bit back on
  157.    #
  158.    search_flags = or(temp, SEARCH_ADVANCE ) 
  159.    return status;
  160. }
  161.  
  162.  
  163. #
  164. # prompt for the search pattern and provide command history
  165. #
  166. local function search_prompt()
  167. {
  168.    local   arrow = and( search_flags, SEARCH_FORWARD ) ? "" : ""
  169.    local   regex = and( search_flags, SEARCH_REGEX ) ? "" : "(RE off) "
  170.  
  171.    return prompt_history( "SEARCH", arrow " Search " regex "for: ",
  172.                           search_pattern, 1, 1, "search_prompt" )
  173. }
  174.  
  175.  
  176. #
  177. # Begin searching from the current position for the next occurrence of
  178. # search_pattern ( the last successful search pattern).
  179. #
  180. # Use all of the "search_flags" settings that have been previously defined
  181. #
  182. #
  183. global function search_again()                                  #PUBLIC #INT
  184. {
  185.    local success = 0;
  186.    
  187.    # check for a previously successful search
  188.    #
  189.    if ( !search_pattern )
  190.    {
  191.       warning( "No previous search pattern." )
  192.       return FALSE
  193.    }
  194.  
  195.    # begin the search, but instruct search() to
  196.    # move forward or backward 1 character (depending on the
  197.    # direction of the search)
  198.    #
  199.    save_position()
  200.    message( "" )
  201.  
  202.    search_flags = or(search_flags, SEARCH_ADVANCE)           
  203.  
  204.    success = string_search( search_pattern );
  205.  
  206.    if ( success )
  207.       restore_position( 0 )
  208.    else 
  209.       restore_position( 1 )
  210.  
  211.    # after the search, turn on the search_advance bit.  So the first time
  212.    # it will just search, after that, you get search again
  213.    #
  214.    search_flags = or(search_flags, SEARCH_ADVANCE)           
  215.  
  216.    return success;
  217. }
  218.  
  219. #
  220. # search_again, but force the direction forwards or backwards
  221. #
  222. global function search_again_forward()                          #PUBLIC #INT
  223. {
  224.    toggle_search_flags(SEARCH_FORWARD, 1 )
  225.    return search_again()
  226. }
  227.  
  228. global function search_again_backward()                         #PUBLIC #INT
  229. {
  230.    toggle_search_flags(SEARCH_FORWARD, 0 )
  231.    return search_again()
  232. }
  233.  
  234. #
  235. # Actually perform the search for the string now. Use the current
  236. # "search_flags" settings except for the SEARCH_ADVANCE flag.
  237. #
  238. # It is assumed that the user has been prompted for a search string
  239. # and if one doesn't exist, nothing is done here.
  240. #
  241. local search_selection # array used to save the selection for search_agains.
  242. function string_search( sspatt, sflags )
  243. {
  244.    local status
  245.    local prevMessage
  246.    local block_search = FALSE
  247.    local bottom_mark 
  248.    local top_mark    
  249.    local bottom_line 
  250.    local bottom_col  
  251.    local top_line    
  252.    local top_col     
  253.  
  254.    unhilight_temp_selection()
  255.  
  256.    if ( !sspatt )
  257.       return FALSE
  258.    else
  259.       add_prompt_history("SEARCH", sspatt);
  260.  
  261.    # set the global search_flags to parameter if one isn't passed in
  262.    #
  263.    if (argcount() == 1 )
  264.       sflags = search_flags
  265.  
  266.    #
  267.    # set parameter to variable just in case this is called somewhere else
  268.    # where it's not done
  269.    #
  270.    search_pattern = sspatt;
  271.  
  272.    message( "Searching..." )
  273.  
  274.    # if we are searching a block...
  275.    #
  276.    if ( and(search_flags, SEARCH_BLOCK))
  277.    {
  278.       if (selection_type() != NO_SELECTION )
  279.       {
  280.          # if there is currently a selection, 
  281.          #    save the selection and position cursor at the beginning or end
  282.          #    of the selection depending on direction
  283.          #
  284.          save_position()
  285.          end_selection()
  286.  
  287.          # delete the last saved selection (if there is one)
  288.          #
  289.          if (search_selection_ok())
  290.             delete_search_selection()
  291.  
  292.          block_search          = TRUE
  293.  
  294.          save_search_selection( TRUE )
  295.  
  296.          if ( selection_type() == LINE_SELECTION )
  297.            goto_bol();
  298.       }
  299.       else if (and(search_flags, SEARCH_ADVANCE) && search_selection_ok())
  300.       {
  301.          # if we are searching for the next occurance,
  302.          #     restore the old selection (if there is one).
  303.          #
  304.          restore_search_selection()
  305.          block_search = TRUE
  306.       }
  307.    }
  308.    else if (search_selection_ok())
  309.       delete_search_selection()
  310.  
  311.    status = search( sspatt, sflags )
  312.  
  313.    if ( status )
  314.    {
  315.       if ( block_search )
  316.       {
  317.          restore_position( FALSE )
  318.          # need to update here to get selection to redraw properly
  319.          update_current_view()
  320.  
  321.          remove_selection()
  322.          update_current_view()
  323.       }
  324.  
  325.       message( "Search completed." )
  326.       if ( and(search_flags, SEARCH_CENTER_CURSOR) )
  327.          center_cursor()
  328.  
  329.       highlightSearch()
  330.    }
  331.    else 
  332.    {
  333.       if ( block_search )
  334.       {
  335.          restore_position( TRUE )
  336.          remove_selection()
  337.          delete_search_selection()
  338.          update_current_view()
  339.          warning( "Pattern \"%s\" not found in the block.", search_pattern )
  340.       }
  341.       else
  342.          warning( "Pattern \"%s\" not found.", search_pattern )
  343.    }
  344.    return status
  345. }
  346.  
  347. # Function to check to see if there is a search_selection
  348. #
  349. global function search_selection_ok()
  350. {
  351.    return (search_selection.type != NO_SELECTION )
  352. }
  353.  
  354. global function save_search_selection( moveCursor )
  355. {
  356.    local bottom_mark 
  357.    local top_mark    
  358.    local bottom_line 
  359.    local bottom_col  
  360.    local top_line    
  361.    local top_col     
  362.  
  363.    search_selection.type = selection_type()
  364.  
  365.    # calculate the bottom and top of the selection
  366.    bottom_mark = selection_mark_bottom()
  367.    top_mark    = selection_mark_top()
  368.  
  369.    bottom_line = mark_line( bottom_mark )
  370.    bottom_col  = max( mark_column(bottom_mark), mark_column(top_mark) )
  371.  
  372.    top_line    = mark_line( top_mark )
  373.    top_col     = min( mark_column(bottom_mark), mark_column(top_mark) )
  374.  
  375.    if ( !moveCursor )
  376.       save_position()
  377.  
  378.    # save the selection marks, ending up with the cursor at the
  379.    # appropriate spot.
  380.    if ( and(search_flags, SEARCH_FORWARD ) )
  381.    {
  382.       goto_pos( bottom_line, bottom_col )
  383.       search_selection.bottom = create_mark(pick_unused_mark())
  384.    
  385.       goto_pos( top_line, top_col )
  386.       search_selection.top = create_mark(pick_unused_mark())
  387.    }
  388.    else
  389.    {
  390.       goto_pos( top_line, top_col )
  391.       search_selection.top = create_mark(pick_unused_mark())
  392.    
  393.       goto_pos( bottom_line, bottom_col )
  394.       search_selection.bottom = create_mark(pick_unused_mark())
  395.    }
  396.  
  397.    if ( !moveCursor )
  398.       restore_position( TRUE )
  399. }
  400.  
  401. # Function to hilight the search block.
  402. #
  403. global function restore_search_selection()
  404. {
  405. #   begin_selection(search_selection.type, search_selection.top)
  406. #   end_selection(search_selection.bottom)
  407.  
  408.    save_position()
  409.  
  410.    goto_mark( search_selection.top )
  411.    begin_selection( search_selection.type )
  412.  
  413.    goto_mark( search_selection.bottom )
  414.    end_selection()
  415.  
  416.    restore_position( TRUE )
  417.  
  418. #  update_current_view()
  419. #  display_update()
  420. }
  421.  
  422. # Function to delete the search block.
  423. #
  424. global function delete_search_selection()
  425. {
  426.    delete_mark(search_selection.top)
  427.    delete_mark(search_selection.bottom)
  428.    delete search_selection
  429. }
  430.  
  431. ## Highlight the search target.
  432. #
  433. #  If called from the keyboard, display the highlight and wait until another
  434. #  key is pressed and then remove it.
  435. #
  436. # original function commented out because could not figure out when
  437. # keyboard_input_pending was changed.  This replacement works well
  438. function highlightSearch(dontSaveSelection)
  439. {
  440.    if ( and( search_flags, SEARCH_HIGHLIGHT ) )
  441.       highlightSearchOn(dontSaveSelection)
  442. }
  443.  
  444. function highlightSearchOn(dontSaveSelection)
  445. {
  446.    local   slen
  447.    local   stype = NORMAL_SELECTION
  448.  
  449.    slen = search_string_length - search_cursor_offset
  450.    if ( slen == 0 )
  451.       stype = INCLUSIVE_SELECTION
  452.  
  453.    create_offset_selection(stype, buffer_offset + slen, buffer_offset, \
  454.                         !dontSaveSelection)
  455. }
  456.  
  457. #
  458. # Find all occurences of the src string one at a time.
  459. # And return an array of found strings with index 0 containing
  460. # the count of found strings.  Other indexes are the line number where
  461. # the strings are located
  462. #
  463. global function find_all( srch, prompt )
  464. {
  465.    local   ch                              # confirm character
  466.    local   found, last, slen, line
  467.    local   tmpFlags
  468.    local   wrapPass
  469.    local   wrapOffset
  470.    local   strings_found                   # number of replacement done
  471.  
  472.    local   srchFwd    = and( search_flags, SEARCH_FORWARD )
  473.    local   remaining  = search_count > 1 ? search_count : MAX_SEARCH
  474.    local   mark_lines = linecommands_enabled && linenumber_width && \
  475.                         length(find_mark)
  476.  
  477.    local   found_array
  478.  
  479.    prompt += 0;
  480.    found_array[0] = 0
  481.  
  482.    if (!mark_lines && ( argcount() == 1 ) )
  483.       prompt = TRUE
  484.  
  485.    # make sure search pattern is present
  486.    #
  487.    if ( !srch )
  488.    {
  489.       srch = search_prompt()
  490.       if ( !srch )
  491.          return found_array
  492.    }
  493.  
  494.    # set search variable and add to history
  495.    #
  496.    search_pattern = srch
  497.    add_prompt_history("SEARCH", search_pattern)
  498.  
  499.    #
  500.    # Prepare to perform the search
  501.    #
  502.  
  503.    # init for wrapping
  504.    wrapPass = !!and( search_flags, SEARCH_WRAPS )
  505.  
  506.    if ( selection_type() != NO_SELECTION )  
  507.       wrapPass = 0;
  508.  
  509.    wrapOffset = buffer_offset
  510.  
  511.    tmpFlags = and( search_flags, not( SEARCH_ADVANCE + SEARCH_WRAPS ))
  512.  
  513.    # save original position
  514.    save_position()
  515.  
  516.    #
  517.    # continue to search until the user says no or we can't find any more.
  518.    #
  519.    save_selection()
  520.  
  521.    search_count = 0
  522.    while ( remaining )
  523.    {
  524.       save_position()
  525.       restore_selection()
  526.       restore_position(1)
  527.       found = search( srch, tmpFlags )
  528.       save_selection()
  529.  
  530.       tmpFlags = and( tmpFlags, not( SEARCH_ADVANCE ))
  531.  
  532.       # check for normal termination and handle wrapping
  533.       #
  534.       if (( wrapPass == 2 ) && ( buffer_offset >= wrapOffset ))
  535.          found = FALSE
  536.  
  537.       if ( !found )
  538.       {
  539.          if ( wrapPass == 1 )
  540.          {
  541.             searchWrap( srchFwd )
  542.             wrapPass = 2
  543.             continue        # try again
  544.          }
  545.          else
  546.             break   # we're done
  547.       }
  548.  
  549.       remaining     -= found
  550.       strings_found += found
  551. #      found_array[ strings_found ] = read_line()
  552.       found_array[ current_line ] = read_line()
  553.  
  554.       if (mark_lines)
  555.       {
  556.          #
  557.          # mark the line the string is on.
  558.          #
  559.          save_position()
  560.          slen = search_string_length - search_cursor_offset
  561.  
  562.          # goto the beginning of word
  563.          goto_buffer_offset( buffer_offset - slen )
  564.          last = current_line
  565.  
  566.          # goto end of the word
  567.          goto_buffer_offset(buffer_offset + slen)
  568.          line = current_line
  569.  
  570.          do {
  571.             line_command[line] = find_mark
  572.             line--
  573.          } while (line > last)
  574.          restore_position(1)
  575.       }
  576.  
  577.       if (prompt)
  578.       {
  579.          #
  580.          # highlight the search string found and wait for user input
  581.          #
  582.          highlightSearch(1)
  583.          ch = tolower( confirm( "Find Next [Yes|No]? ", "YyNn" ))
  584.          unhilight_temp_selection()
  585.          if ( ch == "n" )
  586.             break
  587.       }
  588.       skipSearchString( and( tmpFlags, SEARCH_FORWARD ))
  589.    }
  590.  
  591.    #
  592.    # go back to the original starting position
  593.    #
  594.    restore_position( !prompt )
  595.  
  596.    message( "Search complete; %d occurrence%s found.",
  597.              strings_found, strings_found == 1 ? "" : "s" )
  598.  
  599.    restore_selection()
  600.  
  601.    if (mark_lines)            # Make sure that any lines we marked
  602.       display_redraw()        # will be displayed.
  603.  
  604.    found_array[0] = strings_found
  605.    return found_array
  606. }
  607.  
  608. #------------------ Replace functions --------------------#
  609.  
  610. #
  611. # Search for the next occurrence of spatt and replace it with rpatt.
  612. # Use the current search_flag settings.
  613. # The function string_replace() is called to perform
  614. # any incremental or global replacements.
  615. #
  616. global function sf_replace( spatt, rpatt )                      #PUBLIC #INT
  617. {
  618.    local   arrow, retcode
  619.  
  620.    if ( !spatt )
  621.    {
  622.       #
  623.       # prompt for the search pattern and provide command history
  624.       #
  625.       arrow = and( search_flags, SEARCH_FORWARD ) ? "" : ""
  626.       spatt = prompt_history( "SEARCH",  arrow " Pattern: ", search_pattern, 1, 1, "search_prompt" )
  627.    }
  628.  
  629.    # turn off the all-files flag
  630.    #
  631.    search_flags = and(search_flags, not(SEARCH_ALL_BUFFERS))
  632.  
  633.    # set the search_count variable for later searches
  634.    #
  635.    if ( and( search_flags, SEARCH_GLOBAL ))
  636.    {
  637.       search_flags = and( search_flags, not(SEARCH_GLOBAL) )
  638.       search_count = MAX_SEARCH
  639.    }
  640.  
  641.    # if there is currently a selection, position cursor at beginning
  642.    # of selection depending on direction
  643.    #
  644.    if ( and(search_flags, SEARCH_BLOCK) && selection_type() != NO_SELECTION )
  645.    {
  646.       save_position()
  647.       end_selection()
  648.  
  649.       if ( and(search_flags, SEARCH_FORWARD ) )
  650.          goto_mark(selection_mark_top())
  651.       else
  652.          goto_mark(selection_mark_bottom())
  653.  
  654.       if ( selection_type() == LINE_SELECTION )
  655.         goto_bol();
  656.    }
  657.  
  658.    if ( argcount() > 1 )
  659.       retcode = string_replace( spatt, rpatt )
  660.    else
  661.       retcode = string_replace( spatt )
  662.  
  663.    if ( selection_type() != NO_SELECTION )
  664.    {
  665.       restore_position()
  666.       remove_selection()
  667.    }
  668.    return retcode;
  669. }
  670.  
  671. #
  672. # Search for the next occurrence of spatt and replace it with rpatt.
  673. # The function string_replace() is called to perform
  674. # any incremental or global replacements.
  675. #
  676. global function replace_forward( spatt, rpatt )                 #PUBLIC #INT
  677. {
  678.    local retcode
  679.    local old_sf = search_flags
  680.  
  681.    if ( selection_type() != NO_SELECTION )
  682.       search_flags = or( search_flags, SEARCH_BLOCK )
  683.    else
  684.       search_flags = and( search_flags, not( SEARCH_BLOCK ) )
  685.  
  686.    toggle_search_flags(SEARCH_FORWARD, 1 )
  687.  
  688.    if ( argcount() > 1 )
  689.       retcode = sf_replace( spatt, rpatt )
  690.    else
  691.       retcode = sf_replace( spatt )
  692.  
  693.    search_flags = old_sf
  694.  
  695.    return retcode
  696. }
  697.  
  698.  
  699. #
  700. # Search for the previous occurrence of spatt and replace it with rpatt.
  701. # The function string_replace() is called to perform
  702. # any incremental or global replacements.
  703. #
  704. global function replace_backward( spatt, rpatt )                #PUBLIC #INT
  705. {
  706.    local rc
  707.    local old_sf = search_flags
  708.  
  709.    toggle_search_flags(SEARCH_FORWARD, 0 )
  710.  
  711.    if ( selection_type() != NO_SELECTION )
  712.       search_flags = or( search_flags, SEARCH_BLOCK )
  713.    else
  714.       search_flags = and( search_flags, not( SEARCH_BLOCK ) )
  715.  
  716.    if ( argcount() > 1 )
  717.       rc = sf_replace( spatt, rpatt )
  718.    else
  719.       rc = sf_replace( spatt )
  720.  
  721.    search_flags = old_sf
  722.  
  723.    return rc
  724. }
  725.  
  726. #
  727. # Begin searching from the current position for the next occurrence of
  728. # search_pattern (the last successful search pattern) and replace it.
  729. #
  730. # Use all of the "search_flags" settings that have been previously defined
  731. #
  732. global function replace_again(noadvance)                        #PUBLIC #INT
  733. {
  734.    local direction, slen, line, last
  735.  
  736.    #
  737.    # make sure we have something to search for and something
  738.    # to replace it with.
  739.    #
  740.    if ( search_pattern && replace_pattern )
  741.    {
  742.       message( "Replacing..." )
  743.       if ( replace( search_pattern, replace_pattern,
  744.                     noadvance ? and(search_flags, not(SEARCH_ADVANCE)) \
  745.                               :  or(search_flags, SEARCH_ADVANCE)))
  746.       {
  747.          #
  748.          # we found it and replaced successfully
  749.          #
  750.          if (linecommands_enabled && linenumber_width && length(change_mark))
  751.          {
  752.             save_position()
  753.             slen = search_string_length - search_cursor_offset
  754.  
  755.             # goto the beginning of word
  756.             goto_buffer_offset( buffer_offset - slen )
  757.             last = current_line
  758.  
  759.             # goto end of the word
  760.             goto_buffer_offset(buffer_offset + slen)
  761.             line = current_line
  762.  
  763.             do {
  764.                line_command[line] = change_mark
  765.                line--
  766.             } while (line > last)
  767.             restore_position(1)
  768.          }
  769.          message( "Replacement complete." )
  770.          return TRUE
  771.       }
  772.       else
  773.          warning( "Pattern \"%s\" not found.", search_pattern )
  774.    }
  775.    else
  776.    {
  777.       #
  778.       # not enough information to do anything
  779.       #
  780.       warning( "No previous replacement pattern(s)." )
  781.    }
  782.    return FALSE
  783. }
  784.  
  785. #
  786. # Replace the "srch" string if found and prompt for multiple (or global)
  787. # replacements.
  788. #
  789. # We need to make sure that if found and replaced, skip of the previous
  790. # replacement so that we don't get into an infinite loop.
  791. #
  792. global function string_replace( srch, repl )                    #PUBLIC #INT
  793. {
  794.     local   changes_made            # number of replacement done
  795.     local   found_replacement       # at least one string was found
  796.     local   save_count
  797.     local   found
  798.     local   tmpFlags
  799.     local   srchFwd = and( search_flags, SEARCH_FORWARD )
  800.     local   prevMessage
  801.     local   wrapPass
  802.     local   wrapOffset
  803.     local   ch                              # confirm character
  804.     local   optype
  805.  
  806.     # save original search_count
  807.     #
  808.     save_count = search_count
  809.     search_count = 0
  810.  
  811.     # make sure search pattern is present
  812.     #
  813.     if ( !srch )
  814.       return 0
  815.  
  816.     # get the replacement string to use
  817.     #
  818.    if ( argcount() < 2 )
  819.       repl = prompt_history("REPLACE", "Replacement: ", replace_pattern, 1, 1, "replace_prompt" )
  820.  
  821.     # Check for ESC to differentiate between a CR and a canceled prompt.
  822.     #
  823.    if ( !repl && ( current_key == KEYCODE_ESC ))
  824.       return 0
  825.  
  826.    # set search and replace variables and add to history
  827.    #
  828.    replace_pattern = repl
  829.    search_pattern  = srch
  830.    add_prompt_history("REPLACE", replace_pattern)
  831.    add_prompt_history("SEARCH", search_pattern)
  832.  
  833.    #
  834.    # We have both strings now prepare to perform the replacement
  835.    #
  836.  
  837.    # init for wrapping
  838.    if ( selection_type() != NO_SELECTION )  
  839.       wrapPass = 0;
  840.    else
  841.       wrapPass = !!and( search_flags, SEARCH_WRAPS )
  842.  
  843.    wrapOffset = buffer_offset
  844.  
  845.    tmpFlags = and( search_flags, not( SEARCH_ADVANCE + SEARCH_WRAPS ))
  846.  
  847.    if (linecommands_enabled && linenumber_width && length(change_mark)) 
  848.       tmpFlags = or( tmpFlags, SEARCH_MARK_CHG )
  849.    else
  850.       tmpFlags = and( tmpFlags, not( SEARCH_MARK_CHG ))
  851.  
  852.    prevMessage = last_message
  853.  
  854.    # save original position
  855.    save_position()
  856.  
  857.    #
  858.    # continue to replace until the user says no or
  859.    # we can't replace any more.
  860.    #
  861.    save_selection()
  862.  
  863.    while ( TRUE )
  864.    {
  865.       save_position()
  866.       restore_selection()
  867.       restore_position(1)
  868.       found = search( srch, tmpFlags )
  869.       save_selection()
  870.  
  871. #     update_current_view()
  872.       display_update()
  873.  
  874.       tmpFlags = and( tmpFlags, not( SEARCH_ADVANCE ))
  875.  
  876.       # check for normal termination and handle wrapping
  877.       #
  878.       if (( wrapPass == 2 ) && ( buffer_offset >= wrapOffset ))
  879.          found = FALSE
  880.  
  881.       if ( !found )
  882.       {
  883.          if ( wrapPass == 1 )
  884.          {
  885.             searchWrap( srchFwd )
  886.             wrapPass = 2
  887.             continue        # try again
  888.          }
  889.          break   # we're done
  890.       }
  891.          
  892.       # at least one search string was found
  893.       found_replacement = TRUE
  894.  
  895.       #
  896.       # highlight the search string found and wait for user input
  897.       #
  898.       if ( save_count > 0 )
  899.          ch = "g"
  900.  
  901.       else
  902.       {
  903.          highlightSearch(1)
  904.          ch = tolower( confirm( "Change [Yes|No|Global]? ", "YyNnGg" ))
  905.          unhilight_temp_selection()
  906.  
  907.          if ( ch == "g" )
  908.             save_count = MAX_SEARCH
  909.       }
  910.       if ( ch == "y" )
  911.       {
  912.          # replace and skip over the replacement
  913.          replace( srch, repl, tmpFlags )
  914.          skipReplaceString( and( tmpFlags, SEARCH_FORWARD ))
  915.          changes_made++      
  916.       }
  917.       else if ( ch == "n" )
  918.       {
  919.          # skip this replacement
  920.          skipSearchString( and( tmpFlags, SEARCH_FORWARD ))
  921.          tmpFlags = or(tmpFlags, SEARCH_ADVANCE)
  922.       }
  923.       else if ( ch == "g" )
  924.       {
  925.          # global replace
  926.          search_count = save_count
  927.  
  928.          restore_selection()
  929.          changes_made += globalReplace( srch, repl, tmpFlags, srchFwd,
  930.                                         wrapPass, wrapOffset )
  931.          break
  932.       }
  933.       else
  934.       {
  935.          # replacement was canceled
  936.          #
  937.          unhilight_temp_selection()
  938.          restore_position( 0 )
  939.          restore_selection()
  940.          message( "Translation complete; %d occurrence%s changed.",
  941.                   changes_made, changes_made == 1 ? "" : "s" )
  942.          return changes_made
  943.       }
  944.    }       # while TRUE
  945.  
  946.    #
  947.    # go back to the original starting position
  948.    #
  949.    restore_position( 1 )
  950.  
  951.    # We found at least one string to replace.
  952.    # Display the number that were replaced.
  953.    #
  954.    message( "Translation complete; %d occurrence%s changed.",
  955.                       changes_made, \
  956.                       changes_made == 1 ? "" : "s" )
  957.  
  958.    restore_selection()
  959.    return changes_made
  960. }
  961.  
  962.  
  963. # Perform a global replace.  We will continue until we fail or
  964. # seach_count is satisfied.
  965. #
  966. global function globalReplace( srch, repl, tmpFlags, srchFwd, wrapPass,
  967.                                wrapOffset )
  968. {
  969.    local   mark_changes = and(tmpFlags, SEARCH_MARK_CHG)
  970.    local   remaining    = search_count
  971.    local   attempts     = 1
  972.    local   found
  973.    local   last
  974.    local   line
  975.    local   slen
  976.    local   totalFound
  977.  
  978.    message( "Replacing..." )
  979.    while (TRUE )
  980.    {
  981.       if ( wrapPass == 2 )
  982.       {
  983.          # If wrapping, any match after our starting position
  984.          # is a failure.
  985.          #
  986.          search_count = 1
  987.          if ( !search( srch, tmpFlags ) || ( buffer_offset >= wrapOffset ))
  988.             break
  989.  
  990.          attempts = 1
  991.       }
  992.       else if (!mark_changes)
  993.       {
  994.          # We update the screen every 50 replacements
  995.          # just to let the user know we're still alive.
  996.          #
  997.          attempts = (( remaining > 50 ) ? 50 : remaining )
  998.       }
  999.        
  1000.       search_count = attempts
  1001.       found        = replace( srch, repl, tmpFlags )
  1002.  
  1003.       if (mark_changes)
  1004.       {
  1005.          save_position()
  1006.          slen = search_string_length - search_cursor_offset
  1007.       
  1008.          # goto the beginning of word
  1009.          goto_buffer_offset( buffer_offset - slen )
  1010.          last = current_line
  1011.  
  1012.          # goto end of the word
  1013.          goto_buffer_offset(buffer_offset + slen)
  1014.          line = current_line
  1015.  
  1016.          do {
  1017.             line_command[line] = change_mark
  1018.             line--
  1019.          } while (line > last)
  1020.          restore_position(1)
  1021.       }
  1022.  
  1023.       remaining       -= found
  1024.       totalFound      += found
  1025.  
  1026.       # skip over the replacement
  1027.       #
  1028.       skipReplaceString( srchFwd )
  1029.  
  1030.       # check for normal termination and handle wrapping
  1031.       #
  1032.       if ( attempts != found )
  1033.       {
  1034.          if ( wrapPass == 1 )
  1035.          {
  1036.             searchWrap( srchFwd )
  1037.             wrapPass = 2    # try again
  1038.          } 
  1039.          else if ( wrapPass == 0 )
  1040.             break
  1041.       }
  1042.       else if ( remaining <= 0 )
  1043.          break   # we're done
  1044.    }
  1045.    return totalFound
  1046. }
  1047.  
  1048. global function skipReplaceString( direction )
  1049. {
  1050.    if ( direction )
  1051.    {
  1052.       next_char(( replace_string_length ? replace_string_length : 1 ) + \
  1053.                 ( search_string_length  ? 0 : 1 ))
  1054.    }
  1055.    else
  1056.       prev_char( 1 )
  1057. }
  1058.  
  1059. global function skipSearchString( direction )
  1060. {
  1061.    if ( direction )
  1062.       next_char( search_string_length ? search_string_length : 1 )
  1063.    else
  1064.       prev_char( 1 )
  1065. }
  1066.  
  1067. # wrap at the end of the search region
  1068. #
  1069. local function searchWrap( direction )
  1070. {
  1071.    if ( direction )
  1072.    {
  1073.       goto_buffer_top()
  1074.       goto_mark( selection_mark_top() )
  1075.    }
  1076.    else
  1077.    {
  1078.       goto_buffer_bottom()
  1079.       goto_mark( selection_mark_bottom() )
  1080.    }
  1081. }
  1082.  
  1083.  
  1084. #------------------ Incremental search functions --------------------#
  1085.  
  1086.  
  1087. #
  1088. # Perform an incremental search through the current buffer.
  1089. #
  1090. # This is accomplished by reading one character at a time from the keyboard
  1091. # and appending it to the current search string. If the string is not found
  1092. # the character is stripped from the search string and the previous buffer
  1093. # position is restored.
  1094. #
  1095. local reentrant_search_i = 0
  1096. local searchi_pattern    = ""
  1097.  
  1098. global function search_i()                                      #PUBLIC #VOID
  1099. {
  1100.    local   char       = ""
  1101.    local   ch         = 0
  1102.    local   level      = 0
  1103.    local   sf         = and( search_flags, not(SEARCH_REGEX+SEARCH_ADVANCE) )
  1104.  
  1105.    # don't allow reentering the search_i if we
  1106.    # are already in here
  1107.    if ( reentrant_search_i )
  1108.    {
  1109.       # just in case message has disappeared
  1110.       message( "Incremental-Search for: %s\334",
  1111.                quote_printf_string( searchi_pattern ))
  1112.       return;
  1113.    }
  1114.  
  1115.    searchi_pattern = ""
  1116.  
  1117.    reentrant_search_i = 1
  1118.  
  1119.    optional_function( "enable_status_bar_messages" )
  1120.  
  1121.    while ( TRUE )
  1122.    {
  1123.       # display the prompt message with a fake cursor
  1124.       message( "Incremental-Search for: %s\334",
  1125.                quote_printf_string( searchi_pattern ))
  1126.  
  1127.       # get the next ascii character from the keyboard
  1128.       # ignore extended character which have an ascii code of 0
  1129.       ch = getchar()
  1130.       if ( ch == 0 )
  1131.       {
  1132.          # clear the extended character scan code
  1133.          # out of the keyboard buffer
  1134.          getchar()
  1135.          beep()
  1136.          continue
  1137.       }
  1138.  
  1139.       # quit incremental searching when an ESC is pressed
  1140.       if ( ch == ASCII_ESC || ch == ASCII_ENTER)
  1141.          break
  1142.  
  1143.       if ( ch == ASCII_BACKSPACE )
  1144.       {
  1145.          #
  1146.          # remove the last char in the search string and
  1147.          # restore the previous position
  1148.          #
  1149.          searchi_pattern = substr( searchi_pattern, 0, length( searchi_pattern ) - 1 )
  1150.          if ( level )
  1151.          {
  1152.             restore_position( TRUE )
  1153.             level--
  1154.          }
  1155.       }
  1156.       else
  1157.       {
  1158.          #
  1159.          # It is a normal ascii character.
  1160.          # Let's search for the new pattern.  If we find it,
  1161.          # save the previous position and advance to the
  1162.          # newly found string.
  1163.          #
  1164.          char = chr( ch )
  1165.          save_position()
  1166.          message( "Incremental-Search for: %s\137",
  1167.                   quote_printf_string( searchi_pattern char ))
  1168.  
  1169.          sf = and( sf, not( SEARCH_BACKWARD ) )
  1170.  
  1171.          sf = or(sf, SEARCH_MAXIMAL_MATCH+SEARCH_BACKWARD )
  1172.  
  1173. #         if ( search( searchi_pattern char, SEARCH_MAXIMAL_MATCH+SEARCH_FORWARD ))
  1174.          if ( search( searchi_pattern char, sf ))
  1175.          {
  1176.             searchi_pattern = searchi_pattern char
  1177.             level++
  1178.          }
  1179.          else
  1180.          {
  1181.             beep()
  1182.             restore_position( FALSE )
  1183.          }
  1184.       }
  1185.       display_update()
  1186.    }
  1187.  
  1188.    optional_function( "restore_status_bar" )
  1189.    message( "Incremental-search done." )
  1190.  
  1191.    while ( level-- )
  1192.    {
  1193.       restore_position( FALSE )
  1194.    }
  1195.  
  1196.    if (searchi_pattern)
  1197.    {
  1198.       # must set global 'search_pattern' so that future calls to prompt_history
  1199.       # from search_forward display last searchi_pattern.  This is required
  1200.       # since this function calls search() instead of search_forward().
  1201.       search_pattern = searchi_pattern
  1202.       add_prompt_history("SEARCH", searchi_pattern);
  1203.    }
  1204.  
  1205.    reentrant_search_i = 0
  1206. }
  1207.  
  1208.  
  1209.  
  1210. #----------- Supporting search and replace functions ------------#
  1211.  
  1212. global function toggle_search_flags(mask, value)
  1213. {
  1214.    local msg, suffix = "disabled.";
  1215.  
  1216.    #  If no value supplied, toggle the old value;
  1217.    if(argcount() < 2)
  1218.       value = xor(mask, and(search_flags, mask));
  1219.  
  1220.    if ( value )
  1221.    {
  1222.       search_flags = or( search_flags, mask )
  1223.       suffix = "enabled.";
  1224.    }
  1225.    else
  1226.       search_flags = and( search_flags, not(mask) )
  1227.  
  1228.    if(mask == SEARCH_ADVANCE)
  1229.       msg = "Search advance " suffix;
  1230.    else if(mask == SEARCH_BACKWARD)
  1231.       msg = "Search backward " suffix;
  1232.    else if(mask == SEARCH_CASE)
  1233.       msg = "Search case sensitive " suffix;
  1234.    else if(mask == SEARCH_CENTER_CURSOR)
  1235.       msg = "Search centering results " suffix;
  1236.    else if(mask == SEARCH_FORWARD)
  1237.       msg = "Search forward " suffix;
  1238.    else if(mask == SEARCH_MAXIMAL_MATCH)
  1239.       msg = "Search maximal match " suffix;
  1240.    else if(mask == SEARCH_REGEX)
  1241.       msg = "Search regular expressions " suffix;
  1242.    else if(mask == SEARCH_WHOLE_WORD)
  1243.       msg = "Search matching whole word " suffix;
  1244.    else if(mask == SEARCH_WRAPS)
  1245.       msg = "Search wrapping " suffix;
  1246.    else
  1247.       msg = "Search mode " suffix;
  1248.  
  1249.    message(msg);
  1250.  
  1251.    return value;
  1252. }
  1253.  
  1254. #
  1255. # toggle the case sensitivity setting in the "search_flags" variable
  1256. # and display a message indicating the new default case sensitivity value.
  1257. #
  1258. #global function toggle_search_case( on )                        #PUBLIC #INT
  1259. #{
  1260. #   if ( argcount() < 1 )
  1261. #      on = !and( search_flags, SEARCH_CASE )
  1262. #   else
  1263. #      on = 0+on
  1264. #
  1265. #   #
  1266. #   # toggle the setting
  1267. #   #
  1268. #   if ( on )
  1269. #      search_flags = or( search_flags, SEARCH_CASE )
  1270. #   else
  1271. #      search_flags = and( search_flags, not( SEARCH_CASE ))
  1272. #
  1273. #   message( "Case sensitive search %s.", on ? "on" : "off" )
  1274. #   return on
  1275. #}
  1276. #
  1277. #
  1278. ##
  1279. ## toggle the global search setting in the "search_flags" variable
  1280. ## and display a message indicating the new default global value.
  1281. ##
  1282. #global function toggle_search_global( on )                        #PUBLIC #INT
  1283. #{
  1284. #   if ( argcount() < 1 )
  1285. #      on = !and( search_flags, SEARCH_GLOBAL )
  1286. #   else
  1287. #      on = 0+on
  1288. #
  1289. #   #
  1290. #   # toggle the setting
  1291. #   #
  1292. #   if ( on )
  1293. #      search_flags = or( search_flags, SEARCH_GLOBAL )
  1294. #   else
  1295. #      search_flags = and( search_flags, not( SEARCH_GLOBAL ))
  1296. #
  1297. #   message( "Global search %s.", on ? "on" : "off" )
  1298. #   return on
  1299. #}
  1300. #
  1301. ##
  1302. ## toggle the all-files search setting in the "search_flags" variable
  1303. ## and display a message indicating the new default all-files value.
  1304. ##
  1305. #global function toggle_search_all_buffers( on )                   #PUBLIC #INT
  1306. #{
  1307. #   if ( argcount() < 1 )
  1308. #      on = !and( search_flags, SEARCH_ALL_BUFFERS )
  1309. #   else
  1310. #      on = 0+on
  1311. #
  1312. #   #
  1313. #   # toggle the setting
  1314. #   #
  1315. #   if ( on )
  1316. #      search_flags = or( search_flags, SEARCH_ALL_BUFFERS )
  1317. #   else
  1318. #      search_flags = and( search_flags, not( SEARCH_ALL_BUFFERS ))
  1319. #
  1320. #   message( "All-Files search %s.", on ? "on" : "off" )
  1321. #   return on
  1322. #}
  1323. #
  1324. ##
  1325. ## toggle the center search setting in the "search_flags" variable
  1326. ## and display a message indicating the new default center value.
  1327. ##
  1328. #global function toggle_search_center( on )                        #PUBLIC #INT
  1329. #{
  1330. #   if ( argcount() < 1 )
  1331. #      on = !and( search_flags, SEARCH_CENTER_CURSOR )
  1332. #   else
  1333. #      on = 0+on
  1334. #
  1335. #   #
  1336. #   # toggle the setting
  1337. #   #
  1338. #   if ( on )
  1339. #      search_flags = or( search_flags, SEARCH_CENTER_CURSOR )
  1340. #   else
  1341. #      search_flags = and( search_flags, not( SEARCH_CENTER_CURSOR ))
  1342. #
  1343. #   message( "Centering search is %s.", on ? "on" : "off" )
  1344. #   return on
  1345. #}
  1346. #
  1347. ##
  1348. ## toggle the regular expression setting in the "search_flags" variable
  1349. ## and display a message indicating the new default regex value.
  1350. ##
  1351. #global function toggle_search_regex( on )                       #PUBLIC #INT
  1352. #{
  1353. #   if ( argcount() < 1 )
  1354. #      on = !and( search_flags, SEARCH_REGEX )
  1355. #   else
  1356. #      on = 0+on
  1357. #
  1358. #   #
  1359. #   # toggle the setting
  1360. #   #
  1361. #   if ( on )
  1362. #      search_flags = or( search_flags, SEARCH_REGEX )
  1363. #   else
  1364. #      search_flags = and( search_flags, not( SEARCH_REGEX ))
  1365. #
  1366. #   message( "Regular expression search %s.", on ? "on" : "off" )
  1367. #   return on
  1368. #}
  1369. #
  1370. ##
  1371. ## toggle the state of the SEARCH_BLOCK flag in search_flags
  1372. ##
  1373. #global function toggle_search_block( on )                       #PUBLIC #INT
  1374. #{
  1375. #   if( argcount() < 1 )
  1376. #      on = !and( search_flags, SEARCH_BLOCK )
  1377. #   else
  1378. #      on = 0+on
  1379. #
  1380. #   #
  1381. #   # toggle the setting
  1382. #   #
  1383. #   if ( on )
  1384. #      search_flags = or( search_flags, SEARCH_BLOCK )
  1385. #   else
  1386. #      search_flags = and( search_flags, not( SEARCH_BLOCK ))
  1387. #
  1388. #   message( "Block searching %s.", on ? "on" : "off" )
  1389. #   return on
  1390. #}
  1391. #
  1392. ##
  1393. ## toggle the state of the SEARCH_WHOLE_WORD flag in search_flags
  1394. ##
  1395. #global function toggle_search_word( on )                       #PUBLIC #INT
  1396. #{
  1397. #   if( argcount() < 1 )
  1398. #      on = !and( search_flags, SEARCH_WHOLE_WORD )
  1399. #   else
  1400. #      on = 0+on
  1401. #
  1402. #   #
  1403. #   # toggle the setting
  1404. #   #
  1405. #   if ( on )
  1406. #      search_flags = or( search_flags, SEARCH_WHOLE_WORD )
  1407. #   else
  1408. #      search_flags = and( search_flags, not( SEARCH_WHOLE_WORD ))
  1409. #
  1410. #   message( "Whole word searching is %s.", on ? "on" : "off" )
  1411. #   return on
  1412. #}
  1413. #
  1414. ##
  1415. ## toggle the search forward setting in the "search_flags" variable
  1416. ## and display a message indicating the new default forward value.
  1417. ##
  1418. #global function toggle_search_forward( on )                     #PUBLIC #INT
  1419. #{
  1420. #   if ( argcount() < 1 )
  1421. #      on = !and( search_flags, SEARCH_FORWARD )
  1422. #   else
  1423. #      on = 0+on
  1424. #
  1425. #   #
  1426. #   # toggle the setting
  1427. #   #
  1428. #   if ( on )
  1429. #      search_flags = or( search_flags, SEARCH_FORWARD )
  1430. #   else
  1431. #      search_flags = and( search_flags, not( SEARCH_FORWARD ))
  1432. #
  1433. #   message( "%s searching is on.", on ? "Forward" : "Backward" )
  1434. #   return on
  1435. #}
  1436. #
  1437. ##
  1438. ## toggle the search for a maximum match setting in the "search_flags" variable
  1439. ## and display a message indicating the new default max match value.
  1440. ##
  1441. #global function toggle_search_max_match( on )                     #PUBLIC #INT
  1442. #{
  1443. #   if ( argcount() < 1 )
  1444. #      on = !and( search_flags, SEARCH_MAXIMAL_MATCH )
  1445. #   else
  1446. #      on = 0+on
  1447. #
  1448. #   #
  1449. #   # toggle the setting
  1450. #   #
  1451. #   if ( on )
  1452. #      search_flags = or( search_flags, SEARCH_MAXIMAL_MATCH )
  1453. #   else
  1454. #      search_flags = and( search_flags, not( SEARCH_MAXIMAL_MATCH ))
  1455. #
  1456. #   message( "Maximum match searching is %s.", on ? "on" : "off" )
  1457. #   return on
  1458. #}
  1459. #
  1460. ##
  1461. ## toggle the search wraps setting in the "search_flags" variable
  1462. ## and display a message indicating the new default wrap value.
  1463. ##
  1464. #global function toggle_search_wrap( on )                     #PUBLIC #INT
  1465. #{
  1466. #   if ( argcount() < 1 )
  1467. #      on = !and( search_flags, SEARCH_WRAPS )
  1468. #   else
  1469. #      on = 0+on
  1470. #
  1471. #   #
  1472. #   # toggle the setting
  1473. #   #
  1474. #   if ( on )
  1475. #      search_flags = or( search_flags, SEARCH_WRAPS )
  1476. #   else
  1477. #      search_flags = and( search_flags, not( SEARCH_WRAPS ))
  1478. #
  1479. #   message( "Wrap searching is %s.", on ? "on" : "off" )
  1480. #   return on
  1481. #}
  1482. #
  1483. ##
  1484. ## toggle the search advance setting in the "search_flags" variable
  1485. ## and display a message indicating the new default advance value.
  1486. ##
  1487. #global function toggle_search_advance( on )                     #PUBLIC #INT
  1488. #{
  1489. #   if ( argcount() < 1 )
  1490. #      on = !and( search_flags, SEARCH_ADVANCE )
  1491. #   else
  1492. #      on = 0+on
  1493. #
  1494. #   #
  1495. #   # toggle the setting
  1496. #   #
  1497. #   if ( on )
  1498. #      search_flags = or( search_flags, SEARCH_ADVANCE )
  1499. #   else
  1500. #      search_flags = and( search_flags, not( SEARCH_ADVANCE ))
  1501. #
  1502. #   message( "Advance search is %s.", on ? "on" : "off" )
  1503. #   return on
  1504. #}
  1505. #
  1506. ##
  1507. ## toggle the search once per line setting in the "search_flags" variable
  1508. ## and display a message indicating the new default once per line value.
  1509. ##
  1510. #global function toggle_search_once( on )                     #PUBLIC #INT
  1511. #{
  1512. #   if ( argcount() < 1 )
  1513. #      on = !and( search_flags, SEARCH_ONCE_PER_LINE )
  1514. #   else
  1515. #      on = 0+on
  1516. #
  1517. #   #
  1518. #   # toggle the setting
  1519. #   #
  1520. #   if ( on )
  1521. #      search_flags = or( search_flags, SEARCH_ONCE_PER_LINE )
  1522. #   else
  1523. #      search_flags = and( search_flags, not( SEARCH_ONCE_PER_LINE ))
  1524. #
  1525. #   message( "Once per line searching is %s.", on ? "on" : "off" )
  1526. #   return on
  1527. #}
  1528. #
  1529. ##
  1530. ## toggle the search highlight setting in the "search_flags" variable
  1531. ## and display a message indicating the new default highlight value.
  1532. ##
  1533. #global function toggle_search_highlight( on )                     #PUBLIC #INT
  1534. #{
  1535. #   if ( argcount() < 1 )
  1536. #      on = !and( search_flags, SEARCH_HIGHLIGHT )
  1537. #   else
  1538. #      on = 0+on
  1539. #
  1540. #   #
  1541. #   # toggle the setting
  1542. #   #
  1543. #   if ( on )
  1544. #      search_flags = or( search_flags, SEARCH_HIGHLIGHT )
  1545. #   else
  1546. #      search_flags = and( search_flags, not( SEARCH_HIGHLIGHT ))
  1547. #
  1548. #   message( "Highlight search is %s.", on ? "on" : "off" )
  1549. #   return on
  1550. #}
  1551.  
  1552. global function quote_printf_string( str )                      #PUBLIC #STR
  1553. {
  1554.    local   newstr = str
  1555.    gsub( "%", "%%", newstr )
  1556.    return newstr
  1557. }
  1558.  
  1559. #------------------ Wsearch functions --------------------#
  1560.  
  1561. #
  1562. # prompt for the search pattern and provide command history
  1563. #
  1564. local function replace_prompt( str )
  1565. {
  1566.    return prompt_history( "REPLACE", " Replace " str " with: ", replace_pattern, 1, 1, "replace_prompt" )
  1567. }
  1568.  
  1569. # generic function that does either search or replace accross buffers
  1570. global function wsearch_replace( srch, replacement, dlgbox )
  1571. {
  1572.    local   priorBuffer = current_buffer
  1573.    local   sentinel
  1574.    local   sf
  1575.    local   found
  1576.    local   n
  1577.    local   orig_search_count = search_count ? search_count : 1
  1578.    local   forward
  1579.  
  1580.    local   replacing = ( argcount() > 1 && replacement ) ? TRUE : FALSE
  1581.  
  1582.    sf      = search_flags
  1583.    sf      = and( sf, not(SEARCH_WRAPS) )
  1584.    forward = and(sf, SEARCH_FORWARD);
  1585.  
  1586.    #
  1587.    # search the remainder of the current buffer
  1588.    #
  1589.    save_position()
  1590.    n = orig_search_count
  1591.  
  1592.    if ( replacing )
  1593.       found = replace( srch, replacement, sf)
  1594.    else
  1595.       found = search( srch, sf)
  1596.  
  1597.    if ( found >= n )
  1598.    {
  1599.       restore_position( 0 )
  1600.       if ( and( search_flags, SEARCH_CENTER_CURSOR ))
  1601.          center_cursor()
  1602.       highlightSearch()
  1603.       return orig_search_count        # found
  1604.    }
  1605.    restore_position( 1 )
  1606.  
  1607.    #
  1608.    # search the other buffers
  1609.    #
  1610.  
  1611.    forward ? (sentinel = next_buffer("", 0, 1)) : (sentinel = prev_buffer("", 0, 1));
  1612.  
  1613.    do
  1614.    {
  1615.       if ( current_buffer == priorBuffer )
  1616.          break
  1617.  
  1618.       if ( replacing )
  1619.          message( "Replacing in %s...", buffer_filename )
  1620.       else
  1621.          message( "Searching %s...", buffer_filename )
  1622.  
  1623.       save_position()
  1624.  
  1625.       forward ? goto_buffer_top() : goto_buffer_bottom();
  1626.  
  1627.       n -= found
  1628.       search_count = n
  1629.  
  1630.       if ( replacing )
  1631.          found = replace( srch, replacement, sf )
  1632.       else
  1633.          found = search( srch, sf )
  1634.  
  1635.       if ( found >= n )
  1636.       {
  1637.          restore_position( 0 )
  1638.          save_position()
  1639.          message( "" )
  1640.          create_buf_and_win(buffer_filename, dlgbox)
  1641.          restore_position( 1 )
  1642.          if ( and( search_flags, SEARCH_CENTER_CURSOR ))
  1643.             center_cursor()
  1644.          highlightSearch()
  1645.          return orig_search_count        # found
  1646.       }
  1647.       restore_position( 1 )
  1648.       
  1649.       forward ? next_buffer("", 0, 1) : prev_buffer("", 0, 1);
  1650.    }
  1651.    while ( current_buffer != sentinel )
  1652.  
  1653.    #
  1654.    # search the current buffer above the current cursor position
  1655.    #
  1656.    current_buffer = priorBuffer
  1657.  
  1658.    if ( replacing )
  1659.       message( "Replacing in %s...", buffer_filename )
  1660.    else
  1661.       message( "Searching %s...", buffer_filename )
  1662.  
  1663.    save_position()
  1664.    begin_selection( INCLUSIVE_SELECTION )
  1665.  
  1666.    forward ? goto_buffer_top() : goto_buffer_bottom();
  1667.  
  1668.    n -= found
  1669.    search_count = n
  1670.  
  1671.    if ( replacing )
  1672.       found = replace( srch, replacement, or( sf, SEARCH_BLOCK ))
  1673.    else
  1674.       found = search( srch, or( sf, SEARCH_BLOCK ))
  1675.  
  1676.    remove_selection()
  1677.    if ( found >= n )
  1678.    {
  1679.       restore_position( 0 )
  1680.       save_position()
  1681.       message( "" )
  1682.       create_buf_and_win(buffer_filename, dlgbox)
  1683.       restore_position( 1 )
  1684.       if ( and( search_flags, SEARCH_CENTER_CURSOR ))
  1685.          center_cursor()
  1686.       highlightSearch()
  1687.       return orig_search_count        # found
  1688.    }
  1689.  
  1690.    restore_position( 1 )
  1691.  
  1692.    # if we're searching globaly, then we know 
  1693.    # we'll get to the "no more found" case
  1694.    if ( !and(search_flags, SEARCH_GLOBAL) )
  1695.       warning("Pattern not found")
  1696.  
  1697.    return orig_search_count - n + found    # not found
  1698. }
  1699.  
  1700. ## wsearch()            search all buffers for a string
  1701. ## wsearch_again()      repeat prior wsearch in all buffers for a string
  1702. #
  1703. global function wsearch( srch, dlgbox )                     #PUBLIC #INT
  1704. {
  1705.    local sf = search_flags
  1706.    local rc
  1707.  
  1708.    # if no search argument given, prompt for one
  1709.    if ( !srch )
  1710.    {
  1711.       srch = search_prompt()
  1712.       if ( srch == "" )
  1713.          return
  1714.    }
  1715.  
  1716.    search_pattern = srch
  1717.  
  1718.    sf = or( sf, SEARCH_ALL_BUFFERS )
  1719.    rc = wsearch_replace( srch, 0, dlgbox )
  1720.  
  1721.    search_flags = sf
  1722.    return rc
  1723. }
  1724.  
  1725. global function wsearch_again( srch, dlgbox )                 #PUBLIC #INT
  1726. {
  1727.    search_flags = or( search_flags, SEARCH_ADVANCE )
  1728.  
  1729.    if ( !srch )
  1730.       {
  1731.       if ( search_pattern )
  1732.          srch = search_pattern
  1733.       else
  1734.          return 0
  1735.  
  1736.       srch = search_pattern
  1737.       }
  1738.  
  1739.    return wsearch( srch, dlgbox )
  1740. }
  1741.  
  1742. #------------------ Wreplace functions --------------------#
  1743.  
  1744. global function wreplace( srch, replacement )
  1745. {
  1746.    # if no search argument given, prompt for one
  1747.    if ( !srch )
  1748.    {
  1749.       srch = search_prompt()
  1750.       if ( srch == "" )
  1751.          return
  1752.    }
  1753.  
  1754.    # if no replacement argument given, prompt for one
  1755.    if ( argcount() < 2 )
  1756.    {
  1757.       replacement = replace_prompt( srch )
  1758.       if ( !replacement && ( current_key == KEYCODE_ESC ))
  1759.          return
  1760.    }
  1761.  
  1762.    return wsearch_replace( srch, replacement )
  1763. }
  1764.  
  1765. global function wreplace_again( srch, replacement )
  1766. {
  1767.    search_flags = or(search_flags, SEARCH_ADVANCE)           
  1768.  
  1769.    return wreplace( srch, replacement )
  1770. }
  1771.  
  1772. # freplace functions
  1773.  
  1774. global function background_freplace( srch, replacement, arrayOfFiles )
  1775. {
  1776.    local i
  1777.    local fn
  1778.    local fileToOpen
  1779.    local orig_buffer = current_buffer
  1780.    local sys_buffer
  1781.    local title
  1782.    local dhTemp
  1783.    local matches
  1784.    local total_matches
  1785.    local mode
  1786.  
  1787.    title = sprintf( "Replace %s with %s", srch, replacement )
  1788.  
  1789.    dhTemp = create_list_dialog( title, editor_helpfile, "grep_list_callback" )
  1790.  
  1791.    begin_list_dialog( dhTemp )
  1792.  
  1793.    for ( i in arrayOfFiles )
  1794.    {
  1795.       fileToOpen = arrayOfFiles[i]
  1796.  
  1797.       if ( (fn = findfirst( fileToOpen )) )
  1798.       {
  1799.          do
  1800.          {
  1801.             fn = tolower( path_path( fileToOpen ) fn )
  1802.  
  1803.             set_dialog_window( dhTemp, DWC_STATUSBARTEXT, "Replacing in " fn "..." )
  1804.             
  1805.             # open the buffer as a system buffer
  1806.             mode = filemode( fn )
  1807.             if ( mode == -1 )
  1808.                continue
  1809.  
  1810.             if ( and(mode, _READ_ONLY) )
  1811.                {
  1812.                add_item_to_list( dhTemp, fn ": READ-ONLY FILE, NO REPLACEMENTS PERFORMED" )
  1813.                continue
  1814.                }
  1815.  
  1816.             sys_buffer = current_buffer = \
  1817.                create_buffer(fn, fn, BUFFER_SYSTEM + BUFFER_NO_UNDO )
  1818.  
  1819.             search_count = MAX_SEARCH
  1820.             matches = replace( srch, replacement, search_flags )
  1821.             add_item_to_list( dhTemp, fn ": " matches " occurrences replaced", fn )
  1822.             total_matches = total_matches + matches
  1823.             write_buffer()
  1824.             
  1825.             delete_buffer()
  1826.  
  1827.             sys_buffer = 0
  1828.             
  1829.             current_buffer = orig_buffer
  1830.          } while ( (fn = findnext()) )
  1831.       }
  1832.  
  1833.       set_dialog_window( dhTemp, DWC_STATUSBARTEXT, total_matches " occurrences replaced" )
  1834.  
  1835.       # parse the drive:directory from the filename and store in
  1836.       # last path.
  1837.       #
  1838.       lastFReplacePath = path_path(fileToOpen) "*.*"
  1839.    }
  1840.  
  1841.    return total_matches
  1842. }
  1843.  
  1844. local lastFReplacePath
  1845. global function freplace( srch, replacement, listOfFiles, recursive )
  1846. {
  1847.    local arrayOfFiles[]
  1848.    local ret_val
  1849.  
  1850.    # if no search argument given, prompt for one
  1851.    if ( !srch )
  1852.    {
  1853.       srch = search_prompt()
  1854.       if ( srch == "" )
  1855.          return
  1856.    }
  1857.  
  1858.    # if no replacement argument given, prompt for one
  1859.    if ( argcount() < 2 )
  1860.    {
  1861.       replacement = replace_prompt( srch )
  1862.       if ( !replacement && ( current_key == KEYCODE_ESC ))
  1863.          return
  1864.    }
  1865.  
  1866.    if ( !listOfFiles )
  1867.       listOfFiles = open_dialog( lastFReplacePath, "Select files to freplace" )
  1868.  
  1869.    if ( listOfFiles )
  1870.    {
  1871.       add_prompt_history( "SEARCH", srch )
  1872.       add_prompt_history( "REPLACE", replacement )
  1873.       add_prompt_history( "SRCHFILES", listOfFiles )
  1874.  
  1875.       if ( tolower(confirm("Changes will not be undoable, continue?[yn] ", "yYnN")) != "y" )
  1876.          return
  1877.    
  1878.       if ( recursive )
  1879.          arrayOfFiles = get_recursive_dir_list( listOfFiles )
  1880.       else
  1881.          split( listOfFiles, arrayOfFiles, ";" )
  1882.    
  1883.       process_background( DISABLE_FOREGROUND )
  1884.       ret_val = background_freplace( srch, replacement, arrayOfFiles )
  1885.       process_background( END_BACKGROUND )
  1886.    }
  1887.  
  1888.    return ret_val
  1889. }
  1890.