diff --git a/IPython/Debugger.py b/IPython/Debugger.py
index 3044e0f..576395c 100644
--- a/IPython/Debugger.py
+++ b/IPython/Debugger.py
@@ -333,6 +333,12 @@ class Pdb(OldPdb):
         #frame, lineno = frame_lineno
         print >>Term.cout, self.format_stack_entry(frame_lineno, '', context)
 
+        # vds: >>
+        frame, lineno = frame_lineno
+        filename = frame.f_code.co_filename
+        __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
+        # vds: <<
+
     def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
         import linecache, repr
         
@@ -496,6 +502,12 @@ class Pdb(OldPdb):
             last = first + 10
         self.print_list_lines(self.curframe.f_code.co_filename, first, last)
 
+        # vds: >>
+        lineno = first
+        filename = self.curframe.f_code.co_filename
+        __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
+        # vds: <<
+
     do_l = do_list
 
     def do_pdef(self, arg):
diff --git a/IPython/Extensions/ipy_synchronize_with.py b/IPython/Extensions/ipy_synchronize_with.py
new file mode 100644
index 0000000..d6222b6
--- /dev/null
+++ b/IPython/Extensions/ipy_synchronize_with.py
@@ -0,0 +1,242 @@
+import IPython.ipapi
+ip = IPython.ipapi.get()
+
+import win32api
+import win32ui
+import win32console
+import dde
+import os
+import scitedirector
+
+# test to write.
+
+def set_hook(synchronize_with_editor):
+    """Set the synchronize with editor hook with a callable object.
+    
+    The callable object will be called with the following arguments when
+    IPython wants to synchronize with you favorite editor:
+    
+     - ip: a running IPython instance.
+     
+     - filename: the path of the file the editor is supposed to display.
+     
+     - lineno : the line number of the line the editor is supposed to
+     highlight.
+     
+     - columnno : the column number of the character the editor is supposed
+     to highlight.
+    """
+    ip.set_hook("synchronize_with_editor", synchronize_with_editor)
+
+
+def find_filename(filename):
+    """Return the filename to synchronize with based on """
+    filename = os.path.splitext(filename)
+    if filename[1] == ".pyc":
+        filename = (filename[0], ".py")
+    filename = "".join(filename)
+
+    if not os.path.isabs(filename):
+        filename = os.path.join(os.getcwd(), filename)
+
+    if os.path.isfile(filename):
+        return filename
+
+    return ""
+
+
+def run_command(path, command, arguments, asynchronous = True):
+    """Run a shell command and return the exit code of the command"""
+    # This is a thin wrapper around os.system that:
+    #  - Let you run command asynchronously.
+    #  - Accept spaces in command path.
+    #  - Dont throw exception if the command don't exist.
+    line = ''
+    if asynchronous:
+        line += 'start '
+        
+    try:
+        line += win32api.GetShortPathName(os.path.join(path, command) + ".exe") + " "
+    except:
+        print 'could not find: "%s"' % (os.path.join(path, command) + ".exe")
+        return -1
+        
+    line += arguments
+    r = os.system(line)
+    return r
+
+
+def sleep(milliseconds):
+    """Wait some milliseconds."""
+    # This is used to make sure the editor did its job before we reset the focus on the console.
+    win32api.Sleep(milliseconds)
+
+
+def restore_console_focus():
+    """Restore the focus to the IPython console."""
+    h = win32console.GetConsoleWindow()
+    console_window = win32ui.CreateWindowFromHandle(h)
+    console_window.SetForegroundWindow()
+    
+
+# This is the most simple example of hook:
+class GVimHook:
+    def __init__(self, path, wakeup_duration):
+        self.path = path
+        self.wakeup_duration = wakeup_duration
+
+    def __call__(self, ip, filename, lineno, columnno):
+        filename = find_filename(filename)
+
+        if not filename:
+            return
+
+        run_command(self.path, 'gvim', '--remote-silent +%d "%s"' % (lineno, filename))
+
+        sleep(self.wakeup_duration)
+
+        restore_console_focus()
+
+
+def gvim(path = r"C:\Program Files\vim\vim71", wakeup_duration = 100):
+    synchronize_with_editor = GVimHook(path, wakeup_duration)
+    set_hook(synchronize_with_editor)
+
+
+class EmacsHook:
+    def __init__(self, path, wakeup_duration, start_duration):
+        self.path = path
+        self.wakeup_duration = wakeup_duration
+        self.start_duration = start_duration
+
+    def __call__(self, ip, filename, lineno, columnno):
+        filename = find_filename(filename)
+
+        if not filename:
+            return
+
+        r = run_command(self.path, "emacsclient", '-n +%d:%d "%s" 2>nul' % (lineno, columnno, filename), False)
+        if r != 0:
+            run_command(self.path, 'runemacs', '--quick -f server-start +%d:%d "%s"' % (lineno, columnno, filename))
+            sleep(self.start_duration)
+        else:
+            sleep(self.wakeup_duration)
+
+        restore_console_focus()
+
+
+def emacs(path = r"C:\Program Files\emacs\bin", wakeup_duration = 100, start_duration = 2000):
+    synchronize_with_editor = EmacsHook(path, wakeup_duration, start_duration)
+    set_hook(synchronize_with_editor)
+
+
+class SciteHook:
+    def __init__(self, path, wakeup_duration, start_duration):
+        self.path = path
+        self.wakeup_duration = wakeup_duration
+        self.start_duration = start_duration
+
+    def __call__(self, ip, filename, lineno, columnno):
+        filename = find_filename(filename)
+
+        if not filename:
+            return
+
+        scites = scitedirector.findWindows()
+        if not scites:
+            run_command(self.path, "scite", '"-open:%s" -goto:%d' % (filename.replace("\\", "/"), lineno))
+
+            sleep(self.start_duration)
+            restore_console_focus()
+        else:
+            scite = scites[0]
+            scitedirector.sendCommand(scite, 'open:%s' % filename.replace("\\", "/"))
+            scitedirector.sendCommand(scite, "goto:%d" % lineno)
+
+
+def scite(path = r"C:\Program Files\SciTE Source Code Editor", wakeup_duration = 100, start_duration = 500):
+    synchronize_with_editor = SciteHook(path, wakeup_duration, start_duration)
+    set_hook(synchronize_with_editor)
+
+
+class NodePadPlusPlusHook:
+    def __init__(self, path, wakeup_duration):
+        self.path = path
+        self.wakeup_duration = wakeup_duration
+
+    def __call__(self, ip, filename, lineno, columnno):
+        filename = find_filename(filename)
+
+        if not filename:
+            return
+
+        run_command(self.path, "notepad++", '"%s" -n%d' % (filename, lineno))
+
+        sleep(self.wakeup_duration)
+
+        restore_console_focus()
+
+
+def notepadplusplus(path = r"C:\Program Files\Notepad++", wakeup_duration = 100):
+    synchronize_with_editor = NodePadPlusPlusHook(path, wakeup_duration)
+    set_hook(synchronize_with_editor)
+
+
+class PsPadHook:
+    def __init__(self, path, wakeup_duration):
+        self.path = path
+        self.wakeup_duration = wakeup_duration
+
+    def __call__(self, ip, filename, lineno, columnno):
+        filename = find_filename(filename)
+
+        if not filename:
+            return
+
+        run_command(self.path, "pspad", '"%s" -%d' % (filename, lineno))
+
+        sleep(self.wakeup_duration)
+
+        restore_console_focus()
+
+
+def pspad(path = r"C:\Program Files\PSPad editor", wakeup_duration = 100):
+    synchronize_with_editor = PsPadHook(path, wakeup_duration)
+    set_hook(synchronize_with_editor)
+
+
+# This is an example of DDE hook:
+class UltraEditHook:
+    def __init__(self, path, wakeup_duration, start_duration):
+        self.path = path
+        self.wakeup_duration = wakeup_duration
+        self.start_duration = start_duration
+
+    def __call__(self, ip, filename, lineno, columnno):
+        filename = find_filename(filename)
+
+        if not filename:
+            return
+
+        server = dde.CreateServer()
+        server.Create("myddeserver")
+        conversation = dde.CreateConversation(server)
+        try:
+            conversation.ConnectTo("uedit32", "System")
+            conversation.Exec(r'[open("%s/%d"])' % (filename, lineno))
+            
+            sleep(self.wakeup_duration)
+        except:
+            run_command(self.path, 'uedit32', '"%s/%d"' % (filename, lineno))
+            
+            sleep(self.start_duration)
+
+        server.Shutdown()
+
+        restore_console_focus()
+
+
+def ultraedit(path = r"C:\Program Files\IDM Computer Solutions\UltraEdit-32", wakeup_duration = 10, start_duration = 2000):
+    synchronize_with_editor = UltraEditHook(path, wakeup_duration, start_duration)
+    set_hook(synchronize_with_editor)
+    
\ No newline at end of file
diff --git a/IPython/Extensions/scitedirector.py b/IPython/Extensions/scitedirector.py
new file mode 100644
index 0000000..97dc6cd
--- /dev/null
+++ b/IPython/Extensions/scitedirector.py
@@ -0,0 +1,26 @@
+import win32api
+import win32gui
+import win32con
+
+import struct
+import array
+
+def findWindows():
+    ret = []
+    sdi = win32api.RegisterWindowMessage("SciTEDirectorInterface")
+    w = win32gui.GetWindow(win32gui.GetDesktopWindow(), win32con.GW_CHILD)
+    while w:
+        res = win32gui.SendMessage(w, sdi, 0, 0)
+        if res == sdi:
+            ret.append(w)
+        w = win32gui.GetWindow(w, win32con.GW_HWNDNEXT)
+
+    return ret
+
+def sendCommand(w, message):
+    CopyDataStruct = "IIP"
+    char_buffer = array.array('c', message)
+    char_buffer_address = char_buffer.buffer_info()[0]
+    char_buffer_size = char_buffer.buffer_info()[1]
+    cds = struct.pack(CopyDataStruct, 0, char_buffer_size, char_buffer_address)
+    win32gui.SendMessage(w, win32con.WM_COPYDATA, 0, cds)
diff --git a/IPython/hooks.py b/IPython/hooks.py
index 777f308..6a67264 100644
--- a/IPython/hooks.py
+++ b/IPython/hooks.py
@@ -53,10 +53,12 @@ from pprint import PrettyPrinter
 
 # List here all the default hooks.  For now it's just the editor functions
 # but over time we'll move here all the public API for user-accessible things.
-__all__ = ['editor', 'fix_error_editor', 'result_display',
+# vds: >>
+__all__ = ['editor', 'fix_error_editor', 'synchronize_with_editor', 'result_display',
            'input_prefilter', 'shutdown_hook', 'late_startup_hook',
            'generate_prompt', 'generate_output_prompt','shell_hook',
            'show_in_pager','pre_prompt_hook', 'pre_runcode_hook']
+# vds: <<
 
 pformat = PrettyPrinter().pformat
 
@@ -107,6 +109,10 @@ def fix_error_editor(self,filename,linenum,column,msg):
     finally:
         t.close()
 
+# vds: >>
+def synchronize_with_editor(self, filename, linenum, column):
+	pass
+# vds: <<
 
 class CommandChainDispatcher:
     """ Dispatch calls to a chain of commands until some func can handle it
diff --git a/IPython/ultraTB.py b/IPython/ultraTB.py
index eb2e579..51a0eee 100644
--- a/IPython/ultraTB.py
+++ b/IPython/ultraTB.py
@@ -490,6 +490,11 @@ class ListTB(TBTools):
                                               Colors.Normal, s))
             else:
                 list.append('%s\n' % str(stype))
+
+        # vds:>>
+        __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
+        # vds:<<
+
         return list
 
     def _some_str(self, value):
@@ -801,6 +806,15 @@ class VerboseTB(TBTools):
             for name in names:
                 value = text_repr(getattr(evalue, name))
                 exception.append('\n%s%s = %s' % (indent, name, value))
+
+        # vds: >>
+        if records:
+             frame, file, lnum, func, lines, index = records[-1]
+             #print "file:", str(file), "linenb", str(lnum)         
+             file = abspath(file)
+             __IPYTHON__.hooks.synchronize_with_editor(file, lnum, 0)
+        # vds: <<
+                
         # return all our info assembled as a single string
         return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )