let rec search =
  let forward = ref true in
  fun (fsearch_buffer : search_buffer_function)
    mes ?(changed=false) _forward (v: sourceview) args ->
      forward := _forward;
    let fixed wrapped = Printf.sprintf "%s%s%s: "
      (if wrapped then "[wrapped] " else "")
        mes
        (if !forward then "" else " backward")
    in
    let mb = v#minibuffer in
    if mb#active then
      (
       let s_utf8 = mb#get_user_text in
       match s_utf8 with
         "" ->
           begin
             match !prev_search with
               None -> ()
             | Some s -> mb#set_user_text s
           end
       | _ ->
           (*           prerr_endline ("search "^(Ed_misc.of_utf8 s_utf8));*)
           let start =
             if changed then
               let (start, stop) = v#file#buffer#selection_bounds in
               Some (if !forward then start else stop)
             else
               None
           in
           match fsearch_buffer !forward v#file#buffer ?start s_utf8 with
             (wrapped, None->
               mb#set_text ~fixed: (fixed wrapped) s_utf8
           | (wrapped, Some (start, stop)) ->
               (*
                  prerr_endline (Printf.sprintf "found start=%d,%d" start#line start#line_offset);
                  prerr_endline (Printf.sprintf "and stop=%d,%d" stop#line stop#line_offset);
               *)

               let loc =
                 let it = if !forward then stop else start in
                 location_of_iter it
               in
               v#set_location loc;
               if !forward then
                 v#file#buffer#select_range stop start
               else
                 v#file#buffer#select_range start stop;
               ignore(v#source_view#scroll_to_iter start);
               ignore(v#source_view#scroll_to_iter stop);
               mb#set_text ~fixed: (fixed wrapped) s_utf8
      )
    else
      (
       let on_changed () =
         (* do not do anything if there is nothing to search
            or the searched string has not changed, to prevent
            from moving to next search when changing the fixed text
            of the minibuffer *)

         match mb#get_user_text with
           "" -> ()
         | s ->
             if !prev_search = Some s then
               ()
             else
               (
                prev_search := Some s;
                search fsearch_buffer mes ~changed: true !forward  v args
               )
       in
       mb#clear;
       mb#set_text ~fixed: (fixed false"";
       mb#set_on_text_changed on_changed;

       mb#set_more_key_bindings
         (keep_key_bindings_from_view v
          [ factory_name^"_search" ;
            factory_name^"_search_backward" ;
            factory_name^"_search_re" ;
            factory_name^"_search_re_backward" ;
          ]
         );
       mb#set_active true
      )