[nemiver] Move core asm handling lower in the stack.



commit 19a94bbf0bac34009337bc4287a2efbc49d3929c
Author: Dodji Seketeli <dodji redhat com>
Date:   Sun Aug 29 00:09:17 2010 +0200

    Move core asm handling lower in the stack.
    
    	* src/dbgengine/nmv-asm-utils.h: Move content from here to ...
    	* common/nmv-asm-utils.h: ... here.
    	* common/nmv-asm-utils.cc: New file.
    	* src/common/Makefile.am: Add nmv-asm-utils.[h|cc] to the build
    	system.
    	* src/dbgengine/Makefile.am: Remove nmv-asm-utils.[h|cc] from the
    	build system.
    	* src/dbgengine/nmv-gdbmi-parser.cc: Don't include nmv-asm-utils.h
    	anymore.
    	* tests/test-disassemble.cc: Include common/nmv-asm-utils.h
    	instead of just nmv-asm-utils.h.
    	* tests/test-gdbmi.cc: Likewise.
    	* src/common/nmv-env.h (find_file, find_file_absolute_or_relative)
    	(read_file_line): Declare ...
    	* src/common/nmv-env.cc (find_file, find_file_absolute_or_relative)
    	(read_file_line): ... new functions.
    	* src/common/nmv-str-utils.h (is_buffer_valid_utf8)
    	(ensure_buffer_is_in_utf8): Declare ...
    	* src/common/nmv-str-utils.cc (is_buffer_valid_utf8)
    	(ensure_buffer_is_in_utf8): ... new functions.
    	* src/common/nmv-ustring.h (UString::split_to_list): Declare new function.
    	* src/common/nmv-ustring.cc (split_base): New function template.
    	(UString::split): Use the new splite_base function template.
    	(UString::split_to_list): Define new function. Uses splite_base.
    	* src/uicommon/nmv-dialog.[h|cc]: Moved here from
    	src/persp/dbgperspective/nmv-dialog.[h|cc].
    	(Dialog::Priv::Priv): Support loading glade file from the "global"
    	glade install dir of Nemiver as well as from the plugins glade
    	install dir.
    	* glade/locatefiledialog.glade: Moved here from
    	src/persp/dbgperspective/glade/locatefiledialog.glade.
    	* glade/Makefile.am: Add locatefiledialog.glade file to build system.
    	* src/uicommon/nmv-locate-file-dialog.[h|cc]: Moved here from
    	src/persp/dbgperspective/nmv-locate-file-dialog.[h|cc].
    	* src/uicommon/Makefile.am: Add nmv-dialog.[h|cc] and
    	nmv-locate-file-dialog.cc to the build system.
    	* src/uicommon/nmv-ui-utils.cc|h (ask_user_to_select_file)
    	(find_absolute_path_or_ask_user, find_file_and_read_line): New
    	functions. Moved here from DBGPerspective and hacked to fit in here.
    	* src/uicommon/nmv-source-editor.cc|h
    	(SourceEditor::get_file_mime_type)
    	(SourceEditor::setup_buffer_mime_and_lang)
    	(SourceEditor::create_source_buffer)
    	(SourceEditor::load_file, SourceEditor::add_asm)
    	(SourceEditor::load_asm): New functions. Mostly the result of
    	moving their counterparts from DBGPerspective to here. They got
    	also hacked to use new support functions from the common::env and
    	ui_utils namespace.
    	* src/persp/dbgperspective/glade/locatefiledialog.glade: Moved to
    	glade/locatefiledialog.glade.
    	* src/persp/dbgperspective/glade/Makefile.am: Remove
    	locatefiledialog.glade from the build system here.
    	* src/persp/dbgperspective/Makefile.am: Remove nmv-dialog.[cc|h] and
    	nmv-locate-file-dialog.[h|cc] from the build system here.
    	* src/persp/dbgperspective/nmv-dbg-perspective.h (load_asm): Remove.
    	* src/persp/dbgperspective/nmv-dbg-perspective.cc (log_asm_insns)
    	(get_file_mime_type, setup_buffer_mime_and_lang)
    	(create_source_buffer, load_file, load_asm, write_asm_instr)
    	(write_asm_instr, add_asm, read_file_line): Remove these
    	functions. Actually they got moved to lower level layers in the
    	stack, i.e, mostly into nmv-source-editor.cc, nmv-ui-utils.cc, and
    	nmv-env.cc.
    	(get_global_search_paths): get_source_dirs got renamed into this.
    	(DBGPerspective::Priv::session_search_paths): Renamed
    	DBGPerspective::Priv::search_paths into this.
    	(DBGPerspective::Priv::global_search_paths): Renamed
    	DBGPerspective::Priv::source_dirs into this.
    	(Priv::get_supported_encodings): New function.
    	(Priv::load_file): New function. Use get_supported_encodings and
    	the new SourceEditor::load_file.
    	(find_absolute_path): Use the new
    	common::env::find_file_absolute_or_relative.
    	(find_absolute_path_or_ask_user): Use the new
    	ui_utils::find_absolute_path_or_ask_user.
    	(get_or_append_asm_source_editor): Use the new
    	SourceEditor::create_source_buffer.
    	(find_file_in_source_dirs): Use the new common::env::find_file.
    	(open_file_real): Use the Priv::load_file, instead of the new
    	defunct load_file.
    	(open_asm): Use the new SourceEditor::load_asm instead of the
    	defunct load_asm.
    	(switch_to_asm): use the new
    	SourceEditor::setup_buffer_mime_and_lang and SourceEditor::load_asm.
    	(switch_to_source_code): Use the new
    	SourceEditor::get_file_mime_type,
    	SourceEditor::setup_buffer_mime_and_lang and Priv::load_file.
    	(reload_file): Use the Priv::load_file.
    	(ask_user_to_select_file): Use the new
    	ui_utils::ask_user_to_select_file.

 glade/Makefile.am                                  |    2 +-
 .../glade => glade}/locatefiledialog.glade         |    0
 src/common/Makefile.am                             |    2 +
 src/common/nmv-asm-instr.h                         |    6 +-
 src/common/nmv-asm-utils.h                         |  147 ++++
 src/common/nmv-env.cc                              |  155 ++++
 src/common/nmv-env.h                               |   20 +
 src/common/nmv-str-utils.cc                        |   91 +++
 src/common/nmv-str-utils.h                         |    7 +
 src/common/nmv-ustring.cc                          |   25 +-
 src/common/nmv-ustring.h                           |    1 +
 src/dbgengine/Makefile.am                          |    2 +-
 src/dbgengine/nmv-asm-utils.h                      |   91 ---
 src/dbgengine/nmv-gdbmi-parser.cc                  |    1 -
 src/dbgengine/nmv-i-debugger.h                     |    4 +-
 src/persp/dbgperspective/Makefile.am               |    4 -
 src/persp/dbgperspective/glade/Makefile.am         |    1 -
 src/persp/dbgperspective/nmv-dbg-perspective.cc    |  777 ++------------------
 src/persp/dbgperspective/nmv-dbg-perspective.h     |    4 -
 src/uicommon/Makefile.am                           |    4 +
 .../dbgperspective => uicommon}/nmv-dialog.cc      |   21 +-
 .../dbgperspective => uicommon}/nmv-dialog.h       |    0
 .../nmv-locate-file-dialog.cc                      |    0
 .../nmv-locate-file-dialog.h                       |    0
 src/uicommon/nmv-source-editor.cc                  |  312 ++++++++-
 src/uicommon/nmv-source-editor.h                   |   38 +
 src/uicommon/nmv-ui-utils.cc                       |  113 +++-
 src/uicommon/nmv-ui-utils.h                        |   23 +
 tests/test-disassemble.cc                          |    2 +-
 tests/test-gdbmi.cc                                |    2 +-
 30 files changed, 1032 insertions(+), 823 deletions(-)
---
diff --git a/glade/Makefile.am b/glade/Makefile.am
index 58d91ef..9c9bd35 100644
--- a/glade/Makefile.am
+++ b/glade/Makefile.am
@@ -1,4 +1,4 @@
-gladefiles = workbench.glade
+gladefiles = workbench.glade locatefiledialog.glade
 
 gladedir = $(datadir)/@PACKAGE@/glade
 glade_DATA = $(gladefiles)
diff --git a/src/persp/dbgperspective/glade/locatefiledialog.glade b/glade/locatefiledialog.glade
similarity index 100%
rename from src/persp/dbgperspective/glade/locatefiledialog.glade
rename to glade/locatefiledialog.glade
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 525d97e..a238df5 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -7,6 +7,7 @@ nmv-namespace.h \
 nmv-ustring.h \
 nmv-address.h \
 nmv-asm-instr.h \
+nmv-asm-utils.h \
 nmv-range.h \
 nmv-str-utils.h \
 nmv-libxml-utils.h \
@@ -43,6 +44,7 @@ nmv-proc-mgr.h
 libnemivercommon_la_SOURCES= $(headers) \
 nmv-ustring.cc \
 nmv-address.cc \
+nmv-asm-utils.cc \
 nmv-str-utils.cc \
 nmv-object.cc \
 nmv-libxml-utils.cc \
diff --git a/src/common/nmv-asm-instr.h b/src/common/nmv-asm-instr.h
index 356ae88..1cdd71f 100644
--- a/src/common/nmv-asm-instr.h
+++ b/src/common/nmv-asm-instr.h
@@ -24,10 +24,12 @@
  */
 #ifndef __NEMIVER_ASM_INSTR_H__
 #define __NEMIVER_ASM_INSTR_H__
+
+#include <list>
+#include <boost/variant.hpp>
 #include "nmv-namespace.h"
 #include "nmv-api-macros.h"
-#include <boost/variant.hpp>
-#include <list>
+#include "nmv-exception.h"
 
 NEMIVER_BEGIN_NAMESPACE (nemiver)
 NEMIVER_BEGIN_NAMESPACE (common)
diff --git a/src/common/nmv-asm-utils.h b/src/common/nmv-asm-utils.h
new file mode 100644
index 0000000..08454a5
--- /dev/null
+++ b/src/common/nmv-asm-utils.h
@@ -0,0 +1,147 @@
+// Author: Dodji Seketeli
+/*
+ *This file is part of the Nemiver project
+ *
+ *Nemiver 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; either version 2,
+ *or (at your option) any later version.
+ *
+ *Nemiver 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.
+ *
+ *You should have received a copy of the
+ *GNU General Public License along with Nemiver;
+ *see the file COPYING.
+ *If not, write to the Free Software Foundation,
+ *Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *See COPYRIGHT file copyright information.
+ */
+#ifndef __NEMIVER_ASM_UTILS_H__
+#define __NEMIVER_ASM_UTILS_H__
+
+#include "nmv-asm-instr.h"
+
+using nemiver::common::UString;
+
+NEMIVER_BEGIN_NAMESPACE (nemiver)
+NEMIVER_BEGIN_NAMESPACE (common)
+
+template<class Stream>
+Stream&
+operator<< (Stream &a_out, const AsmInstr &a_instr)
+{
+    a_out << "<asm-instr>\n"
+          << " <addr>" <<  a_instr.address () << "</addr>\n"
+          << " <function-name>" << a_instr.function () << "</function-name>\n"
+          << " <offset>" << a_instr.offset () << "</offset>\n"
+          << " <instr>" << a_instr.instruction () << "</instr>\n"
+          << "</asm-instr>\n";
+    return a_out;
+}
+
+template<class Stream>
+Stream&
+operator<< (Stream &a_out, const MixedAsmInstr &a_instr)
+{
+    a_out << "<asm-mixed-instr>\n"
+          << " <line>" << a_instr.line_number () << "</line>\n"
+          << " <path>" << a_instr.file_path ()   << "</path>\n";
+
+    list<AsmInstr>::const_iterator it;
+    a_out << " <asm-instr-list>";
+    for (it = a_instr.instrs ().begin ();
+         it != a_instr.instrs ().end ();
+         ++it) {
+        a_out << "  <asm-instr>\n"
+              << "   <addr>" <<  it->address () << "</addr>\n"
+              << "   <function-name>" << it->function ()
+                                      << "</function-name>\n"
+              << "   <offset>" << it->offset ()      << "</offset>\n"
+              << "   <instr>" <<  it->instruction () << "</instr>\n"
+              << "  </asm-instr>\n";
+    }
+    a_out << " </asm-instr-list>"
+          << "</asm-mixed-instr>\n";
+
+    return a_out;
+}
+
+template<class Stream>
+Stream&
+operator<< (Stream &a_out, const Asm &a_asm)
+{
+    switch (a_asm.which ()) {
+        case Asm::TYPE_PURE:
+            a_out << a_asm.instr ();
+            break;
+        case Asm::TYPE_MIXED:
+            a_out << a_asm.mixed_instr ();
+            break;
+        default:
+	  THROW ("reached unreachable");
+    }
+    return a_out;
+}
+
+void log_asm_insns (const std::list<common::Asm> &a_asm);
+
+typedef bool (* FindFileAndReadLine) (const UString &a_file_path,
+                                      const UString &a_prog_path,
+                                      const UString &a_cwd,
+                                      list<UString> &a_sess_dirs,
+                                      const list<UString> &a_glob_dirs,
+                                      map<UString, bool> &a_ignore_paths,
+                                      bool a_ignore_if_not_found,
+                                      int a_line_number,
+                                      std::string &a_line);
+class ReadLine
+{
+ private:
+    ReadLine ();
+    ReadLine (const ReadLine &);
+
+ protected:
+    const UString &m_prog_path;
+    const UString &m_cwd;
+    list<UString> &m_session_dirs;
+    const list<UString> &m_global_dirs;
+    map<UString, bool> &m_ignore_paths;
+    FindFileAndReadLine read_line;
+
+ public:
+    ReadLine (const UString &prog_path,
+              const UString &cwd,
+              list<UString> &session_dirs,
+              const list<UString> &global_dirs,
+              map<UString, bool> &ignore_paths,
+              FindFileAndReadLine read_line_func) :
+    m_prog_path (prog_path), m_cwd (cwd), m_session_dirs (session_dirs),
+        m_global_dirs (global_dirs), m_ignore_paths (ignore_paths),
+        read_line (read_line_func)
+    {
+    }
+
+    bool operator () (const UString &a_file_path,
+                      int a_line_number,
+                      std::string &a_line)
+    {
+        return read_line (a_file_path, m_prog_path, m_cwd, m_session_dirs,
+                          m_global_dirs, m_ignore_paths, true, a_line_number,
+                          a_line);
+    }
+};
+
+bool write_asm_instr (const common::Asm &a_asm,
+		      ReadLine &a_read,
+		      std::ostringstream &a_os);
+
+NEMIVER_END_NAMESPACE (common)
+NEMIVER_END_NAMESPACE (nemiver)
+
+#endif // __NEMIVER_ASM_UTILS_H__
diff --git a/src/common/nmv-env.cc b/src/common/nmv-env.cc
index eb7aa52..53cc2b9 100644
--- a/src/common/nmv-env.cc
+++ b/src/common/nmv-env.cc
@@ -32,6 +32,7 @@
 #include <fcntl.h>
 #include <string>
 #include <vector>
+#include <fstream>
 #include <glibmm.h>
 #include "nmv-env.h"
 #include "nmv-ustring.h"
@@ -376,6 +377,160 @@ build_path_to_executable (const UString &a_exe_name,
     return true;
 }
 
+bool
+find_file (const UString &a_file_name,
+           const UString &a_prog_path,
+           const UString &a_cwd,
+           const list<UString> &a_session_dirs,
+           const list<UString> &a_global_dirs,
+           UString &a_file_path)
+{
+    string file_name = Glib::filename_from_utf8 (a_file_name),
+        path,
+        candidate;
+
+    // first check if this is an absolute path
+    if (Glib::path_is_absolute (file_name)) {
+        if (Glib::file_test (file_name, Glib::FILE_TEST_IS_REGULAR)) {
+            a_file_path = Glib::filename_to_utf8 (file_name);
+            return true;
+        }
+    }
+    // then look in the working directory
+    candidate = Glib::build_filename (a_cwd, file_name);
+    if (Glib::file_test (candidate, Glib::FILE_TEST_IS_REGULAR)) {
+        a_file_path = Glib::filename_to_utf8 (candidate);
+        return true;
+    }
+    // then look in the directory of the binary
+    candidate =
+        Glib::build_filename (Glib::path_get_dirname (a_prog_path),
+                              file_name);
+    if (Glib::file_test (candidate, Glib::FILE_TEST_IS_REGULAR)) {
+        a_file_path = Glib::filename_to_utf8 (candidate);
+        return true;
+    }
+    // then look in the session-specific search paths
+    list<UString>::const_iterator session_iter;
+    for (session_iter = a_session_dirs.begin ();
+         session_iter != a_session_dirs.end ();
+         ++session_iter) {
+        path = Glib::filename_from_utf8 (*session_iter);
+        candidate = Glib::build_filename (path, file_name);
+        if (Glib::file_test (candidate, Glib::FILE_TEST_IS_REGULAR)) {
+            a_file_path = Glib::filename_to_utf8 (candidate);
+            return true;
+        }
+    }
+    // if not found, then look in the global search paths
+    list<UString>::const_iterator global_iter;
+    for (global_iter = a_global_dirs.begin ();
+         global_iter != a_global_dirs.end ();
+         ++global_iter) {
+        path = Glib::filename_from_utf8 (*global_iter);
+        candidate = Glib::build_filename (path, file_name);
+        if (Glib::file_test (candidate, Glib::FILE_TEST_IS_REGULAR)) {
+            a_file_path = Glib::filename_to_utf8 (candidate);
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+find_file_absolute_or_relative (const UString &a_file_name,
+                                const UString &a_prog_path,
+                                const UString &a_cwd,
+                                const list<UString> &a_session_dirs,
+                                const list<UString> &a_global_dirs,
+                                UString &a_file_path)
+{
+    // First, assume it's a full path name already.
+    if (Glib::file_test (a_file_name, Glib::FILE_TEST_IS_REGULAR)) {
+        a_file_path = a_file_name;
+        return true;
+    }
+
+    // If that didn't work, look for a file of that name in the search
+    // directories.
+    if (find_file (a_file_name, a_prog_path, a_cwd,
+                   a_session_dirs, a_global_dirs,
+                   a_file_path)) {
+        return true;
+    }
+
+    // Then look for a file of that basename in the search directories.
+    std::string basename =
+            Glib::path_get_basename (Glib::filename_from_utf8 (a_file_name));
+    if (basename != a_file_name
+        && find_file (basename, a_prog_path, a_cwd,
+                      a_session_dirs, a_global_dirs,
+                      a_file_path)) {
+        return true;
+    }
+    return false;
+}
+
+/// Given a file path P and a line number N , reads the line N from P
+/// and return it iff the function returns true. This is useful
+/// e.g. when forging a mixed source/assembly source view, and we want
+/// to display a source line N from a file P.
+///
+/// \param a_file_path the absolute file path to consider
+/// \param a_line_number the line number to consider
+/// \param a_line the string containing the resulting line read, if
+/// and only if the function returned true.
+/// \return true upon successful completion, false otherwise.
+bool
+read_file_line (const UString &a_file_path,
+                int a_line_number,
+                string &a_line)
+{
+    if (a_file_path.empty ())
+        return false;
+
+    bool found_line = false;
+    int line_num = 1;
+    char c = 0;
+
+    NEMIVER_TRY;
+
+    std::ifstream file (a_file_path.c_str ());
+
+    if (!file.good ()) {
+        LOG_ERROR ("Could not open file " + a_file_path);
+        return false;
+    }
+
+    while (true) {
+        if (line_num == a_line_number) {
+            found_line = true;
+            break;
+        }
+        file.get (c);
+        if (!file.good ())
+            break;
+        if (c == '\n')
+            ++line_num;
+    }
+    if (found_line) {
+        a_line.clear ();
+        while (true) {
+            file.get (c);
+            if (!file.good ())
+                break;
+            if (c == '\n')
+                break;
+            a_line += c;
+        }
+    }
+    file.close ();
+
+    NEMIVER_CATCH_NOX;
+
+    return found_line;
+}
+
 NEMIVER_END_NAMESPACE (env)
 NEMIVER_END_NAMESPACE (common)
 NEMIVER_END_NAMESPACE (nemiver)
diff --git a/src/common/nmv-env.h b/src/common/nmv-env.h
index 32e79cd..7181433 100644
--- a/src/common/nmv-env.h
+++ b/src/common/nmv-env.h
@@ -34,6 +34,8 @@
 #include "nmv-ustring.h"
 #include "nmv-exception.h"
 
+using nemiver::common::UString;
+
 NEMIVER_BEGIN_NAMESPACE (nemiver)
 NEMIVER_BEGIN_NAMESPACE (common)
 NEMIVER_BEGIN_NAMESPACE (env)
@@ -81,6 +83,24 @@ NEMIVER_API UString build_path_to_help_file (const UString &a_file_name);
 NEMIVER_API bool build_path_to_executable (const UString &a_exe_name,
                                            UString &a_exe_path);
 
+NEMIVER_API bool find_file (const UString &a_file_name,
+                            const UString &a_prog_path,
+                            const UString &a_cwd,
+                            const list<UString> &a_session_dirs,
+                            const list<UString> &a_global_dirs,
+                            UString &a_file_path);
+
+NEMIVER_API bool find_file_absolute_or_relative (const UString &a_file_name,
+                                                 const UString &a_prog_path,
+                                                 const UString &a_cwd,
+                                                 const list<UString> &a_sess_dirs,
+                                                 const list<UString> &a_glob_dirs,
+                                                 UString &a_file_path);
+
+NEMIVER_API bool read_file_line (const UString &a_file_path,
+                                 int a_line_number,
+                                 string &a_line);
+
 NEMIVER_END_NAMESPACE (env)
 NEMIVER_END_NAMESPACE (common)
 NEMIVER_END_NAMESPACE (nemiver)
diff --git a/src/common/nmv-str-utils.cc b/src/common/nmv-str-utils.cc
index 97c0f58..daffc6b 100644
--- a/src/common/nmv-str-utils.cc
+++ b/src/common/nmv-str-utils.cc
@@ -26,6 +26,7 @@
 #include <cstring>
 #include "nmv-str-utils.h"
 #include "nmv-safe-ptr-utils.h"
+#include "nmv-exception.h"
 
 NEMIVER_BEGIN_NAMESPACE (nemiver)
 NEMIVER_BEGIN_NAMESPACE (str_utils)
@@ -33,6 +34,17 @@ NEMIVER_BEGIN_NAMESPACE (str_utils)
 using nemiver::common::UString;
 using namespace nemiver::common;
 
+static const char *SUPPORTED_ENCODINGS[] =
+{
+    "UTF-8",
+    "ISO-8859",
+    "ISO-8859-1",
+    "ISO-8859-15",
+};
+
+#define SIZE_OF_SUPPORTED_ENCODINGS \
+sizeof (SUPPORTED_ENCODINGS)/sizeof (SUPPORTED_ENCODINGS[0])
+
 // Return true if a_str is a location string of the form
 // "filename:number", where number is string of digits.
 // Keep in mind that filename can also be a path that contains ':'
@@ -292,5 +304,84 @@ vprintf (const UString &a_format, va_list a_args)
     return result;
 }
 
+bool
+is_buffer_valid_utf8 (const char *a_buffer, unsigned a_len)
+{
+    
+    RETURN_VAL_IF_FAIL (a_buffer, false);
+    const char *end=0;
+    bool is_valid = g_utf8_validate (a_buffer, a_len, &end);
+    return is_valid;
+}
+
+bool
+ensure_buffer_is_in_utf8 (const std::string &a_input,
+			  const std::list<std::string> &a_supported_encodings,
+			  UString &a_output)
+{
+    UString buf_content;
+    if (is_buffer_valid_utf8 (a_input.c_str (), a_input.size ())) {
+        a_output = a_input;
+        return true;
+    }
+
+    UString utf8_content;
+    bool converted = false;
+
+    // get the list of candidate encodings that could be the encoding
+    // of the a_input. If for a reason we cannot sucessfully proceed
+    // with the conversion then we will fall back to a hardcoded list
+    // of encodings.
+    std::string current_charset;
+    if (!a_supported_encodings.empty ()) {
+        std::list<std::string>::const_iterator it;
+        for (it = a_supported_encodings.begin ();
+             it != a_supported_encodings.end ();
+             ++it) {
+            current_charset = *it;
+            try {
+                utf8_content =
+                    Glib::convert (a_input, "UTF-8", current_charset);
+            } catch (Glib::Exception &e) {
+                continue;
+            } catch (...) {
+                return false;
+            }
+            converted = true;
+            break;
+        }
+    }
+
+    if (!converted) {
+        // fall back to trying the hardcoded list of supported encodings
+        for (unsigned int i=0; i < SIZE_OF_SUPPORTED_ENCODINGS; i++) {
+            try {
+                utf8_content =
+                    Glib::convert (a_input,
+                                   "UTF-8",
+                                   SUPPORTED_ENCODINGS[i]);
+            } catch (Glib::Exception &e) {
+                continue;
+            } catch (...) {
+                return false;
+            }
+            converted = true;
+        }
+    }
+
+    if (!converted)
+        return false;
+
+    const char *end=0;
+    if (utf8_content.empty ()
+        || !g_utf8_validate (utf8_content.raw ().c_str (),
+                             utf8_content.bytes (),
+                             &end)) {
+        return false;
+    }
+    a_output = utf8_content;
+    return true;
+}
+
 NEMIVER_END_NAMESPACE (str_utils)
 NEMIVER_END_NAMESPACE (nemiver)
diff --git a/src/common/nmv-str-utils.h b/src/common/nmv-str-utils.h
index 76490cd..65b798d 100644
--- a/src/common/nmv-str-utils.h
+++ b/src/common/nmv-str-utils.h
@@ -82,6 +82,13 @@ UString printf (const UString &a_format, ...);
 
 UString vprintf (const UString &a_format, va_list a_args);
 
+bool is_buffer_valid_utf8 (const char *a_buffer, unsigned a_len);
+
+bool ensure_buffer_is_in_utf8 (const std::string &a_input,
+			       const std::list<std::string> &supported_encodings,
+			       UString &a_output);
+			       
+
 NEMIVER_END_NAMESPACE (str_utils)
 NEMIVER_END_NAMESPACE (nemiver)
 
diff --git a/src/common/nmv-ustring.cc b/src/common/nmv-ustring.cc
index 8be7e7b..4e2d5d6 100644
--- a/src/common/nmv-ustring.cc
+++ b/src/common/nmv-ustring.cc
@@ -191,16 +191,17 @@ UString::operator! () const
     return false;
 }
 
-vector<UString>
-UString::split (const UString &a_delim) const
+template<class string_container>
+string_container
+split_base (const UString &a_string, const UString &a_delim)
 {
-    vector<UString> result;
-    if (size () == Glib::ustring::size_type (0)) {return result;}
+    string_container result;
+    if (a_string.size () == Glib::ustring::size_type (0)) {return result;}
 
-    gint len = bytes () + 1;
+    gint len = a_string.bytes () + 1;
     CharSafePtr buf (new gchar[len]);
     memset (buf.get (), 0, len);
-    memcpy (buf.get (), c_str (), bytes ());
+    memcpy (buf.get (), a_string.c_str (), a_string.bytes ());
 
     gchar **splited = g_strsplit (buf.get (), a_delim.c_str (), -1);
     try {
@@ -217,6 +218,18 @@ UString::split (const UString &a_delim) const
 }
 
 vector<UString>
+UString::split (const UString &a_delim) const
+{
+    return split_base<vector<UString> > (*this, a_delim);
+}
+
+list<UString>
+UString::split_to_list (const UString &a_delim) const
+{
+    return split_base<list<UString> > (*this, a_delim);
+}
+
+vector<UString>
 UString::split_set (const UString &a_delim_set) const
 {
     vector<UString> result;
diff --git a/src/common/nmv-ustring.h b/src/common/nmv-ustring.h
index 3a2acde..a181c97 100644
--- a/src/common/nmv-ustring.h
+++ b/src/common/nmv-ustring.h
@@ -64,6 +64,7 @@ public:
     UString& operator= (UString const &a_cstr);
     bool operator! () const;
     vector<UString> split (const UString &a_delim) const;
+    list<UString> split_to_list (const UString &a_delim) const;
     vector<UString> split_set (const UString &a_delim_set) const;
     static UString join (const vector<UString> &a_elements,
                          const UString &a_delim=" ");
diff --git a/src/dbgengine/Makefile.am b/src/dbgengine/Makefile.am
index 439c441..c4e73cd 100644
--- a/src/dbgengine/Makefile.am
+++ b/src/dbgengine/Makefile.am
@@ -23,7 +23,7 @@ libdebuggerutils.la \
 libgdbengine.la
 
 idebuggerheaders= \
-nmv-i-debugger.h nmv-asm-utils.h
+nmv-i-debugger.h
 
 ivarlistheaders= \
 nmv-i-var-list.h
diff --git a/src/dbgengine/nmv-gdbmi-parser.cc b/src/dbgengine/nmv-gdbmi-parser.cc
index 7d1f6fe..29f39c6 100644
--- a/src/dbgengine/nmv-gdbmi-parser.cc
+++ b/src/dbgengine/nmv-gdbmi-parser.cc
@@ -26,7 +26,6 @@
 #include <sstream>
 #include "common/nmv-str-utils.h"
 #include "nmv-gdbmi-parser.h"
-#include "nmv-asm-utils.h"
 
 using nemiver::common::UString;
 
diff --git a/src/dbgengine/nmv-i-debugger.h b/src/dbgengine/nmv-i-debugger.h
index e8a7af4..101573c 100644
--- a/src/dbgengine/nmv-i-debugger.h
+++ b/src/dbgengine/nmv-i-debugger.h
@@ -39,8 +39,6 @@
 #include "common/nmv-asm-instr.h"
 #include "nmv-i-conf-mgr.h"
 
-NEMIVER_BEGIN_NAMESPACE (nemiver)
-
 using nemiver::common::SafePtr;
 using nemiver::common::DynamicModule;
 using nemiver::common::DynamicModuleSafePtr;
@@ -59,6 +57,8 @@ using std::string;
 using std::map;
 using std::list;
 
+NEMIVER_BEGIN_NAMESPACE (nemiver)
+
 class ILangTrait;
 class IDebugger;
 typedef SafePtr<IDebugger, ObjectRef, ObjectUnref> IDebuggerSafePtr;
diff --git a/src/persp/dbgperspective/Makefile.am b/src/persp/dbgperspective/Makefile.am
index 334bef1..7bcdc56 100644
--- a/src/persp/dbgperspective/Makefile.am
+++ b/src/persp/dbgperspective/Makefile.am
@@ -24,12 +24,8 @@ pluginconfigdir= NEMIVER_PLUGINS_DIR@/$(PLUGIN_NAME)
 plugin_LTLIBRARIES=libdbgperspectiveplugin.la
 plugindir= NEMIVER_PLUGINS_DIR@/$(PLUGIN_NAME)
 sources= \
-nmv-dialog.cc \
-nmv-dialog.h \
 nmv-run-program-dialog.cc \
 nmv-run-program-dialog.h \
-nmv-locate-file-dialog.cc \
-nmv-locate-file-dialog.h \
 nmv-load-core-dialog.cc \
 nmv-load-core-dialog.h \
 nmv-saved-sessions-dialog.h \
diff --git a/src/persp/dbgperspective/glade/Makefile.am b/src/persp/dbgperspective/glade/Makefile.am
index a40be1e..a6e98b0 100644
--- a/src/persp/dbgperspective/glade/Makefile.am
+++ b/src/persp/dbgperspective/glade/Makefile.am
@@ -3,7 +3,6 @@ gladefiles = bodycontainer.glade \
 runprogramdialog.glade \
 proclistdialog.glade \
 loadcoredialog.glade \
-locatefiledialog.glade \
 savedsessionsdialog.glade \
 preferencesdialog.glade \
 varinspectordialog.glade \
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.cc b/src/persp/dbgperspective/nmv-dbg-perspective.cc
index c3152e3..1e27263 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.cc
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.cc
@@ -32,7 +32,6 @@
 #include <unistd.h>
 #include <algorithm>
 #include <iostream>
-#include <fstream>
 #include <sstream>
 #include <glib/gi18n.h>
 
@@ -99,7 +98,6 @@
 #include "nmv-memory-view.h"
 #endif // WITH_MEMORYVIEW
 #include "nmv-watchpoint-dialog.h"
-#include "nmv-asm-utils.h"
 
 using namespace std;
 using namespace nemiver::common;
@@ -131,7 +129,6 @@ const char *PROGRAM_CWD= "programcwd";
 const char *LAST_RUN_TIME= "lastruntime";
 const char *DBG_PERSPECTIVE_MOUSE_MOTION_DOMAIN =
                                 "dbg-perspective-mouse-motion-domain";
-const char *DBG_PERSPECTIVE_ASM_DOMAIN = "dbg-perspective-asm-domain";
 const char *DISASSEMBLY_TITLE = "<Disassembly>";
 
 static const int NUM_INSTR_TO_DISASSEMBLE = 20;
@@ -180,21 +177,10 @@ const Gtk::StockID STOCK_STEP_INTO (STEP_INTO);
 const Gtk::StockID STOCK_STEP_OVER (STEP_OVER);
 const Gtk::StockID STOCK_STEP_OUT (STEP_OUT);
 
-const char *SUPPORTED_ENCODINGS[] =
-{
-    "UTF-8",
-    "ISO-8859",
-    "ISO-8859-1",
-    "ISO-8859-15",
-};
-
 const char *I_DEBUGGER_COOKIE_EXECUTE_PROGRAM = "i-debugger-execute-program";
 
 const char *PROG_ARG_SEPARATOR = "#DUMMY-SEP007#";
 
-#define SIZE_OF_SUPPORTED_ENCODINGS \
-sizeof (SUPPORTED_ENCODINGS)/sizeof (SUPPORTED_ENCODINGS[0])
-
 class DBGPerspective;
 
 #ifdef WITH_GIO
@@ -212,18 +198,6 @@ gnome_vfs_file_monitor_cb (GnomeVFSMonitorHandle *a_handle,
                            DBGPerspective *a_persp);
 #endif
 
-static void
-log_asm_insns (std::list<common::Asm> a_asm)
-{
-    typedef std::list<common::Asm> Asms;
-    Asms::const_iterator it = a_asm.begin ();
-    if (it != a_asm.end ()) {
-        LOG_D (*it, DBG_PERSPECTIVE_ASM_DOMAIN);
-    }
-    for (++it; it != a_asm.end (); ++it) {
-        LOG_D ("\n" << *it, DBG_PERSPECTIVE_ASM_DOMAIN);
-    }
-}
 
 class DBGPerspective : public IDBGPerspective, public sigc::trackable {
     //non copyable
@@ -538,18 +512,6 @@ public:
 
     void open_file ();
 
-    bool get_file_mime_type (const UString &a_path,
-                             UString &a_mime_type);
-
-    bool setup_buffer_mime_and_lang
-                         (Glib::RefPtr<SourceBuffer> &a_buf,
-                          const std::string &a_mime_type = "text/x-c++") const;
-
-    Glib::RefPtr<SourceBuffer> create_source_buffer () const;
-
-    bool load_file (const UString &a_file,
-                    Glib::RefPtr<SourceBuffer> &a_source_buffer);
-
     bool open_file (const UString &a_path, int current_line=-1);
 
     SourceEditor* open_file_real (const UString &a_path, int current_line=-1);
@@ -571,21 +533,7 @@ public:
 
     bool is_asm_title (const UString &);
 
-    bool load_asm (const common::DisassembleInfo &a_info,
-                   const std::list<common::Asm> &a_asm,
-                   Glib::RefPtr<gtksourceview::SourceBuffer> &a_buf);
-
     bool read_file_line (const UString&, int, string&);
-    bool write_asm_instr (std::ostringstream&,
-                          const common::AsmInstr&);
-
-    bool write_asm_instr (std::ostringstream&,
-                          const common::Asm&);
-
-    bool add_asm (const common::DisassembleInfo &a_info,
-                  const std::list<common::Asm> &a_asm,
-                  Glib::RefPtr<gtksourceview::SourceBuffer> &a_buf,
-                  bool a_append = true);
 
     SourceEditor* open_asm (const common::DisassembleInfo &a_info,
                             const std::list<common::Asm> &a_asm,
@@ -599,8 +547,7 @@ public:
                         SourceEditor *a_editor);
 
     void pump_asm_including_address (SourceEditor *a_editor,
-                                     const Address a_address,
-                                     bool a_tight = false);
+                                     const Address a_address);
 
     void switch_to_source_code ();
 
@@ -847,7 +794,7 @@ public:
 
     void read_default_config ();
 
-    vector<UString>& get_source_dirs ();
+    list<UString>& get_global_search_paths ();
 
     bool find_file_in_source_dirs (const UString &a_file_name,
                                    UString &a_file_path);
@@ -929,7 +876,8 @@ struct DBGPerspective::Priv {
     vector<UString> prog_args;
     UString prog_cwd;
     map<UString, UString> env_variables;
-    list<UString> search_paths;
+    list<UString> session_search_paths;
+    list<UString> global_search_paths;
     map<UString, bool> paths_to_ignore;
     Glib::RefPtr<Gnome::Glade::Xml> body_glade;
     SafePtr<Gtk::Window> body_window;
@@ -1014,7 +962,6 @@ struct DBGPerspective::Priv {
     ISessMgr::Session session;
     IProcMgrSafePtr process_manager;
     UString last_command_text;
-    vector<UString> source_dirs;
     bool show_dbg_errors;
     bool use_system_font;
     bool show_line_numbers;
@@ -1164,120 +1111,36 @@ struct DBGPerspective::Priv {
         }
     }
 
-    bool is_buffer_valid_utf8 (const char *a_buffer,
-                               unsigned a_len)
-    {
-        RETURN_VAL_IF_FAIL (a_buffer, false);
-        const char *end=0;
-        bool is_valid = g_utf8_validate (a_buffer, a_len, &end);
-        return is_valid;
-    }
-
-    //if source_buffer is not encoded in utf8, assume it is encoded
-    //in the current user locale.
-    //Try to convert it from user locale to utf8, and make sure the result
-    //is valid. if not, throw an exception due to the fact the file is
-    //encoded in an unknown encoding.
-    bool ensure_buffer_is_in_utf8 (const UString &a_path,
-                                   const std::string &a_input,
-                                   UString &a_output,
-                                   std::string &a_current_charset)
+    bool get_supported_encodings (list<string> &a_encodings)
     {
-        LOG_FUNCTION_SCOPE_NORMAL_DD;
-        NEMIVER_TRY
+        list<UString> encodings;
+
+        NEMIVER_TRY;
 
-        UString buf_content;
-        if (is_buffer_valid_utf8 (a_input.c_str (), a_input.size ())) {
-            a_output = a_input;
-            return true;
-        }
-        UString utf8_content;
-        bool converted=false;
-        //get the list of candidate encodings that could be the encoding of
-        //the a_input. This list is in gconf. So let's kindly ask gconf for
-        //it. If for a reason we cannot reach gconf or the list is empty,
-        //then we will fall back to a hardcoded list of encodings.
-        THROW_IF_FAIL (workbench);
         IConfMgrSafePtr conf_mgr = workbench->get_configuration_manager ();
-        THROW_IF_FAIL (conf_mgr);
-        std::list<UString> supported_encodings;
-        bool have_gconf_values = false;
+        conf_mgr->get_key_value (CONF_KEY_SOURCE_FILE_ENCODING_LIST,
+                                 encodings);
 
-        NEMIVER_TRY
-        have_gconf_values =
-            conf_mgr->get_key_value (CONF_KEY_SOURCE_FILE_ENCODING_LIST,
-                                     supported_encodings);
-        NEMIVER_CATCH_NOX
-        if (have_gconf_values && !supported_encodings.empty ()) {
-            LOG_DD ("trying encodings coming from gconf");
-            std::list<UString>::const_iterator it;
-            for (it = supported_encodings.begin ();
-                 it != supported_encodings.end ();
-                 ++it) {
-                try {
-                    LOG_DD ("trying to convert buffer from encoding "
-                             << it->c_str ()
-                             << " to UTF-8");
-                    utf8_content =
-                        Glib::convert (a_input, "UTF-8",
-                                       it->c_str ());
-                } catch (Glib::Exception &e) {
-                    LOG_DD ("tentative encoding conversion failed!");
-                    continue;
-                } catch (...) {
-                    THROW ("unknown exception raised by Glib::convert()");
-                }
-                LOG_DD ("tentative encoding conversion succeeded!");
-                converted = true;
-                break;
-            }
-        }
+        NEMIVER_CATCH_AND_RETURN (false);
 
-        if (!converted) {
-            //fall back to trying the hardcoded list of supported encodings
-            LOG_DD ("trying hardcoded encodings");
-            for (unsigned int i=0; i < SIZE_OF_SUPPORTED_ENCODINGS; i++) {
-                try {
-                    utf8_content =
-                        Glib::convert (a_input,
-                                       "UTF-8",
-                                       SUPPORTED_ENCODINGS[i]);
-                } catch (Glib::Exception &e) {
-                    continue;
-                } catch (...) {
-                    THROW ("unknown exception raised by Glib::convert()");
-                }
-                converted = true;
-            }
-        }
-        if (!converted) {
-            THROW_IF_FAIL (!a_path.empty ());
-            UString message;
-            message.printf (_("File %s has an encoding that is not listed in "
-                            "the value of gconf key %s. "
-                            "Please add the encoding "
-                            "of that file to the values of the gconf "
-                            "key, and resume debugging"),
-                             a_path.c_str (),
-                             CONF_KEY_SOURCE_FILE_ENCODING_LIST);
-            THROW (message);
-        }
-        const char *end=0;
-        if (utf8_content.empty ()
-            || !g_utf8_validate (utf8_content.raw ().c_str (),
-                                 utf8_content.bytes (),
-                                 &end)) {
-            LOG_ERROR ("conversion from "
-                       << a_current_charset
-                       << " to utf8 failed");
-            return false;
+        for (list<UString>::const_iterator it = encodings.begin ();
+             it != encodings.end ();
+             ++it) {
+            a_encodings.push_back (it->raw ());
         }
-        a_output = utf8_content;
-
-        NEMIVER_CATCH_AND_RETURN (false)
+        return !encodings.empty ();
+    }
 
-        return true;
+    bool load_file (const UString &a_path,
+                    Glib::RefPtr<SourceBuffer> &a_buffer)
+    {
+        list<string> supported_encodings;
+        get_supported_encodings (supported_encodings);
+        return SourceEditor::load_file (a_path, supported_encodings,
+                                        enable_syntax_highlight,
+                                        a_buffer);
     }
+
 };//end struct DBGPerspective::Priv
 
 enum ViewsIndex
@@ -2282,7 +2145,7 @@ DBGPerspective::on_conf_key_changed_signal (const UString &a_key,
     NEMIVER_TRY
     if (a_key == CONF_KEY_NEMIVER_SOURCE_DIRS) {
         LOG_DD ("updated key source-dirs");
-        m_priv->source_dirs = boost::get<UString> (a_value).split (":");
+        m_priv->global_search_paths = boost::get<UString> (a_value).split_to_list (":");
     } else if (a_key == CONF_KEY_SHOW_DBG_ERROR_DIALOGS) {
         m_priv->show_dbg_errors = boost::get<bool> (a_value);
     } else if (a_key == CONF_KEY_SHOW_SOURCE_LINE_NUMBERS) {
@@ -4075,33 +3938,21 @@ DBGPerspective::clear_session_data ()
     THROW_IF_FAIL (m_priv);
 
     m_priv->env_variables.clear ();
-    m_priv->search_paths.clear ();
+    m_priv->session_search_paths.clear ();
     m_priv->breakpoints.clear ();
-    m_priv->source_dirs.clear ();
+    m_priv->global_search_paths.clear ();
 }
 
 bool
 DBGPerspective::find_absolute_path (const UString& a_file_path,
                                     UString &a_absolute_path)
 {
-    // First, assume it's a full path name already.
-    if (Glib::file_test (a_file_path, Glib::FILE_TEST_IS_REGULAR)) {
-        a_absolute_path = a_file_path;
-        return true;
-    }
-    // If that didn't work, look for a file of that name in the search
-    // directories.
-    if (find_file_in_source_dirs (a_file_path, a_absolute_path)) {
-        return true;
-    }
-    // Then look for a file of that basename in the search directories.
-    std::string basename =
-            Glib::path_get_basename (Glib::filename_from_utf8 (a_file_path));
-    if (basename != a_file_path
-        && find_file_in_source_dirs (basename, a_absolute_path)) {
-        return true;
-    }
-    return false;
+    return common::env::find_file_absolute_or_relative (a_file_path,
+                                                        m_priv->prog_path,
+                                                        m_priv->prog_cwd,
+                                                        m_priv->session_search_paths,
+                                                        m_priv->global_search_paths,
+                                                        a_absolute_path);
 }
 
 /// Lookup a file path and return true if found. If the path is not
@@ -4120,25 +3971,14 @@ DBGPerspective::find_absolute_path_or_ask_user (const UString& a_file_path,
                                                 UString& a_absolute_path,
                                                 bool a_ignore_if_not_found)
 {
-    if (!find_absolute_path (a_file_path, a_absolute_path)) {
-        if (m_priv->paths_to_ignore.find (a_file_path)
-            != m_priv->paths_to_ignore.end ())
-            // We didn't find a_file_path but as we were previously
-            // requested to *not* ask the user to locate it, just
-            // pretend we didn't find the file.
-            return false;
-        if (ask_user_to_select_file (a_file_path, a_absolute_path)) {
-            UString parent_dir = Glib::filename_to_utf8
-                                    (Glib::path_get_dirname (a_absolute_path));
-            m_priv->search_paths.push_back (parent_dir);
-        } else {
-            if (a_ignore_if_not_found)
-                // Don't ask the user to locate a_file_path next time.
-                m_priv->paths_to_ignore[a_file_path] = true;
-            return false;
-        }
-    }
-    return true;
+    return ui_utils::find_absolute_path_or_ask_user (a_file_path,
+                                                     m_priv->prog_path,
+                                                     m_priv->prog_cwd,
+                                                     m_priv->session_search_paths,
+                                                     m_priv->global_search_paths,
+                                                     m_priv->paths_to_ignore,
+                                                     a_ignore_if_not_found,
+                                                     a_absolute_path);
 }
 
 void
@@ -4462,7 +4302,8 @@ DBGPerspective::get_or_append_asm_source_editor ()
     SourceEditor *source_editor =
         get_source_editor_from_path (get_asm_title (), path);
     if (source_editor == 0) {
-        Glib::RefPtr<SourceBuffer> source_buffer = create_source_buffer ();
+        Glib::RefPtr<SourceBuffer> source_buffer =
+            SourceEditor::create_source_buffer ();
         source_editor =
             create_source_editor (source_buffer,
                                   /*a_asm_view=*/true,
@@ -4812,16 +4653,16 @@ DBGPerspective::get_thread_list ()
     return *m_priv->thread_list;
 }
 
-vector<UString>&
-DBGPerspective::get_source_dirs ()
+list<UString>&
+DBGPerspective::get_global_search_paths ()
 {
 
     THROW_IF_FAIL (m_priv);
 
-    if (m_priv->source_dirs.empty ()) {
+    if (m_priv->global_search_paths.empty ()) {
         read_default_config ();
     }
-    return m_priv->source_dirs;
+    return m_priv->global_search_paths;
 }
 
 bool
@@ -4830,55 +4671,9 @@ DBGPerspective::find_file_in_source_dirs (const UString &a_file_name,
 {
     THROW_IF_FAIL (m_priv);
 
-    string file_name = Glib::filename_from_utf8 (a_file_name),
-                                                 path,
-                                                 candidate;
-    // first check if this is an absolute path
-    if (Glib::path_is_absolute (file_name)) {
-        if (Glib::file_test (file_name, Glib::FILE_TEST_IS_REGULAR)) {
-            a_file_path = Glib::filename_to_utf8 (file_name);
-            return true;
-        }
-    }
-    // then look in the working directory
-    candidate = Glib::build_filename (m_priv->prog_cwd, file_name);
-    if (Glib::file_test (candidate, Glib::FILE_TEST_IS_REGULAR)) {
-        a_file_path = Glib::filename_to_utf8 (candidate);
-        return true;
-    }
-    // then look in the directory of the binary
-    candidate =
-        Glib::build_filename (Glib::path_get_dirname (m_priv->prog_path),
-                              file_name);
-    if (Glib::file_test (candidate, Glib::FILE_TEST_IS_REGULAR)) {
-        a_file_path = Glib::filename_to_utf8 (candidate);
-        return true;
-    }
-    // then look in the session-specific search paths
-    list<UString>::const_iterator session_iter;
-    for (session_iter = m_priv->search_paths.begin ();
-         session_iter != m_priv->search_paths.end ();
-         ++session_iter) {
-        path = Glib::filename_from_utf8 (*session_iter);
-        candidate = Glib::build_filename (path, file_name);
-        if (Glib::file_test (candidate, Glib::FILE_TEST_IS_REGULAR)) {
-            a_file_path = Glib::filename_to_utf8 (candidate);
-            return true;
-        }
-    }
-    // if not found, then look in the global search paths
-    vector<UString>::const_iterator global_iter;
-    for (global_iter = m_priv->source_dirs.begin ();
-         global_iter != m_priv->source_dirs.end ();
-         ++global_iter) {
-        path = Glib::filename_from_utf8 (*global_iter);
-        candidate = Glib::build_filename (path, file_name);
-        if (Glib::file_test (candidate, Glib::FILE_TEST_IS_REGULAR)) {
-            a_file_path = Glib::filename_to_utf8 (candidate);
-            return true;
-        }
-    }
-    return false;
+    return common::env::find_file (a_file_name, m_priv->prog_path,
+                                   m_priv->prog_cwd, m_priv->session_search_paths,
+                                   m_priv->global_search_paths, a_file_path);
 }
 
 bool
@@ -4958,7 +4753,7 @@ DBGPerspective::read_default_config ()
 {
     THROW_IF_FAIL (m_priv->workbench);
     IConfMgr &conf_mgr = get_conf_mgr ();
-    if (m_priv->source_dirs.empty ()) {
+    if (m_priv->global_search_paths.empty ()) {
         UString dirs;
 
         NEMIVER_TRY
@@ -4967,8 +4762,8 @@ DBGPerspective::read_default_config ()
 
         LOG_DD ("got source dirs '" << dirs << "' from conf mgr");
         if (!dirs.empty ()) {
-            m_priv->source_dirs = dirs.split (":");
-            LOG_DD ("that makes '" <<(int)m_priv->source_dirs.size()
+            m_priv->global_search_paths = dirs.split_to_list (":");
+            LOG_DD ("that makes '" <<(int)m_priv->global_search_paths.size()
                     << "' dir paths");
         }
 
@@ -5360,8 +5155,8 @@ DBGPerspective::record_and_save_session (ISessMgr::Session &a_session)
 
     a_session.search_paths ().clear ();
     list<UString>::const_iterator search_path_iter;
-    for (search_path_iter = m_priv->search_paths.begin ();
-         search_path_iter != m_priv->search_paths.end ();
+    for (search_path_iter = m_priv->session_search_paths.begin ();
+         search_path_iter != m_priv->session_search_paths.end ();
          ++search_path_iter) {
         a_session.search_paths ().push_back (*search_path_iter);
     }
@@ -5461,193 +5256,6 @@ DBGPerspective::edit_workbench_menu ()
     //init_perspective_menu_entries ();
 }
 
-bool
-DBGPerspective::get_file_mime_type (const UString &a_path,
-                                    UString &a_mime_type)
-{
-    NEMIVER_TRY
-
-    std::string path = Glib::filename_from_utf8 (a_path);
-
-#ifdef WITH_GIO
-    Glib::RefPtr<Gio::File> gio_file = Gio::File::create_for_path (path);
-    THROW_IF_FAIL (gio_file);
-#else
-    UString base_name = Glib::filename_to_utf8 (Glib::path_get_basename (path));
-#endif
-
-    UString mime_type;
-#ifdef WITH_GIO
-    Glib::RefPtr<Gio::FileInfo> info = gio_file->query_info();
-    mime_type = Gio::content_type_get_mime_type(info->get_content_type ());
-#else
-    mime_type = gnome_vfs_get_mime_type_for_name (base_name.c_str ());
-#endif
-
-    if (mime_type == "") {
-        mime_type = "text/x-c++";
-    }
-    LOG_DD ("file has mime type: " << mime_type);
-    a_mime_type = mime_type;
-    return true;
-
-    NEMIVER_CATCH_AND_RETURN (false)
-}
-
-// Make sure the source buffer a_buf is properly setup to have the mime
-// type a_mime_type. If a_buf is null, a new one is created.
-// Returns true upon successful completion, false otherwise.
-bool
-DBGPerspective::setup_buffer_mime_and_lang (Glib::RefPtr<SourceBuffer> &a_buf,
-                                            const std::string &a_mime_type) const
-{
-    NEMIVER_TRY
-
-#ifdef WITH_SOURCEVIEWMM2
-    Glib::RefPtr<SourceLanguageManager> lang_manager =
-                                    SourceLanguageManager::get_default ();
-#else
-    Glib::RefPtr<SourceLanguagesManager> lang_manager =
-                                    SourceLanguagesManager::create ();
-#endif  // WITH_SOURCEVIEWMM2
-    Glib::RefPtr<SourceLanguage> lang;
-#ifdef WITH_SOURCEVIEWMM2
-    std::list<Glib::ustring> lang_ids = lang_manager->get_language_ids ();
-    for (std::list<Glib::ustring>::const_iterator it = lang_ids.begin ();
-         it != lang_ids.end ();
-         ++it) {
-        Glib::RefPtr<gtksourceview::SourceLanguage> candidate = 
-            lang_manager->get_language (*it);
-        std::list<Glib::ustring> mime_types = candidate->get_mime_types ();
-        std::list<Glib::ustring>::const_iterator mime_it;
-        for (mime_it = mime_types.begin ();
-             mime_it != mime_types.end ();
-             ++mime_it) {
-            if (*mime_it == a_mime_type) {
-                // one of the mime types associated with this language matches
-                // the mime type of our file, so use this language
-                lang = candidate;
-                break;  // no need to look at further mime types
-            }
-        }
-        // we found a matching language, so stop looking for other languages
-        if (lang) break;
-    }
-#else
-    lang = lang_manager->get_language_from_mime_type (mime_type);
-#endif  // WITH_SOURCEVIEWMM2
-
-    if (!a_buf)
-        a_buf = SourceBuffer::create (lang);
-    else {
-        a_buf->set_language (lang);
-        a_buf->erase (a_buf->begin (), a_buf->end ());
-    }
-    THROW_IF_FAIL (a_buf);
-    return true;
-
-    NEMIVER_CATCH_AND_RETURN (false);
-}
-
-/// Create a source buffer properly set up to contain/highlight c++
-/// code.
-/// \return the created buffer or nil if something bad happened.
-Glib::RefPtr<SourceBuffer>
-DBGPerspective::create_source_buffer () const
-{
-    Glib::RefPtr<SourceBuffer> result;
-    setup_buffer_mime_and_lang (result);
-    return result;
-}
-
-bool
-DBGPerspective::load_file (const UString &a_path,
-                           Glib::RefPtr<SourceBuffer> &a_source_buffer)
-{
-    NEMIVER_TRY
-
-    std::string path = Glib::filename_from_utf8 (a_path);
-#ifdef WITH_GIO
-    Glib::RefPtr<Gio::File> gio_file = Gio::File::create_for_path (path);
-    THROW_IF_FAIL (gio_file);
-    if (!gio_file->query_exists ()) {
-#else
-    ifstream file (path.c_str ());
-    if (!file.good () && !file.eof ()) {
-#endif
-        LOG_ERROR ("Could not open file " + path);
-        ui_utils::display_error ("Could not open file: "
-                                 + Glib::filename_to_utf8 (path));
-        return false;
-    }
-
-    UString mime_type;
-    if (!get_file_mime_type (path, mime_type)) {
-        LOG_ERROR ("Could not get mime type for " + path);
-        return false;
-    }
-
-    if (!setup_buffer_mime_and_lang (a_source_buffer, mime_type)) {
-        LOG_ERROR ("Could not setup source buffer mime type or language");
-        return false;
-    }
-    THROW_IF_FAIL (a_source_buffer);
-
-    gint buf_size = 10 * 1024;
-    CharSafePtr buf (new gchar [buf_size + 1]);
-    memset (buf.get (), 0, buf_size + 1);
-
-    unsigned nb_bytes=0;
-    std::string content;
-#ifdef WITH_GIO
-    Glib::RefPtr<Gio::FileInputStream> gio_stream = gio_file->read ();
-    THROW_IF_FAIL (gio_stream);
-    gssize bytes_read = 0;
-    for (;;) {
-        bytes_read = gio_stream->read (buf.get (), buf_size);
-        content.append (buf.get (), bytes_read);
-        nb_bytes += bytes_read;
-        if (bytes_read != buf_size) {break;}
-    }
-    gio_stream->close ();
-#else
-    for (;;) {
-        file.read (buf.get (), buf_size);
-        content.append (buf.get (), file.gcount ());
-        THROW_IF_FAIL (file.good () || file.eof ());
-        nb_bytes += file.gcount ();
-        if (file.gcount () != buf_size) {break;}
-    }
-    file.close ();
-#endif // WITH_GIO
-    UString utf8_content;
-    std::string cur_charset;
-    if (!m_priv->ensure_buffer_is_in_utf8 (a_path,
-                                           content,
-                                           utf8_content,
-                                           cur_charset)) {
-        UString msg;
-        msg.printf (_("Could not load file %s because its encoding "
-                      "is different from %s"),
-                    path.c_str (),
-                    cur_charset.c_str ());
-        ui_utils::display_error (msg);
-        return false;
-    }
-    a_source_buffer->set_text (utf8_content);
-    LOG_DD ("file loaded. Read " << (int)nb_bytes << " bytes");
-
-#ifdef WITH_SOURCEVIEWMM2
-    a_source_buffer->set_highlight_syntax (m_priv->enable_syntax_highlight);
-#else
-    a_source_buffer->set_highlight (m_priv->enable_syntax_highlight);
-#endif  // WITH_SOURCEVIEWMM2
-
-    NEMIVER_CATCH_AND_RETURN (false);
-
-    return true;
-}
-
 SourceEditor*
 DBGPerspective::create_source_editor (Glib::RefPtr<SourceBuffer> &a_source_buf,
                                       bool a_asm_view,
@@ -5775,9 +5383,8 @@ DBGPerspective::open_file_real (const UString &a_path,
     NEMIVER_TRY
 
     Glib::RefPtr<SourceBuffer> source_buffer;
-    if (!load_file (a_path, source_buffer)) {
+    if (!m_priv->load_file (a_path, source_buffer))
         return 0;
-    }
 
     source_editor = create_source_editor (source_buffer,
                                           /*a_asm_view=*/false,
@@ -5870,224 +5477,6 @@ DBGPerspective::is_asm_title (const UString &a_path)
     return (a_path.raw () == DISASSEMBLY_TITLE);
 }
 
-bool
-DBGPerspective::load_asm (const common::DisassembleInfo &a_info,
-                          const std::list<common::Asm> &a_asm,
-                          Glib::RefPtr<SourceBuffer> &a_source_buffer)
-{
-    LOG_FUNCTION_SCOPE_NORMAL_DD;
-
-    NEMIVER_TRY
-
-    std::string mime_type = "text/x-asm";
-    if (!setup_buffer_mime_and_lang (a_source_buffer, mime_type)) {
-        LOG_ERROR ("Could not setup source buffer mime type of language");
-        return false;
-    }
-    THROW_IF_FAIL (a_source_buffer);
-
-    add_asm (a_info, a_asm, a_source_buffer, /*append=*/ true);
-
-    NEMIVER_CATCH_AND_RETURN (false)
-    return true;
-}
-
-/// Given a file path P and a line number N , reads the line N from P
-/// and return it iff the function returns true. This is useful
-/// e.g. when forging a mixed source/assembly source view, and we want
-/// to display a source line N from a file P.
-///
-/// \param a_file_path the file path to consider
-/// \param a_line_number the line number to consider
-/// \param a_line the string containing the resulting line read, if
-/// and only if the function returned true.
-/// \return true upon successful completion, false otherwise.
-bool
-DBGPerspective::read_file_line (const UString &a_file_path,
-                                int a_line_number,
-                                string &a_line)
-{
-    if (a_file_path.empty ())
-        return false;
-
-    UString path;
-    if (!find_absolute_path_or_ask_user (a_file_path, path))
-        return false;
-    bool found_line = false;
-    int line_num = 1;
-    char c = 0;
-
-    NEMIVER_TRY
-
-    std::ifstream file (path.c_str ());
-
-    if (!file.good ()) {
-        LOG_ERROR ("Could not open file " + path);
-        return false;
-    }
-
-    while (true) {
-        if (line_num == a_line_number) {
-            found_line = true;
-            break;
-        }
-        file.get (c);
-        if (!file.good ())
-            break;
-        if (c == '\n')
-            ++line_num;
-    }
-    if (found_line) {
-        a_line.clear ();
-        while (true) {
-            file.get (c);
-            if (!file.good ())
-                break;
-            if (c == '\n')
-                break;
-            a_line += c;
-        }
-    }
-    file.close ();
-
-    NEMIVER_CATCH
-
-    return found_line;
-}
-
-bool
-DBGPerspective::write_asm_instr (std::ostringstream &a_os,
-                                 const common::AsmInstr &a_instr)
-{
-    a_os << a_instr.address ();
-    a_os << "  ";
-    a_os << "<" << a_instr.function ();
-    if (!a_instr.offset ().empty () && a_instr.offset () != "0")
-        a_os << "+" << a_instr.offset ();
-    a_os << ">:  ";
-    a_os << a_instr.instruction ();
-
-    return true;
-}
-
-bool
-DBGPerspective::write_asm_instr (std::ostringstream &a_os,
-                                 const common::Asm &a_asm)
-{
-    bool written = false;
-
-    switch (a_asm.which ()) {
-        case common::Asm::TYPE_PURE:
-            write_asm_instr (a_os, a_asm.instr ());
-            written = true;
-            break;
-        case common::Asm::TYPE_MIXED: {
-            const common::MixedAsmInstr &instr = a_asm.mixed_instr ();
-            // Ignore requests for line 0. Line 0 cannot exist as lines
-            // should be starting at 1., some
-            // versions of GDB seem to be referencing it for a reason.
-            if (instr.line_number () == 0) {
-                LOG_DD ("Skipping asm instr at line 0");
-                return false;
-            }
-            string line;
-            if (read_file_line (instr.file_path (),
-                                instr.line_number (),
-                                line)) {
-                if (line.empty ())
-                    a_os << "\n";
-                else {
-                    a_os << line; // line does not end with a '\n' char.
-                    written = true;
-                }
-            } else {
-                a_os << "<src file=\""
-                         << instr.file_path ()
-                         << "\" line=\""
-                         << instr.line_number ()
-                         << "\"/>";
-                written = true;
-            }
-
-            if (!instr.instrs ().empty ()) {
-                list<common::AsmInstr>::const_iterator it =
-                                                instr.instrs ().begin ();
-                if (it != instr.instrs ().end ()) {
-                    if (written)
-                        a_os << "\n";
-                    written = write_asm_instr (a_os, *it);
-                    ++it;
-                }
-                for (; it != instr.instrs ().end (); ++it) {
-                    if (written)
-                        a_os << "\n";
-                    written = write_asm_instr (a_os, *it);
-                }
-            }
-        }
-            break;
-        default:
-            break;
-    }
-    return written;
-}
-
-bool
-DBGPerspective::add_asm (const common::DisassembleInfo &/*a_info*/,
-                         const std::list<common::Asm> &a_asm,
-                         Glib::RefPtr<SourceBuffer> &a_buf,
-                         bool a_append)
-{
-    LOG_FUNCTION_SCOPE_NORMAL_DD;
-
-    if (!a_buf)
-        return false;
-
-    log_asm_insns (a_asm);
-
-    std::list<common::Asm>::const_iterator it = a_asm.begin ();
-    if (it == a_asm.end ())
-        return true;
-
-    // Write the first asm instruction into a string stream.
-    std::ostringstream first_os, endl_os;
-    bool first_written = write_asm_instr (first_os, *it);
-    endl_os << std::endl;
-
-    // Figure out where to insert the asm instrs, depending on a_append
-    // (either prepend or append it)
-    // Also, if a_buf is not empty and we are going to append asm
-    // instrs, make sure to add an "end line" before appending our asm
-    // instrs.
-    Gtk::TextBuffer::iterator insert_it;
-    if (a_append) {
-        insert_it = a_buf->end ();
-        if (a_buf->get_char_count () != 0) {
-            insert_it = a_buf->insert (insert_it, endl_os.str ());
-        }
-    } else {
-        insert_it = a_buf->begin ();
-    }
-    // Really insert the the first asm instrs.
-    if (first_written)
-        insert_it = a_buf->insert (insert_it, first_os.str ());
-
-    // Append the remaining asm instrs. Make sure to add an "end of line"
-    // before each asm instr.
-    bool prev_written = true;
-    for (++it; it != a_asm.end (); ++it) {
-        // If the first item was empty, do not insert "\n" on the first
-        // iteration.
-        if (first_written && prev_written)
-            insert_it = a_buf->insert (insert_it, endl_os.str ());
-        first_written = true;
-        ostringstream os;
-        prev_written = write_asm_instr (os, *it);
-        insert_it = a_buf->insert (insert_it, os.str ());
-    }
-    return true;
-}
-
 // If no asm dedicated tab was already present in the perspective,
 // create  a new one, otherwise reuse the one that was already present.
 // Then load the assembly insns a_asm  described by a_info into the
@@ -6112,7 +5501,12 @@ DBGPerspective::open_asm (const common::DisassembleInfo &a_info,
         source_buffer->erase (source_buffer->begin (), source_buffer->end ());
     }
 
-    if (load_asm (a_info, a_asm, source_buffer) == 0)
+    if (!SourceEditor::load_asm (a_info, a_asm, /*a_append=*/true,
+                                 m_priv->prog_path, m_priv->prog_cwd,
+                                 m_priv->session_search_paths,
+                                 m_priv->global_search_paths,
+                                 m_priv->paths_to_ignore,
+                                 source_buffer))
         return 0;
 
     if (!source_editor)
@@ -6161,12 +5555,16 @@ DBGPerspective::switch_to_asm (const common::DisassembleInfo &a_info,
 
     Glib::RefPtr<SourceBuffer> asm_buf;
     if ((asm_buf = a_source_editor->get_assembly_source_buffer ()) == 0) {
-        setup_buffer_mime_and_lang (asm_buf, "test/x-asm");
+        SourceEditor::setup_buffer_mime_and_lang (asm_buf, "test/x-asm");
         a_source_editor->register_assembly_source_buffer (asm_buf);
         asm_buf = a_source_editor->get_assembly_source_buffer ();
         RETURN_IF_FAIL (asm_buf);
     }
-    if (!load_asm (a_info, a_asm, asm_buf)) {
+    if (!SourceEditor::load_asm (a_info, a_asm, /*a_append=*/true,
+                                 m_priv->prog_path, m_priv->prog_cwd,
+                                 m_priv->session_search_paths,
+                                 m_priv->global_search_paths,
+                                 m_priv->paths_to_ignore, asm_buf)) {
         LOG_ERROR ("failed to load asm");
         return;
     }
@@ -6241,9 +5639,9 @@ DBGPerspective::switch_to_source_code ()
                     << m_priv->current_frame.file_name ());
             return;
         }
-        get_file_mime_type (absolute_path, mime_type);
-        setup_buffer_mime_and_lang (source_buf, mime_type);
-        load_file (absolute_path, source_buf);
+        SourceEditor::get_file_mime_type (absolute_path, mime_type);
+        SourceEditor::setup_buffer_mime_and_lang (source_buf, mime_type);
+        m_priv->load_file (absolute_path, source_buf);
         source_editor->register_non_assembly_source_buffer (source_buf);
     }
     source_editor->switch_to_non_assembly_source_buffer ();
@@ -6342,7 +5740,8 @@ DBGPerspective::reload_file (const UString &a_path)
         editor->source_view ().get_source_buffer ();
     int current_line = editor->current_line ();
     int current_column = editor->current_column ();
-    if (!load_file (a_path, buffer))
+    
+    if (!m_priv->load_file (a_path, buffer))
         return false;
     editor->register_non_assembly_source_buffer (buffer);
     editor->current_line (current_line);
@@ -6415,11 +5814,11 @@ DBGPerspective::execute_session (ISessMgr::Session &a_session)
 
     // populate the list of search paths from the current session
     list<UString>::const_iterator path_iter;
-    m_priv->search_paths.clear();
+    m_priv->session_search_paths.clear();
     for (path_iter = m_priv->session.search_paths ().begin ();
             path_iter != m_priv->session.search_paths ().end ();
             ++path_iter) {
-        m_priv->search_paths.push_back (*path_iter);
+        m_priv->session_search_paths.push_back (*path_iter);
     }
 
     // open the previously opened files
@@ -7161,26 +6560,8 @@ bool
 DBGPerspective::ask_user_to_select_file (const UString &a_file_name,
                                          UString &a_selected_file_path)
 {
-    LocateFileDialog dialog (plugin_path (), a_file_name);
-    // start looking in the working directory
-    dialog.file_location (m_priv->prog_cwd);
-    int result = dialog.run ();
-    if (result == Gtk::RESPONSE_OK) {
-        UString file_path = dialog.file_location ();
-        if (!Glib::file_test (file_path, Glib::FILE_TEST_IS_REGULAR)
-            || (Glib::path_get_basename (a_file_name)
-                != Glib::path_get_basename (file_path)))
-            return false;
-        UString parent_dir =
-            Glib::filename_to_utf8 (Glib::path_get_dirname
-                                                (dialog.file_location ()));
-        if (!Glib::file_test (parent_dir, Glib::FILE_TEST_IS_DIR))
-            return false;
-
-        a_selected_file_path = file_path;
-        return true;
-    }
-    return false;
+    return ui_utils::ask_user_to_select_file (a_file_name, m_priv->prog_cwd,
+                                              a_selected_file_path);
 }
 
 bool
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.h b/src/persp/dbgperspective/nmv-dbg-perspective.h
index dfeb5d6..72d3258 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.h
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.h
@@ -73,10 +73,6 @@ public:
 
     virtual void close_file (const UString &a_uri) = 0;
 
-    virtual bool load_asm (const common::DisassembleInfo &a_info,
-                           const std::list<common::Asm> &a_asm,
-                           Glib::RefPtr<gtksourceview::SourceBuffer> &a_buf) = 0;
-
     virtual Gtk::Widget* load_menu (const UString &a_filename,
                                     const UString &a_widget_name) = 0;
 
diff --git a/src/uicommon/Makefile.am b/src/uicommon/Makefile.am
index f3358b1..9bbe4e9 100644
--- a/src/uicommon/Makefile.am
+++ b/src/uicommon/Makefile.am
@@ -4,6 +4,10 @@ sources = \
 $(public_headers) \
 nmv-ui-utils.h \
 nmv-ui-utils.cc \
+nmv-dialog.cc \
+nmv-dialog.h \
+nmv-locate-file-dialog.cc \
+nmv-locate-file-dialog.h \
 ephy-spinner.c \
 ephy-spinner.h \
 ephy-spinner-tool-item.c \
diff --git a/src/persp/dbgperspective/nmv-dialog.cc b/src/uicommon/nmv-dialog.cc
similarity index 82%
rename from src/persp/dbgperspective/nmv-dialog.cc
rename to src/uicommon/nmv-dialog.cc
index 9c12f25..2f60efb 100644
--- a/src/persp/dbgperspective/nmv-dialog.cc
+++ b/src/uicommon/nmv-dialog.cc
@@ -47,14 +47,25 @@ public:
           const UString &a_glade_filename,
           const UString &a_widget_name)
     {
-        vector<string> path_elems;
-        path_elems.push_back (Glib::locale_from_utf8 (a_resource_root_path));
-        path_elems.push_back ("glade");
-        path_elems.push_back (a_glade_filename);
-        string glade_path = Glib::build_filename (path_elems);
+        string glade_path;
+        if (!a_resource_root_path.empty ()) {
+            // So the glade file is shipped within a plugin. Build the
+            // path to it accordingly.
+            vector<string> path_elems;
+            path_elems.push_back (Glib::locale_from_utf8 (a_resource_root_path));
+            path_elems.push_back ("glade");
+            path_elems.push_back (a_glade_filename);
+            glade_path = Glib::build_filename (path_elems);
+        } else {
+            // THe glade file is shipped into the global nemiver glade
+            // directories.
+            glade_path = env::build_path_to_glade_file (a_glade_filename);
+        }
+
         if (!Glib::file_test (glade_path, Glib::FILE_TEST_IS_REGULAR)) {
             THROW (UString ("could not find file ") + glade_path);
         }
+
         glade = Gnome::Glade::Xml::create (glade_path);
         THROW_IF_FAIL (glade);
         dialog.reset
diff --git a/src/persp/dbgperspective/nmv-dialog.h b/src/uicommon/nmv-dialog.h
similarity index 100%
rename from src/persp/dbgperspective/nmv-dialog.h
rename to src/uicommon/nmv-dialog.h
diff --git a/src/persp/dbgperspective/nmv-locate-file-dialog.cc b/src/uicommon/nmv-locate-file-dialog.cc
similarity index 100%
rename from src/persp/dbgperspective/nmv-locate-file-dialog.cc
rename to src/uicommon/nmv-locate-file-dialog.cc
diff --git a/src/persp/dbgperspective/nmv-locate-file-dialog.h b/src/uicommon/nmv-locate-file-dialog.h
similarity index 100%
rename from src/persp/dbgperspective/nmv-locate-file-dialog.h
rename to src/uicommon/nmv-locate-file-dialog.h
diff --git a/src/uicommon/nmv-source-editor.cc b/src/uicommon/nmv-source-editor.cc
index d1c3ce7..06e0d45 100644
--- a/src/uicommon/nmv-source-editor.cc
+++ b/src/uicommon/nmv-source-editor.cc
@@ -30,9 +30,25 @@
 #include <gtkmm/scrolledwindow.h>
 #include <gtksourceviewmm/sourcemark.h>
 #include <gtksourceviewmm/sourceiter.h>
+#ifdef WITH_SOURCEVIEWMM2
+#include <gtksourceviewmm/sourcelanguagemanager.h>
+#include <gtksourceviewmm/sourcestyleschememanager.h>
+#else
+#include <gtksourceviewmm/sourcelanguagesmanager.h>
+#endif  // WITH_SOURCEVIEWMM2
+#ifdef WITH_GIO
+#include <giomm/file.h>
+#include <giomm/contenttype.h>
+#else
+#include <libgnomevfs/gnome-vfs-mime-utils.h>
+#include <libgnomevfs/gnome-vfs-monitor.h>
+#include <libgnomevfs/gnome-vfs-ops.h>
+#include <libgnomevfs/gnome-vfs-utils.h>
+#endif // WITH_GIO
 #include "common/nmv-exception.h"
 #include "common/nmv-sequence.h"
 #include "common/nmv-str-utils.h"
+#include "common/nmv-asm-utils.h"
 #include "uicommon/nmv-ui-utils.h"
 #include "nmv-source-editor.h"
 
@@ -41,9 +57,10 @@ using namespace nemiver::common;
 using gtksourceview::SourceMark;
 using gtksourceview::SourceIter;
 using gtksourceview::SearchFlags;
+using gtksourceview::SourceLanguage;
+using gtksourceview::SourceLanguageManager;
 
-namespace nemiver
-{
+NEMIVER_BEGIN_NAMESPACE (nemiver)
 
 const char* BREAKPOINT_ENABLED_CATEGORY = "breakpoint-enabled-category";
 const char* BREAKPOINT_DISABLED_CATEGORY = "breakpoint-disabled-category";
@@ -1087,6 +1104,294 @@ SourceEditor::do_search (const UString &a_str,
     return false;
 }
 
+/// Guess the mime type of a file.
+/// \param a_path the path of the file to consider.
+/// \param a_mime_type the resulting mime type, set iff the function
+/// returns true.
+/// \return true upon successful completion, false otherwise.
+bool
+SourceEditor::get_file_mime_type (const UString &a_path,
+                                  UString &a_mime_type)
+{
+    NEMIVER_TRY
+
+    std::string path = Glib::filename_from_utf8 (a_path);
+
+#ifdef WITH_GIO
+    Glib::RefPtr<Gio::File> gio_file = Gio::File::create_for_path (path);
+    THROW_IF_FAIL (gio_file);
+#else
+    UString base_name = Glib::filename_to_utf8 (Glib::path_get_basename (path));
+#endif
+
+    UString mime_type;
+#ifdef WITH_GIO
+    Glib::RefPtr<Gio::FileInfo> info = gio_file->query_info();
+    mime_type = Gio::content_type_get_mime_type(info->get_content_type ());
+#else
+    mime_type = gnome_vfs_get_mime_type_for_name (base_name.c_str ());
+#endif
+
+    if (mime_type == "") {
+        mime_type = "text/x-c++";
+    }
+    LOG_DD ("file has mime type: " << mime_type);
+    a_mime_type = mime_type;
+    return true;
+
+    NEMIVER_CATCH_AND_RETURN (false)
+}
+
+/// Make sure the source buffer a_buf is properly setup to have the
+/// mime type a_mime_type. If a_buf is null, a new one is created.
+/// Returns true upon successful completion, false otherwise.
+bool
+SourceEditor::setup_buffer_mime_and_lang (Glib::RefPtr<SourceBuffer> &a_buf,
+					  const std::string &a_mime_type)
+{
+    NEMIVER_TRY
+
+#ifdef WITH_SOURCEVIEWMM2
+    Glib::RefPtr<SourceLanguageManager> lang_manager =
+        SourceLanguageManager::get_default ();
+#else
+    Glib::RefPtr<SourceLanguagesManager> lang_manager =
+        SourceLanguagesManager::create ();
+#endif  // WITH_SOURCEVIEWMM2
+    Glib::RefPtr<SourceLanguage> lang;
+    #ifdef WITH_SOURCEVIEWMM2
+    std::list<Glib::ustring> lang_ids = lang_manager->get_language_ids ();
+    for (std::list<Glib::ustring>::const_iterator it = lang_ids.begin ();
+         it != lang_ids.end ();
+         ++it) {
+        Glib::RefPtr<gtksourceview::SourceLanguage> candidate = 
+            lang_manager->get_language (*it);
+        std::list<Glib::ustring> mime_types = candidate->get_mime_types ();
+        std::list<Glib::ustring>::const_iterator mime_it;
+        for (mime_it = mime_types.begin ();
+             mime_it != mime_types.end ();
+             ++mime_it) {
+            if (*mime_it == a_mime_type) {
+                // one of the mime types associated with this language matches
+                // the mime type of our file, so use this language
+                lang = candidate;
+                break;  // no need to look at further mime types
+            }
+        }
+        // we found a matching language, so stop looking for other languages
+        if (lang) break;
+    }
+#else
+    lang = lang_manager->get_language_from_mime_type (mime_type);
+#endif  // WITH_SOURCEVIEWMM2
+
+    if (!a_buf)
+        a_buf = SourceBuffer::create (lang);
+    else {
+        a_buf->set_language (lang);
+        a_buf->erase (a_buf->begin (), a_buf->end ());
+    }
+    THROW_IF_FAIL (a_buf);
+    return true;
+
+    NEMIVER_CATCH_AND_RETURN (false);
+}
+
+/// Create a source buffer properly set up to contain/highlight c++
+/// code.
+/// \return the created buffer or nil if something bad happened.
+Glib::RefPtr<SourceBuffer>
+SourceEditor::create_source_buffer ()
+{
+    Glib::RefPtr<SourceBuffer> result;
+    setup_buffer_mime_and_lang (result);
+    return result;
+}
+
+bool
+SourceEditor::load_file (const UString &a_path,
+                         const std::list<std::string> &a_supported_encodings,
+                         bool a_enable_syntax_highlight,
+                         Glib::RefPtr<SourceBuffer> &a_source_buffer)
+{
+    NEMIVER_TRY;
+
+    std::string path = Glib::filename_from_utf8 (a_path);
+#ifdef WITH_GIO
+    Glib::RefPtr<Gio::File> gio_file = Gio::File::create_for_path (path);
+    THROW_IF_FAIL (gio_file);
+    #define FILE_IS_OK (!gio_file->query_exists ())
+#else
+    ifstream file (path.c_str ());
+    #define FILE_IS_OK (!file.good () && !file.eof ())
+
+#endif
+    if (FILE_IS_OK) {
+        LOG_ERROR ("Could not open file " + path);
+        ui_utils::display_error ("Could not open file: "
+                                 + Glib::filename_to_utf8 (path));
+        return false;
+    }
+
+    UString mime_type;
+    if (!get_file_mime_type (path, mime_type)) {
+        LOG_ERROR ("Could not get mime type for " + path);
+        return false;
+    }
+
+    if (!setup_buffer_mime_and_lang (a_source_buffer, mime_type)) {
+        LOG_ERROR ("Could not setup source buffer mime type or language");
+        return false;
+    }
+    THROW_IF_FAIL (a_source_buffer);
+
+    gint buf_size = 10 * 1024;
+    CharSafePtr buf (new gchar [buf_size + 1]);
+    memset (buf.get (), 0, buf_size + 1);
+
+    unsigned nb_bytes=0;
+    std::string content;
+#ifdef WITH_GIO
+    Glib::RefPtr<Gio::FileInputStream> gio_stream = gio_file->read ();
+    THROW_IF_FAIL (gio_stream);
+    gssize bytes_read = 0;
+    for (;;) {
+        bytes_read = gio_stream->read (buf.get (), buf_size);
+        content.append (buf.get (), bytes_read);
+        nb_bytes += bytes_read;
+        if (bytes_read != buf_size) {break;}
+    }
+    gio_stream->close ();
+#else
+    for (;;) {
+        file.read (buf.get (), buf_size);
+        content.append (buf.get (), file.gcount ());
+        THROW_IF_FAIL (file.good () || file.eof ());
+        nb_bytes += file.gcount ();
+        if (file.gcount () != buf_size) {break;}
+    }
+    file.close ();
+#endif // WITH_GIO
+    UString utf8_content;
+    std::string cur_charset;
+    if (!str_utils::ensure_buffer_is_in_utf8 (content,
+                                              a_supported_encodings,
+                                              utf8_content)) {
+        UString msg;
+        msg.printf (_("Could not load file %s because its encoding "
+                      "is different from %s"),
+                    path.c_str (),
+                    cur_charset.c_str ());
+        ui_utils::display_error (msg);
+        return false;
+    }
+    a_source_buffer->set_text (utf8_content);
+    LOG_DD ("file loaded. Read " << (int)nb_bytes << " bytes");
+
+#ifdef WITH_SOURCEVIEWMM2
+    a_source_buffer->set_highlight_syntax (a_enable_syntax_highlight);
+#else
+    a_source_buffer->set_highlight (a_enable_syntax_highlight);
+#endif  // WITH_SOURCEVIEWMM2
+
+    NEMIVER_CATCH_AND_RETURN (false);
+
+    return true;
+}
+
+bool
+SourceEditor::add_asm (const common::DisassembleInfo &/*a_info*/,
+                       const std::list<common::Asm> &a_asm,
+                       bool a_append,
+                       const UString &a_prog_path,
+                       const UString &a_cwd,
+                       list<UString> &a_session_dirs,
+                       const list<UString> &a_glob_dirs,
+                       std::map<UString, bool> &a_ignore_paths,
+                       Glib::RefPtr<SourceBuffer> &a_buf)
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+    if (!a_buf)
+        return false;
+
+    nemiver::common::log_asm_insns (a_asm);
+
+    std::list<common::Asm>::const_iterator it = a_asm.begin ();
+    if (it == a_asm.end ())
+        return true;
+
+    // Write the first asm instruction into a string stream.
+    std::ostringstream first_os, endl_os;
+    ReadLine reader (a_prog_path, a_cwd, a_session_dirs, a_glob_dirs,
+                     a_ignore_paths, &ui_utils::find_file_and_read_line);
+    bool first_written = write_asm_instr (*it, reader, first_os);
+    endl_os << std::endl;
+
+    // Figure out where to insert the asm instrs, depending on a_append
+    // (either prepend or append it)
+    // Also, if a_buf is not empty and we are going to append asm
+    // instrs, make sure to add an "end line" before appending our asm
+    // instrs.
+    Gtk::TextBuffer::iterator insert_it;
+    if (a_append) {
+        insert_it = a_buf->end ();
+        if (a_buf->get_char_count () != 0) {
+            insert_it = a_buf->insert (insert_it, endl_os.str ());
+        }
+    } else {
+        insert_it = a_buf->begin ();
+    }
+    // Really insert the the first asm instrs.
+    if (first_written)
+        insert_it = a_buf->insert (insert_it, first_os.str ());
+
+    // Append the remaining asm instrs. Make sure to add an "end of line"
+    // before each asm instr.
+    bool prev_written = true;
+    for (++it; it != a_asm.end (); ++it) {
+        // If the first item was empty, do not insert "\n" on the first
+        // iteration.
+        if (first_written && prev_written)
+            insert_it = a_buf->insert (insert_it, endl_os.str ());
+        first_written = true;
+        ostringstream os;
+        prev_written = write_asm_instr (*it, reader, os);
+        insert_it = a_buf->insert (insert_it, os.str ());
+    }
+    return true;
+}
+
+bool
+SourceEditor::load_asm (const common::DisassembleInfo &a_info,
+                        const std::list<common::Asm> &a_asm,
+                        bool a_append,
+                        const UString &a_prog_path,
+                        const UString &a_cwd,
+                        list<UString> &a_session_dirs,
+                        const list<UString> &a_glob_dirs,
+                        std::map<UString, bool> &a_ignore_paths,
+                        Glib::RefPtr<SourceBuffer> &a_buf)
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+    NEMIVER_TRY
+
+    std::string mime_type = "text/x-asm";
+    if (!setup_buffer_mime_and_lang (a_buf, mime_type)) {
+        LOG_ERROR ("Could not setup source buffer mime type of language");
+        return false;
+    }
+    THROW_IF_FAIL (a_buf);
+
+    add_asm (a_info, a_asm, a_append, a_prog_path, a_cwd,
+             a_session_dirs, a_glob_dirs, a_ignore_paths,
+             a_buf);
+
+    NEMIVER_CATCH_AND_RETURN (false)
+    return true;
+}
+
 /// Registers a assembly source buffer
 /// \param a_buf the assembly source buffer
 void
@@ -1270,5 +1575,4 @@ SourceEditor::insertion_changed_signal () const
     return m_priv->insertion_changed_signal;
 }
 
-}//end namespace nemiver
-
+NEMIVER_END_NAMESPACE (nemiver)
diff --git a/src/uicommon/nmv-source-editor.h b/src/uicommon/nmv-source-editor.h
index 8a9163d..0c3f2c9 100644
--- a/src/uicommon/nmv-source-editor.h
+++ b/src/uicommon/nmv-source-editor.h
@@ -27,12 +27,14 @@
 
 #include <list>
 #include <functional>
+#include <map>
 #include <gtkmm/box.h>
 #include <gtksourceviewmm/sourceview.h>
 #include "common/nmv-safe-ptr-utils.h"
 #include "common/nmv-ustring.h"
 #include "common/nmv-address.h"
 #include "common/nmv-range.h"
+#include "common/nmv-asm-instr.h"
 
 using gtksourceview::SourceView;
 using gtksourceview::SourceBuffer;
@@ -41,6 +43,7 @@ using nemiver::common::SafePtr;
 using nemiver::common::UString;
 using nemiver::common::Address;
 using std::list;
+using std::map;
 
 namespace nemiver {
 
@@ -105,6 +108,20 @@ public:
                     bool a_search_backwards=false,
                     bool a_clear_selection=false);
 
+    static bool get_file_mime_type (const UString &a_path,
+				    UString &a_mime_type);
+
+    static bool setup_buffer_mime_and_lang (Glib::RefPtr<SourceBuffer> &a_buf,
+					    const std::string &a_mime_type =
+					    "text/x-c++");
+
+    static Glib::RefPtr<SourceBuffer> create_source_buffer ();
+
+    static bool load_file (const UString &a_path,
+			   const std::list<std::string> &a_supported_encodings,
+			   bool a_enable_syntaxt_highlight,
+			   Glib::RefPtr<SourceBuffer> &a_source_buffer);
+
     /// \name Assembly source buffer handling.
     /// @{
 
@@ -148,6 +165,27 @@ public:
     bool remove_visual_breakpoint_from_address (const Address &);
     bool scroll_to_address (const Address &a_address);
 
+    static bool add_asm (const common::DisassembleInfo &/*a_info*/,
+			 const std::list<common::Asm> &a_asm,
+			 bool a_append,
+			 const UString &a_prog_path,
+			 const UString &a_cwd,
+			 list<UString> &a_session_dirs,
+			 const list<UString> &a_glob_dirs,
+			 std::map<UString, bool> &a_ignore_paths,
+			 Glib::RefPtr<SourceBuffer> &a_buf);
+
+    static bool load_asm (const common::DisassembleInfo &/*a_info*/,
+			  const std::list<common::Asm> &a_asm,
+			  bool a_append,
+			  const UString &a_prog_path,
+			  const UString &a_cwd,
+			  list<UString> &a_session_dirs,
+			  const list<UString> &a_glob_dirs,
+			  std::map<UString, bool> &a_ignore_paths,
+			  Glib::RefPtr<SourceBuffer> &a_buf);
+
+
     /// @}
 
     /// \name signals
diff --git a/src/uicommon/nmv-ui-utils.cc b/src/uicommon/nmv-ui-utils.cc
index 0a18ea0..586a680 100644
--- a/src/uicommon/nmv-ui-utils.cc
+++ b/src/uicommon/nmv-ui-utils.cc
@@ -24,9 +24,11 @@
  *
  *See COPYRIGHT file copyright information.
  */
+#include <glib/gi18n.h>
 #include "common/nmv-exception.h"
 #include "nmv-ui-utils.h"
-#include <glib/gi18n.h>
+#include "nmv-locate-file-dialog.h"
+
 
 using namespace nemiver::common;
 
@@ -175,6 +177,115 @@ ask_yes_no_cancel_question (const common::UString &a_message)
     return dialog.run ();
 }
 
+bool
+ask_user_to_select_file (const UString &a_file_name,
+                         const UString &a_default_dir,
+                         UString &a_selected_file_path)
+{
+    LocateFileDialog dialog ("", a_file_name);
+    // start looking in the default directory
+    dialog.file_location (a_default_dir);
+    int result = dialog.run ();
+    if (result == Gtk::RESPONSE_OK) {
+        UString file_path = dialog.file_location ();
+        if (!Glib::file_test (file_path, Glib::FILE_TEST_IS_REGULAR)
+            || (Glib::path_get_basename (a_file_name)
+                != Glib::path_get_basename (file_path)))
+            return false;
+        UString parent_dir =
+            Glib::filename_to_utf8 (Glib::path_get_dirname
+                                                (dialog.file_location ()));
+        if (!Glib::file_test (parent_dir, Glib::FILE_TEST_IS_DIR))
+            return false;
+
+        a_selected_file_path = file_path;
+        return true;
+    }
+    return false;
+}
+
+bool
+find_absolute_path_or_ask_user (const UString& a_file_path,
+                                const UString &a_prog_path,
+                                const UString &a_cwd,
+                                list<UString> &a_session_dirs,
+                                const list<UString> &a_global_dirs,
+                                map<UString, bool> &a_ignore_paths,
+                                bool a_ignore_if_not_found,
+                                UString& a_absolute_path)
+{
+    if (!env::find_file_absolute_or_relative (a_file_path, a_prog_path,
+                                              a_cwd, a_session_dirs, a_global_dirs,
+                                              a_absolute_path)) {
+        if (a_ignore_paths.find (a_file_path)
+            != a_ignore_paths.end ())
+            // We didn't find a_file_path but as we were previously
+            // requested to *not* ask the user to locate it, just
+            // pretend we didn't find the file.
+            return false;
+        if (ask_user_to_select_file (a_file_path, a_cwd, a_absolute_path)) {
+            UString parent_dir =
+                Glib::filename_to_utf8 (Glib::path_get_dirname
+                                        (a_absolute_path));
+            a_session_dirs.push_back (parent_dir);
+        } else {
+            if (a_ignore_if_not_found)
+                // Don't ask the user to locate a_file_path next time.
+                a_ignore_paths[a_file_path] = true;
+            return false;
+        }
+    }
+    return true;
+}
+
+/// Given a file path P and a line number N , reads the line N from P
+/// and return it iff the function returns true. This is useful
+/// e.g. when forging a mixed source/assembly source view, and we want
+/// to display a source line N from a file P.
+///
+/// \param a_file_path the file path to consider. Not necessarily
+/// absolute. If the file is not found, it will be searched for very hard
+/// in many places.
+/// \param a_prog_path the path of to the current program. This can be
+/// useful to search for a_file_path in case we have to search for it
+/// very hard.
+/// \param a_cwd the current working directory. This can be useful to
+/// search for a_file_path.
+/// \param a_sess_dirs a list of directories where to search for if
+/// all other places we searched for failed.
+/// \param a_glob_dirs a list of directories where to seach for if
+/// anything else failed so far.
+/// \param a_ignore_paths a list of file paths to not search for. If
+/// a_file_path is present in these, we will not search for it.
+/// \param a_ignore_if_not_found if true and if we haven't found
+/// a_file_path so far, then add it to a_ignore_paths.
+/// \param a_line_number the line number to consider
+/// \param a_line the string containing the resulting line read, if
+/// and only if the function returned true.
+/// \return true upon successful completion, false otherwise.
+bool
+find_file_and_read_line (const UString &a_file_path,
+                         const UString &a_prog_path,
+                         const UString &a_cwd,
+                         list<UString> &a_sess_dirs,
+                         const list<UString> &a_glob_dirs,
+                         map<UString, bool> &a_ignore_paths,
+                         bool a_ignore_if_not_found,
+                         int a_line_number,
+                         string &a_line)
+{
+    if (a_file_path.empty ())
+        return false;
+
+    UString path;
+    if (!find_absolute_path_or_ask_user (a_file_path, a_prog_path,
+                                         a_cwd, a_sess_dirs, a_glob_dirs,
+                                         a_ignore_paths, a_ignore_if_not_found,
+                                         path))
+        return false;
+
+    return env::read_file_line (path, a_line_number, a_line);
+}
 
 }//end namespace ui_utils
 }//end namespace nemiver
diff --git a/src/uicommon/nmv-ui-utils.h b/src/uicommon/nmv-ui-utils.h
index 3af255b..a627cd6 100644
--- a/src/uicommon/nmv-ui-utils.h
+++ b/src/uicommon/nmv-ui-utils.h
@@ -147,6 +147,29 @@ NEMIVER_API int ask_yes_no_question (const common::UString &a_message,
 
 NEMIVER_API int ask_yes_no_cancel_question (const common::UString &a_message);
 
+NEMIVER_API bool ask_user_to_select_file (const UString &a_file_name,
+                                          const UString &a_default_dir,
+                                          UString &a_selected_file_path);
+
+NEMIVER_API bool find_absolute_path_or_ask_user (const UString& a_file_path,
+                                                 const UString &a_prog_path,
+                                                 const UString &a_cwd,
+                                                 list<UString> &a_sess_dirs,
+                                                 const list<UString> &a_glob_dirs,
+                                                 map<UString, bool> &a_ignore_paths,
+                                                 bool a_ignore_if_not_found,
+                                                 UString& a_absolute_path);
+
+bool find_file_and_read_line (const UString &a_file_path,
+                              const UString &a_prog_path,
+                              const UString &a_cwd,
+                              list<UString> &a_sess_dirs,
+                              const list<UString> &a_glob_dirs,
+                              map<UString, bool> &a_ignore_paths,
+                              bool a_ignore_if_not_found,
+                              int a_line_number,
+                              string &a_line);
+
 template <class T>
 T*
 get_widget_from_glade (const Glib::RefPtr<Gnome::Glade::Xml> &a_glade,
diff --git a/tests/test-disassemble.cc b/tests/test-disassemble.cc
index 4e5ba4b..6210c24 100644
--- a/tests/test-disassemble.cc
+++ b/tests/test-disassemble.cc
@@ -29,8 +29,8 @@
 #include <glibmm.h>
 #include "common/nmv-initializer.h"
 #include "common/nmv-safe-ptr-utils.h"
+#include "common/nmv-asm-utils.h"
 #include "nmv-i-debugger.h"
-#include "nmv-asm-utils.h"
 #include "nmv-dbg-common.h"
 
 using namespace nemiver;
diff --git a/tests/test-gdbmi.cc b/tests/test-gdbmi.cc
index f78d01b..ffbcaf7 100644
--- a/tests/test-gdbmi.cc
+++ b/tests/test-gdbmi.cc
@@ -3,9 +3,9 @@
 #include <map>
 #include <boost/test/unit_test.hpp>
 #include "dbgengine/nmv-gdbmi-parser.h"
-#include "dbgengine/nmv-asm-utils.h"
 #include "common/nmv-exception.h"
 #include "common/nmv-initializer.h"
+#include "common/nmv-asm-utils.h"
 
 using namespace std;
 using namespace nemiver;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]