[dasher] RM dasher_({in, ex}ternal_)buffer(_set) by combining into editor_{in, ex}ternal



commit cf645eb72821e5b737cfba3f182f31e6d143e0df
Author: Alan Lawrence <acl33 inf phy cam ac uk>
Date:   Sun Mar 20 23:10:08 2011 +0000

    RM dasher_({in,ex}ternal_)buffer(_set) by combining into editor_{in,ex}ternal
    
    Extra buffer methods edit_{move,delete,convert,protect} added to editor
      (others subsumed e.g. buffer insert into editor output)
    
    dasher_main convert/protect callbacks now functional, when the appropriate
     signals are emitted by the GtkDasherControl they call the editor method.
    
    TODO editor_{in,ex}ternal duplicate handle_control decoding of event ids
    TODO ATSPI focus-listener misses many changes in focus, is there a better way?

 Src/Gtk2/Makefile.am                |    6 -
 Src/Gtk2/dasher_buffer_set.cpp      |   97 ---------
 Src/Gtk2/dasher_buffer_set.h        |   54 -----
 Src/Gtk2/dasher_editor.cpp          |   26 +++-
 Src/Gtk2/dasher_editor.h            |   29 +++-
 Src/Gtk2/dasher_editor_external.cpp |  298 +++++++++++++++++++++------
 Src/Gtk2/dasher_editor_internal.cpp |  331 +++++++++++++++++++++++--------
 Src/Gtk2/dasher_editor_internal.h   |    5 -
 Src/Gtk2/dasher_external_buffer.cpp |  346 -------------------------------
 Src/Gtk2/dasher_external_buffer.h   |   32 ---
 Src/Gtk2/dasher_internal_buffer.cpp |  384 -----------------------------------
 Src/Gtk2/dasher_internal_buffer.h   |   37 ----
 Src/Gtk2/dasher_main.cpp            |   26 +--
 13 files changed, 550 insertions(+), 1121 deletions(-)
---
diff --git a/Src/Gtk2/Makefile.am b/Src/Gtk2/Makefile.am
index c083573..5e91924 100644
--- a/Src/Gtk2/Makefile.am
+++ b/Src/Gtk2/Makefile.am
@@ -66,18 +66,12 @@ libdashergtk_la_SOURCES = \
 		dasher_action_keyboard_maemo.h \
 		dasher_action_script.cpp \
 		dasher_action_script.h \
-		dasher_buffer_set.cpp \
-		dasher_buffer_set.h \
 		dasher_editor.cpp \
 		dasher_editor.h \
 		dasher_editor_external.cpp \
 		dasher_editor_external.h \
 		dasher_editor_internal.cpp \
 		dasher_editor_internal.h \
-		dasher_external_buffer.cpp \
-		dasher_external_buffer.h \
-		dasher_internal_buffer.cpp \
-		dasher_internal_buffer.h \
 		dasher_lock_dialogue.cpp \
 		dasher_lock_dialogue.h \
 		dasher_maemo_helper.cpp \
diff --git a/Src/Gtk2/dasher_editor.cpp b/Src/Gtk2/dasher_editor.cpp
index ef30fdb..d11fead 100644
--- a/Src/Gtk2/dasher_editor.cpp
+++ b/Src/Gtk2/dasher_editor.cpp
@@ -32,8 +32,6 @@
 #include "dasher_action_script.h"
 #endif
 #include "dasher_editor.h"
-#include "dasher_external_buffer.h"
-#include "dasher_internal_buffer.h"
 #include "dasher_lock_dialogue.h"
 #include "dasher_main.h"
 //#include "game_mode_helper.h"
@@ -140,6 +138,10 @@ dasher_editor_class_init(DasherEditorClass *pClass) {
   pClass->end_compose = NULL;
   pClass->get_context = NULL;
   pClass->get_offset = NULL;
+  pClass->edit_move = NULL;
+  pClass->edit_delete = NULL;
+  pClass->edit_convert = NULL;
+  pClass->edit_protect = NULL;
   pClass->handle_parameter_change = NULL;
   pClass->handle_stop = NULL;
   pClass->handle_start = NULL;
@@ -305,6 +307,26 @@ dasher_editor_get_offset(DasherEditor *pSelf) {
     return 0;
 }
 
+void dasher_editor_edit_move(DasherEditor *pSelf, gint iDirection, gint iDist) {
+ if(DASHER_EDITOR_GET_CLASS(pSelf)->edit_move)
+    DASHER_EDITOR_GET_CLASS(pSelf)->edit_move(pSelf,iDirection,iDist);
+}
+
+void dasher_editor_edit_delete(DasherEditor *pSelf, gint iDirection, gint iDist) {
+ if(DASHER_EDITOR_GET_CLASS(pSelf)->edit_delete)
+    DASHER_EDITOR_GET_CLASS(pSelf)->edit_delete(pSelf, iDirection, iDist);
+}
+
+void dasher_editor_edit_convert(DasherEditor *pSelf) {
+ if(DASHER_EDITOR_GET_CLASS(pSelf)->edit_convert)
+    DASHER_EDITOR_GET_CLASS(pSelf)->edit_convert(pSelf);
+}
+
+void dasher_editor_edit_protect(DasherEditor *pSelf) {
+ if(DASHER_EDITOR_GET_CLASS(pSelf)->edit_protect)
+    DASHER_EDITOR_GET_CLASS(pSelf)->edit_protect(pSelf);
+}
+
 gboolean 
 dasher_editor_command(DasherEditor *pSelf, const gchar *szCommand) {
   if(DASHER_EDITOR_GET_CLASS(pSelf)->command)
diff --git a/Src/Gtk2/dasher_editor.h b/Src/Gtk2/dasher_editor.h
index 767dab6..406f700 100644
--- a/Src/Gtk2/dasher_editor.h
+++ b/Src/Gtk2/dasher_editor.h
@@ -6,7 +6,6 @@
 #include <gtk/gtk.h>
 
 #include "dasher_action.h"
-#include "dasher_buffer_set.h"
 
 /* Forward declaration */
 typedef struct _DasherMain DasherMain;
@@ -14,6 +13,19 @@ struct _DasherMain;
 typedef struct _DasherAppSettings DasherAppSettings;
 struct _DasherAppSettings;
 
+// Basic cursor movement commands
+enum {
+  EDIT_FORWARDS, 
+  EDIT_BACKWARDS
+};
+  
+enum {
+  EDIT_CHAR,
+  EDIT_WORD,
+  EDIT_LINE,
+  EDIT_FILE
+};
+
 G_BEGIN_DECLS
 #define DASHER_TYPE_EDITOR            (dasher_editor_get_type())
 #define DASHER_EDITOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), DASHER_TYPE_EDITOR, DasherEditor ))
@@ -62,6 +74,16 @@ struct _DasherEditorClass {
   void (*filename_changed)(DasherEditor *);
   void (*buffer_changed)(DasherEditor *);
   void (*context_changed)(DasherEditor *);
+
+  /* These moved from dasher_buffer_set */
+  //void (*insert_text)(DasherEditor *pSelf, const gchar *szText, int iOffset);// = output
+  //void (*delete_text)(DasherEditor *pSelf, gint iLength, int iOffset);//duplicate
+  //gchar *(*get_context)(DasherEditor *pSelf, gint iOffset, gint iLength);//duplicate
+  void (*edit_move)(DasherEditor *pSelf, gint iDirection, gint iDist);
+  void (*edit_delete)(DasherEditor *pSelf, gint iDirection, gint iDist);
+  void (*edit_convert)(DasherEditor *pSelf);
+  void (*edit_protect)(DasherEditor *pSelf);
+  //gint (*get_offset)(DasherEditor *pSelf);//duplicate
 };
 
 /* Boilerplate code */
@@ -100,6 +122,11 @@ void dasher_editor_end_compose(DasherEditor *pSelf, bool bKeep);
 const gchar *dasher_editor_get_context(DasherEditor *pSelf, int iOffset, int iLength);
 gint dasher_editor_get_offset(DasherEditor *pSelf);
 
+void dasher_editor_edit_move(DasherEditor *pSelf, gint iDirection, gint iDist);
+void dasher_editor_edit_delete(DasherEditor *pSelf, gint iDirection, gint iDist);
+void dasher_editor_edit_convert(DasherEditor *pSelf);
+void dasher_editor_edit_protect(DasherEditor *pSelf);
+
 /* Events proagated from main */
 void dasher_editor_handle_parameter_change(DasherEditor *pSelf, gint iParameter);
 void dasher_editor_handle_stop(DasherEditor *pSelf);
diff --git a/Src/Gtk2/dasher_editor_external.cpp b/Src/Gtk2/dasher_editor_external.cpp
index 0b364de..d41be96 100644
--- a/Src/Gtk2/dasher_editor_external.cpp
+++ b/Src/Gtk2/dasher_editor_external.cpp
@@ -5,19 +5,62 @@
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
 
+#ifdef GNOME_A11Y
+#include <cspi/spi.h>
+#else
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XTest.h>
+#include <gdk/gdkx.h>
+#endif
+
+#include <X11/keysym.h>
+#include <algorithm>
+
 #include "dasher_editor_external.h"
-#include "dasher_external_buffer.h"
 #include "dasher_lock_dialogue.h"
 #include "dasher_main.h"
 #include "../DasherCore/ControlManager.h"
 //#include "game_mode_helper.h"
+#include "DasherSpi.h"
+
+// TODO: Figure out if we need this stuff and re-implement
+
+// X_HAVE_UTF8_STRING -> attempt to do keyboard mapping? (This won't work without extended keysyms being defined) - no or otherwise?
+
+// Before...
+
+//   int min, max;
+//   Display *dpy = gdk_x11_get_default_xdisplay();
+
+// #ifdef X_HAVE_UTF8_STRING
+//   XDisplayKeycodes(dpy, &min, &max);
+//   origkeymap = XGetKeyboardMapping(dpy, min, max - min + 1, &numcodes);
+// #endif
+
+// And after...
+
+// #ifdef X_HAVE_UTF8_STRING
+//   // We want to set the keymap back to whatever it was before,
+//   // if that's possible
+//   int min, max;
+//   Display *dpy = gdk_x11_get_default_xdisplay();
+//   XDisplayKeycodes(dpy, &min, &max);
+//   XChangeKeyboardMapping(dpy, min, numcodes, origkeymap, (max - min));
+// #endif
+
+// ---
 
 typedef struct _DasherEditorExternalPrivate DasherEditorExternalPrivate;
 
 struct _DasherEditorExternalPrivate {
   DasherMain *pDasherMain;
   DasherAppSettings *pAppSettings;
-  IDasherBufferSet *pBufferSet;
+#ifdef GNOME_A11Y
+  AccessibleEventListener *pFocusListener;
+  AccessibleEventListener *pCaretListener;
+  AccessibleText *pAccessibleText;
+#endif
 };
 
 #define DASHER_EDITOR_EXTERNAL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), DASHER_TYPE_EDITOR_EXTERNAL, DasherEditorExternalPrivate))
@@ -35,8 +78,6 @@ static gboolean dasher_editor_external_command(DasherEditor *pSelf, const gchar
 static void dasher_editor_external_initialise(DasherEditor *pSelf, DasherAppSettings *pAppSettings, 
 					      DasherMain *pDasherMain, GtkBuilder *pXML, 
 					      const gchar *szFullPath);
-static void dasher_editor_external_convert(DasherEditor *pSelf);
-static void dasher_editor_external_protect(DasherEditor *pSelf);
 static void dasher_editor_external_create_buffer(DasherEditor *pSelf);
 static void dasher_editor_external_output(DasherEditor *pSelf, const gchar *szText, int iOffset);
 static void dasher_editor_external_delete(DasherEditor *pSelf, int iLength, int iOffset);
@@ -46,11 +87,23 @@ static void dasher_editor_external_handle_control(DasherEditor *pSelf, int iNode
 static void dasher_editor_external_grab_focus(DasherEditor *pSelf);
 static const gchar *dasher_editor_external_get_all_text(DasherEditor *pSelf);
 static const gchar *dasher_editor_external_get_new_text(DasherEditor *pSelf);
+//from dasher_external_buffer:
+static void dasher_editor_external_edit_convert(DasherEditor *pSelf);
+static void dasher_editor_external_edit_protect(DasherEditor *pSelf);
+static void dasher_editor_external_edit_move(DasherEditor *pSelf, int iDirection, int iDist);
+static void dasher_editor_external_edit_delete(DasherEditor *pSelf, int iDirection, int iDist);
+
+#ifdef GNOME_A11Y
+void dasher_editor_external_handle_focus(DasherEditorExternal *pSelf, const AccessibleEvent *pEvent);
+void dasher_editor_external_handle_caret(DasherEditorExternal *pSelf, const AccessibleEvent *pEvent);
+
+void focus_listener(const AccessibleEvent *pEvent, void *pUserData);
+void caret_listener(const AccessibleEvent *pEvent, void *pUserData);
+#endif
 
 /* Callback Declarations */
 
 extern "C" void external_context_changed_handler(GObject *pSource, gpointer pUserData);
-extern "C" void external_buffer_changed_handler(GObject *pSource, gpointer pUserData);
 
 /* Method Definitions */
 
@@ -74,6 +127,10 @@ dasher_editor_external_class_init(DasherEditorExternalClass *pClass) {
   pParentClass->grab_focus = dasher_editor_external_grab_focus;
   pParentClass->get_all_text = dasher_editor_external_get_all_text;
   pParentClass->get_new_text = dasher_editor_external_get_new_text;
+  pParentClass->edit_move = dasher_editor_external_edit_move;
+  pParentClass->edit_delete = dasher_editor_external_edit_delete;
+  pParentClass->edit_convert = dasher_editor_external_edit_convert;
+  pParentClass->edit_protect = dasher_editor_external_edit_protect;
 }
 
 static void 
@@ -82,15 +139,15 @@ dasher_editor_external_init(DasherEditorExternal *pDasherControl) {
 
   pPrivate->pDasherMain = NULL;
   pPrivate->pAppSettings = NULL;
-  pPrivate->pBufferSet = NULL;
 }
 
 static void 
 dasher_editor_external_finalize(GObject *pObject) {
-  DasherEditorExternalPrivate *pPrivate = DASHER_EDITOR_EXTERNAL_GET_PRIVATE(pObject);
-
-  if(pPrivate->pBufferSet)
-    g_object_unref(G_OBJECT(pPrivate->pBufferSet));
+  DasherEditorExternalPrivate *pPrivate = DASHER_EDITOR_EXTERNAL_GET_PRIVATE(DASHER_EDITOR_EXTERNAL(pObject));
+#ifdef GNOME_A11Y
+  SPI_deregisterGlobalEventListener(pPrivate->pFocusListener, "focus:");
+  SPI_deregisterGlobalEventListener(pPrivate->pCaretListener, "object:text-caret-moved");
+#endif
 }
 
 /* Public methods */
@@ -155,14 +212,12 @@ dasher_editor_external_handle_control(DasherEditor *pSelf, int iNodeID) {
     {Dasher::CControlManager::CTL_DELETE_BACKWARD_FILE, EDIT_BACKWARDS, EDIT_FILE, true}
   };    
 
-  if(pPrivate->pBufferSet) {
-    for(unsigned int i(0); i < sizeof(sMap)/sizeof(struct SControlMap); ++i) {
-      if(sMap[i].iEvent == iNodeID) {
-	if(sMap[i].bDelete) 
-	  idasher_buffer_set_edit_delete(pPrivate->pBufferSet, sMap[i].iDir, sMap[i].iDist);
-	else
-	  idasher_buffer_set_edit_move(pPrivate->pBufferSet, sMap[i].iDir, sMap[i].iDist);	
-      }
+  for(unsigned int i(0); i < sizeof(sMap)/sizeof(struct SControlMap); ++i) {
+    if(sMap[i].iEvent == iNodeID) {
+      if(sMap[i].bDelete) 
+        dasher_editor_external_edit_delete(pSelf, sMap[i].iDir, sMap[i].iDist);
+      else
+        dasher_editor_external_edit_move(pSelf, sMap[i].iDir, sMap[i].iDist);	
     }
   }
 }
@@ -176,48 +231,80 @@ static void
 dasher_editor_external_create_buffer(DasherEditor *pSelf) {
   DasherEditorExternalPrivate *pPrivate = DASHER_EDITOR_EXTERNAL_GET_PRIVATE(pSelf);
 
-  if(!(pPrivate->pBufferSet))
-    pPrivate->pBufferSet = IDASHER_BUFFER_SET(dasher_external_buffer_new());
+#ifdef GNOME_A11Y
+
+  if(!initSPI()) {
+    g_message("Could not initialise SPI - accessibility options disabled");
+  } else {
+    pPrivate->pFocusListener = SPI_createAccessibleEventListener(focus_listener, pSelf);
+    pPrivate->pCaretListener = SPI_createAccessibleEventListener(caret_listener, pSelf);
+    
+    // TODO: Need to deregister these on destruction
+    
+    if(pPrivate->pFocusListener && pPrivate->pCaretListener) {
+      SPI_registerGlobalEventListener(pPrivate->pFocusListener, "focus:");
+      SPI_registerGlobalEventListener(pPrivate->pCaretListener, "object:text-caret-moved");
+    } else {
+      g_message("Could not obtain an SPI listener");
+    }
+  }    
 
-  g_signal_connect(G_OBJECT(pPrivate->pBufferSet), "offset_changed", G_CALLBACK(external_context_changed_handler), pSelf);
-  g_signal_connect(G_OBJECT(pPrivate->pBufferSet), "buffer_changed", G_CALLBACK(external_buffer_changed_handler), pSelf);
+  pPrivate->pAccessibleText = 0;
+#endif
 }
 
 static void 
 dasher_editor_external_output(DasherEditor *pSelf, const gchar *szText, int iOffset) {
-  DasherEditorExternalPrivate *pPrivate = DASHER_EDITOR_EXTERNAL_GET_PRIVATE(pSelf);
-
-  if(pPrivate->pBufferSet)
-    idasher_buffer_set_insert(pPrivate->pBufferSet, szText, iOffset);
+  sendText(szText);
 }
 
 static void 
 dasher_editor_external_delete(DasherEditor *pSelf, int iLength, int iOffset) {
-  DasherEditorExternalPrivate *pPrivate = DASHER_EDITOR_EXTERNAL_GET_PRIVATE(pSelf);
-
-  if(pPrivate->pBufferSet)
-    idasher_buffer_set_delete(pPrivate->pBufferSet, iLength, iOffset);
+#ifdef GNOME_A11Y
+  if(!initSPI()) return;
+
+  SPI_generateKeyboardEvent(XK_BackSpace, NULL, SPI_KEY_SYM);
+#else
+  Display *dpy;
+  dpy = gdk_x11_get_default_xdisplay();
+  KeyCode code;
+  code = XKeysymToKeycode(dpy, XK_BackSpace);
+  for(int i = 0; i < iLength; i++) {
+    XTestFakeKeyEvent(dpy, code, True, 0);
+    XTestFakeKeyEvent(dpy, code, False, 0);
+  }
+  XFlush(dpy);
+#endif
 }
 
 static const gchar *
 dasher_editor_external_get_context(DasherEditor *pSelf, int iOffset, int iLength) {
-  // TODO: Check where this function is used
+#ifdef GNOME_A11Y
   DasherEditorExternalPrivate *pPrivate = DASHER_EDITOR_EXTERNAL_GET_PRIVATE(pSelf);
-
-  gchar *szContext;
-
-  if(pPrivate->pBufferSet)
-    szContext = idasher_buffer_set_get_context(pPrivate->pBufferSet, iOffset, iLength);
+  if(pPrivate->pAccessibleText)
+    return AccessibleText_getText(pPrivate->pAccessibleText, iOffset, iOffset + iLength);
   else
-    szContext = "";
-
-  return szContext;
+    return "";
+#else
+  return "";
+#endif
 }
 
 static gint 
 dasher_editor_external_get_offset(DasherEditor *pSelf) {
+#ifdef GNOME_A11Y
   DasherEditorExternalPrivate *pPrivate = DASHER_EDITOR_EXTERNAL_GET_PRIVATE(pSelf);
-  return idasher_buffer_set_get_offset(pPrivate->pBufferSet);
+  
+  if(!pPrivate->pAccessibleText)
+    return 0;
+  if (AccessibleText_getNSelections(pPrivate->pAccessibleText)==0)
+    return AccessibleText_getCaretOffset(pPrivate->pAccessibleText);
+  long int start,end;
+  AccessibleText_getSelection(pPrivate->pAccessibleText, 0, &start, &end);
+  return std::min(start,end);
+#else
+  return 0;
+#endif
 }
 
 static gboolean 
@@ -225,8 +312,6 @@ dasher_editor_external_command(DasherEditor *pSelf, const gchar *szCommand) {
   return FALSE;
 }
 
-
-// TODO: We shouldn't need to know about the buffer here - make this a method of the buffer set
 static const gchar *
 dasher_editor_external_get_all_text(DasherEditor *pSelf) { 
   return "";
@@ -237,37 +322,128 @@ dasher_editor_external_get_new_text(DasherEditor *pSelf) {
   return NULL;
 }
 
+static void 
+dasher_editor_external_edit_convert(DasherEditor *pSelf) {
+}
 
 static void 
-dasher_editor_external_convert(DasherEditor *pSelf) {
-  DasherEditorExternalPrivate *pPrivate = DASHER_EDITOR_EXTERNAL_GET_PRIVATE(pSelf);
+dasher_editor_external_edit_protect(DasherEditor *pSelf) {
+}
 
-  if(pPrivate->pBufferSet)
-    idasher_buffer_set_edit_convert(pPrivate->pBufferSet);
+void dasher_editor_external_edit_move(DasherEditor *pSelf, int iDirection, int iDist) {
+  // TODO: Implement
 }
 
-static void 
-dasher_editor_external_protect(DasherEditor *pSelf) {
+void dasher_editor_external_edit_delete(DasherEditor *pSelf, int iDirection, int iDist) {
+  // TODO: Implement
+}
+
+/* Callback Functions */
+
+#ifdef GNOME_A11Y
+void dasher_editor_external_handle_focus(DasherEditorExternal *pSelf, const AccessibleEvent *pEvent) {
   DasherEditorExternalPrivate *pPrivate = DASHER_EDITOR_EXTERNAL_GET_PRIVATE(pSelf);
 
-  if(pPrivate->pBufferSet)
-    idasher_buffer_set_edit_protect(pPrivate->pBufferSet);
+  //  g_message("Focus");
+  
+  if(pPrivate->pAccessibleText) {
+    AccessibleText_unref(pPrivate->pAccessibleText);
+    pPrivate->pAccessibleText = 0;
+  }
+  
+  Accessible *accessible = pEvent->source;
+  Accessible_ref(accessible);
+  
+  //  g_message("%s", Accessible_getName(accessible));
+  // g_message("%s", Accessible_getRoleName(accessible));
+  //g_message("%s", Accessible_getDescription(accessible));
+
+  if(Accessible_isText(accessible) || Accessible_isEditableText(accessible)) {
+    pPrivate->pAccessibleText = Accessible_getText(accessible);
+    AccessibleText_ref(pPrivate->pAccessibleText);
+
+//     g_iExpectedPosition = AccessibleText_getCaretOffset(pPrivate->pAccessibleText);
+//     g_iOldPosition = g_iExpectedPosition;
+
+    //ACL: in old code, external_buffer emitted signal, for which the editor_external had
+    // registered a callback, which then emitted the same/corresponding signal from the
+    // editor_external; so by combining buffer into editor, seems we don't need any of that
+    // and can just emit the signal from the editor directly. However, the callback also said:
+    //TODO: plumb signal back into control
+    // ...if that makes any sense?
+
+    g_signal_emit_by_name(G_OBJECT(pSelf), "buffer_changed", G_OBJECT(pSelf), NULL, NULL);
+
+  }
+
+  Accessible_unref(accessible);
 }
 
-/* Callback Functions */
+void dasher_editor_external_handle_caret(DasherEditorExternal *pSelf, const AccessibleEvent *pEvent) {
+  //  g_message("Caret");
+ DasherEditorExternalPrivate *pPrivate = DASHER_EDITOR_EXTERNAL_GET_PRIVATE(pSelf);
+
+ //  g_message("Focus");
+  
+  if(pPrivate->pAccessibleText) {
+    AccessibleText_unref(pPrivate->pAccessibleText);
+    pPrivate->pAccessibleText = 0;
+  }
+  
+  Accessible *accessible = pEvent->source;
+  Accessible_ref(accessible);
+  
+  // g_message("%s", Accessible_getName(accessible));
+  //g_message("%s", Accessible_getRoleName(accessible));
+  //g_message("%s", Accessible_getDescription(accessible));
+
+  if(Accessible_isText(accessible) || Accessible_isEditableText(accessible)) {
+    pPrivate->pAccessibleText = Accessible_getText(accessible);
+    AccessibleText_ref(pPrivate->pAccessibleText);
+
+//     g_iExpectedPosition = AccessibleText_getCaretOffset(pPrivate->pAccessibleText);
+//     g_iOldPosition = g_iExpectedPosition;
+
+    //ACL: in old code, dasher_external_buffer emitted offset_changed signal,
+    // picked up by editor_external's external_context_changed_handler,
+    // which just emitted a context_changed signal from the editor_external.
+    // So, just emit that directly:
+    g_signal_emit_by_name(G_OBJECT(pSelf), "context_changed", G_OBJECT(pSelf), NULL, NULL);
+  }
+
+  Accessible_unref(accessible);
+//   Accessible_ref(event->source);
+
+//   AccessibleStateSet *pAStateSet = Accessible_getStateSet(event->source);
+//   AccessibleStateSet_ref(pAStateSet);
 
-extern "C" void 
-external_context_changed_handler(GObject *pSource, gpointer pUserData) {
-  DasherEditorExternal *pSelf = DASHER_EDITOR_EXTERNAL(pUserData);
+//   if(!AccessibleStateSet_contains(pAStateSet, SPI_STATE_FOCUSED)) {
+//     return;
+//   }
 
-  // TODO: plumb signal back into control
-  g_signal_emit_by_name(G_OBJECT(pSelf), "context_changed", G_OBJECT(pSelf), NULL, NULL);
+//   AccessibleStateSet_unref(pAStateSet);
+//   Accessible_unref(event->source);
+  
+//   if(g_pAccessibleText) {
+//     int iActualPosition = event->detail1;
+
+//     std::cout << "Expected: " << g_iExpectedPosition << " Actual: " << iActualPosition << std::endl;
+
+//     if((g_iExpectedPosition - iActualPosition) * (g_iOldPosition - iActualPosition) > 0) {
+//       gtk_dasher_control_invalidate_context(GTK_DASHER_CONTROL(pDasherWidget));
+//       g_iExpectedPosition = iActualPosition;
+//     }
+
+//     g_iOldPosition = iActualPosition;
+//   }
 }
 
-extern "C" void 
-external_buffer_changed_handler(GObject *pSource, gpointer pUserData) {
-  DasherEditorExternal *pSelf = DASHER_EDITOR_EXTERNAL(pUserData);
+void focus_listener(const AccessibleEvent *pEvent, void *pUserData) {
+  dasher_editor_external_handle_focus((DasherEditorExternal *)pUserData, pEvent);
+}
 
-  // TODO: plumb signal back into control
-  g_signal_emit_by_name(G_OBJECT(pSelf), "buffer_changed", G_OBJECT(pSelf), NULL, NULL);
+void caret_listener(const AccessibleEvent *pEvent, void *pUserData) {
+  dasher_editor_external_handle_caret((DasherEditorExternal *)pUserData, pEvent);
 }
+
+#endif
diff --git a/Src/Gtk2/dasher_editor_internal.cpp b/Src/Gtk2/dasher_editor_internal.cpp
index 68de53a..6003d72 100644
--- a/Src/Gtk2/dasher_editor_internal.cpp
+++ b/Src/Gtk2/dasher_editor_internal.cpp
@@ -21,7 +21,6 @@
 #endif
 
 #include "dasher_editor_internal.h"
-#include "dasher_internal_buffer.h"
 #include "dasher_lock_dialogue.h"
 #include "dasher_main.h"
 #include "../DasherCore/ControlManager.h"
@@ -83,27 +82,24 @@ struct _DasherEditorInternalPrivate {
   EditorAction *pActionIter;
   gboolean bActionIterStarted;
   gint iNextActionID;
-  IDasherBufferSet *pBufferSet;
   //  GameModeHelper *pGameModeHelper;
   GtkTextMark *pNewMark;
   DasherAppSettings *pAppSettings;
   gchar *szFilename;
   gboolean bFileModified; // TODO: Make this work properly, export to main for quit etc
-};
-
-#define DASHER_EDITOR_INTERNAL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), DASHER_TYPE_EDITOR_INTERNAL, DasherEditorInternalPrivate))
+  //moved from dasher_internal_buffer:
+  //GtkTextView *pTextView; //duplicate
+  //GtkTextBuffer *pBuffer; //duplicate
+  GtkTextTag *pOutputTag;
+  GtkTextTag *pHiddenTag;
+  GtkTextTag *pVisibleTag;
+  gboolean bConversionMode;
+  gint iLastOffset;
+  gint iCurrentState; // 0 = unconverted, 1 = converted
 
-/* Signals */
-enum {
-  FILENAME_CHANGED,
-  BUFFER_CHANGED,
-  CONTEXT_CHANGED,
-  SIGNAL_NUM
 };
 
-//static guint dasher_editor_internal_signals[SIGNAL_NUM];
-
-static DasherEditorInternal *g_pEditor;
+#define DASHER_EDITOR_INTERNAL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), DASHER_TYPE_EDITOR_INTERNAL, DasherEditorInternalPrivate))
 
 G_DEFINE_TYPE(DasherEditorInternal, dasher_editor_internal, DASHER_TYPE_EDITOR);
 
@@ -141,9 +137,10 @@ static gboolean dasher_editor_internal_unix_vfs_save_file(DasherEditor *pSelf, c
 
 static void dasher_editor_internal_set_filename(DasherEditor *pSelf, const gchar *szFilename);
 
-// TODO: Should these be public?
-static void dasher_editor_internal_convert(DasherEditor *pSelf);
-static void dasher_editor_internal_protect(DasherEditor *pSelf);
+static void dasher_editor_internal_edit_convert(DasherEditor *pSelf);
+static void dasher_editor_internal_edit_protect(DasherEditor *pSelf);
+static void dasher_editor_internal_edit_delete(DasherEditor *pSelf, int iDirection, int iDist);
+static void dasher_editor_internal_edit_move(DasherEditor *pSelf, int iDirection, int iDist);
 
 static void dasher_editor_internal_new_buffer(DasherEditor *pSelf, const gchar *szFilename);
 
@@ -159,6 +156,7 @@ void dasher_editor_internal_output(DasherEditor *pSelf, const gchar *szText, int
 void dasher_editor_internal_delete(DasherEditor *pSelf, int iLength, int iOffset);
 const gchar *dasher_editor_internal_get_context(DasherEditor *pSelf, int iOffset, int iLength);
 gint dasher_editor_internal_get_offset(DasherEditor *pSelf);
+void dasher_editor_internal_mark_changed(DasherEditorInternal *pSelf, GtkTextIter *pIter, GtkTextMark *pMark);
 
 /* Events proagated from main */
 void dasher_editor_internal_handle_stop(DasherEditor *pSelf);
@@ -193,16 +191,13 @@ static void dasher_editor_internal_handle_parameter_change(DasherEditor *pSelf,
 extern "C" void delete_children_callback(GtkWidget *pWidget, gpointer pUserData);
 extern "C" void main_window_realized(DasherMain *pMain, gpointer pUserData);
 extern "C" void action_button_callback(GtkWidget *pWidget, gpointer pUserData);
-extern "C" void context_changed_handler(GObject *pSource, gpointer pUserData);
-extern "C" void buffer_changed_handler(GObject *pSource, gpointer pUserData);
+extern "C" void mark_set_handler(GtkWidget *widget, GtkTextIter *pIter, GtkTextMark *pMark, gpointer pUserData);
 extern "C" void handle_stop_event(GtkDasherControl *pDasherControl, gpointer data);
 extern "C" void on_message(GtkDasherControl *pDasherControl, gpointer pMessageInfo, gpointer pUserData);
 extern "C" void on_command(GtkDasherControl *pDasherControl, gchar *szCommand, gpointer pUserData);
 extern "C" void handle_request_settings(GtkDasherControl * pDasherControl, gpointer data);
 extern "C" void gtk2_edit_delete_callback(GtkDasherControl *pDasherControl, const gchar *szText, int iOffset, gpointer user_data);
 extern "C" void gtk2_edit_output_callback(GtkDasherControl *pDasherControl, const gchar *szText, int iOffset, gpointer user_data);
-extern "C" void convert_cb(GtkDasherControl *pDasherControl, gpointer pUserData);
-extern "C" void protect_cb(GtkDasherControl *pDasherControl, gpointer pUserData);
 
 static void 
 dasher_editor_internal_class_init(DasherEditorInternalClass *pClass) {
@@ -218,6 +213,11 @@ dasher_editor_internal_class_init(DasherEditorInternalClass *pClass) {
   pParentClass->delete_text = dasher_editor_internal_delete;
   pParentClass->get_context = dasher_editor_internal_get_context;
   pParentClass->get_offset = dasher_editor_internal_get_offset;
+  pParentClass->edit_move = dasher_editor_internal_edit_move;
+  pParentClass->edit_delete = dasher_editor_internal_edit_delete;
+  pParentClass->edit_convert = dasher_editor_internal_edit_convert;
+  pParentClass->edit_protect = dasher_editor_internal_edit_protect;
+
   pParentClass->handle_stop = dasher_editor_internal_handle_stop;
   pParentClass->handle_start = dasher_editor_internal_handle_start;
   pParentClass->handle_control = dasher_editor_internal_handle_control;
@@ -244,7 +244,6 @@ dasher_editor_internal_init(DasherEditorInternal *pSelf) {
   pPrivate->pTextView = GTK_TEXT_VIEW(gtk_text_view_new());
     gtk_text_view_set_wrap_mode(pPrivate->pTextView, GTK_WRAP_WORD);
   pPrivate->pBuffer = gtk_text_view_get_buffer(pPrivate->pTextView);
-  pPrivate->pBufferSet = NULL;
   pPrivate->szFilename = NULL;
   pPrivate->pTextClipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
   pPrivate->pPrimarySelection = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
@@ -292,9 +291,6 @@ dasher_editor_internal_finalize(GObject *pObject) {
     }
   }
 
-  if(pPrivate->pBufferSet)
-    g_object_unref(G_OBJECT(pPrivate->pBufferSet));
-
   if(pPrivate->szFilename)
     g_free(pPrivate->szFilename);
 }
@@ -379,11 +375,6 @@ dasher_editor_internal_clipboard(DasherEditor *pSelf, clipboard_action act) {
   delete end;
 }
 
-void dasher_editor_internal_cleartext(DasherEditorInternal *pSelf)
-{
-  dasher_editor_internal_clear((DasherEditor *)pSelf, true);
-}
-
 void 
 dasher_editor_internal_handle_stop(DasherEditor *pSelf) {
   DasherEditorInternalPrivate *pPrivate = DASHER_EDITOR_INTERNAL_GET_PRIVATE(pSelf);
@@ -464,14 +455,12 @@ dasher_editor_internal_handle_control(DasherEditor *pSelf, int iNodeID) {
     {Dasher::CControlManager::CTL_DELETE_BACKWARD_FILE, EDIT_BACKWARDS, EDIT_FILE, true}
   };    
 
-  if(pPrivate->pBufferSet) {
-    for(unsigned int i(0); i < sizeof(sMap)/sizeof(struct SControlMap); ++i) {
-      if(sMap[i].iEvent == iNodeID) {
-	if(sMap[i].bDelete) 
-	  idasher_buffer_set_edit_delete(pPrivate->pBufferSet, sMap[i].iDir, sMap[i].iDist);
-	else
-	  idasher_buffer_set_edit_move(pPrivate->pBufferSet, sMap[i].iDir, sMap[i].iDist);	
-      }
+  for(unsigned int i(0); i < sizeof(sMap)/sizeof(struct SControlMap); ++i) {
+    if(sMap[i].iEvent == iNodeID) {
+      if(sMap[i].bDelete) 
+        dasher_editor_internal_edit_delete(pSelf, sMap[i].iDir, sMap[i].iDist);
+      else
+        dasher_editor_internal_edit_move(pSelf, sMap[i].iDir, sMap[i].iDist);	
     }
   }
 }
@@ -492,8 +481,22 @@ static void
 dasher_editor_internal_clear(DasherEditor *pSelf, gboolean bStore) {
   DasherEditorInternalPrivate *pPrivate = DASHER_EDITOR_INTERNAL_GET_PRIVATE(pSelf);
 
-  if(IS_DASHER_INTERNAL_BUFFER(pPrivate->pBufferSet))
-    dasher_internal_buffer_clear(DASHER_INTERNAL_BUFFER(pPrivate->pBufferSet));
+  GtkTextIter start, end;
+
+  gtk_text_buffer_get_iter_at_offset(pPrivate->pBuffer, &start, 0);
+  gtk_text_buffer_get_iter_at_offset(pPrivate->pBuffer, &end, -1);
+
+  gtk_text_buffer_delete(pPrivate->pBuffer, &start, &end);
+
+  /* TODO: this probably shouldn't emit a signal */
+  //ACL but since it did...internal_buffer emitted "buffer_changed" signal,
+  // which was picked up by callback registered by editor_internal, which
+  // then emitted a "buffer_changed" signal from the editor_internal. So
+  // emit directly from the editor_internal...
+  g_signal_emit_by_name(G_OBJECT(pSelf), "buffer_changed", G_OBJECT(pSelf), NULL, NULL);
+
+  pPrivate->iCurrentState = 0;
+  pPrivate->iLastOffset = 0;
 }
 
 
@@ -587,12 +590,23 @@ static void
 dasher_editor_internal_create_buffer(DasherEditor *pSelf) {
   DasherEditorInternalPrivate *pPrivate = DASHER_EDITOR_INTERNAL_GET_PRIVATE(pSelf);
     
-  if(!(pPrivate->pBufferSet))
-    pPrivate->pBufferSet = IDASHER_BUFFER_SET(dasher_internal_buffer_new(pPrivate->pTextView));
+    
+  pPrivate->pOutputTag = gtk_text_buffer_create_tag(pPrivate->pBuffer, NULL, NULL);
+
+#if GTK_CHECK_VERSION(2,8,0)
+  pPrivate->pHiddenTag = gtk_text_buffer_create_tag(pPrivate->pBuffer, NULL, "invisible", TRUE, NULL);
+#else
+  // TODO: We really ought to do something a little more sensible with conversion in GTK < 2.8
+  pPrivate->pHiddenTag = gtk_text_buffer_create_tag(pPrivate->pBuffer, NULL, NULL);
+#endif
+
+  pPrivate->pVisibleTag = gtk_text_buffer_create_tag(pPrivate->pBuffer, NULL, "foreground", "red", NULL);
+
+  pPrivate->bConversionMode = FALSE;
+  pPrivate->iLastOffset = 1;
+  pPrivate->iCurrentState = 0;
 
-  // TODO: Fix this
-  g_signal_connect(G_OBJECT(pPrivate->pBufferSet), "offset_changed", G_CALLBACK(context_changed_handler), pSelf);
-  g_signal_connect(G_OBJECT(pPrivate->pBufferSet), "buffer_changed", G_CALLBACK(buffer_changed_handler), pSelf);
+  g_signal_connect(G_OBJECT(pPrivate->pBuffer), "mark-set", G_CALLBACK(mark_set_handler), pSelf);
 }
 
 void 
@@ -617,8 +631,39 @@ dasher_editor_internal_output(DasherEditor *pSelf, const gchar *szText, int iOff
     }
   }
 
-  if(pPrivate->pBufferSet)
-    idasher_buffer_set_insert(pPrivate->pBufferSet, szText, iOffset);
+  //  std::cout << "i: " << szText << " (" << iOffset << " " << gtk_text_buffer_get_char_count(pPrivate->pBuffer) << ")" << std::endl;
+
+  // This seems overzealous.
+  // DASHER_ASSERT(gtk_text_buffer_get_char_count(pPrivate->pBuffer) == iOffset);
+
+  gtk_text_buffer_delete_selection(pPrivate->pBuffer, false, true );
+
+  GtkTextIter sIter;
+  gtk_text_buffer_get_iter_at_mark(pPrivate->pBuffer, &sIter, gtk_text_buffer_get_insert(pPrivate->pBuffer));
+
+  GtkTextTag *pCurrentTag = NULL;
+
+  if(!pPrivate->bConversionMode)
+    pCurrentTag = pPrivate->pOutputTag;
+  else {
+    switch(pPrivate->iCurrentState) {
+    case 0:
+      pCurrentTag = pPrivate->pVisibleTag;
+      break;
+    case 1:
+      pCurrentTag = pPrivate->pOutputTag;
+      break;
+    }
+  }
+
+  if(!pCurrentTag)
+    return;
+
+  gtk_text_buffer_insert_with_tags(pPrivate->pBuffer, &sIter, szText, -1, pCurrentTag, NULL);
+
+  gtk_text_view_scroll_mark_onscreen(pPrivate->pTextView, gtk_text_buffer_get_insert(pPrivate->pBuffer));
+
+  //  g_message("Buffer lenght: %d", gtk_text_buffer_get_char_count(pPrivate->pBuffer));
 
 //   if(pPrivate->pGameModeHelper)
 //     game_mode_helper_output(pPrivate->pGameModeHelper, szText);
@@ -629,9 +674,18 @@ dasher_editor_internal_output(DasherEditor *pSelf, const gchar *szText, int iOff
 void 
 dasher_editor_internal_delete(DasherEditor *pSelf, int iLength, int iOffset) {
   DasherEditorInternalPrivate *pPrivate = DASHER_EDITOR_INTERNAL_GET_PRIVATE(pSelf);
+  
+  GtkTextIter end;
+
+  gtk_text_buffer_get_iter_at_mark(pPrivate->pBuffer, &end, gtk_text_buffer_get_insert(pPrivate->pBuffer));
+
+  GtkTextIter start = end;
 
-  if(pPrivate->pBufferSet)
-    idasher_buffer_set_delete(pPrivate->pBufferSet, iLength, iOffset);
+  gtk_text_iter_backward_chars(&start, iLength);
+  //  g_bIgnoreCursorMove = true;
+  gtk_text_buffer_delete(pPrivate->pBuffer, &start, &end);
+  gtk_text_view_scroll_mark_onscreen(pPrivate->pTextView, gtk_text_buffer_get_insert(pPrivate->pBuffer));
+  //  g_bIgnoreCursorMove = false;
 
 //   if(pPrivate->pGameModeHelper)
 //     game_mode_helper_delete(pPrivate->pGameModeHelper, iLength);
@@ -641,28 +695,39 @@ dasher_editor_internal_delete(DasherEditor *pSelf, int iLength, int iOffset) {
 
 const gchar *
 dasher_editor_internal_get_context(DasherEditor *pSelf, int iOffset, int iLength) {
-  // TODO: Check where this function is used
   DasherEditorInternalPrivate *pPrivate = DASHER_EDITOR_INTERNAL_GET_PRIVATE(pSelf);
 
-  const gchar *szContext;
+  //  g_message("Buffer lenght: %d", gtk_text_buffer_get_char_count(pPrivate->pBuffer));
 
-  if(pPrivate->pBufferSet)
-    szContext = idasher_buffer_set_get_context(pPrivate->pBufferSet, iOffset, iLength);
-  else
-    szContext = "";
+  GtkTextIter start;
+  GtkTextIter end; // Refers to end of context, which is start of selection!
+
+  gtk_text_buffer_get_iter_at_offset(pPrivate->pBuffer, &start, iOffset);
+  gtk_text_buffer_get_iter_at_offset(pPrivate->pBuffer, &end, iOffset + iLength);
 
-  // TODO: reimplement
-//   if(szContext && (strlen(szContext) > 0))
-//     gtk_dasher_control_set_context( GTK_DASHER_CONTROL(pDasherWidget), szContext );
-  return szContext;
+  return gtk_text_buffer_get_text( pPrivate->pBuffer, &start, &end, false );
 }
 
 gint 
 dasher_editor_internal_get_offset(DasherEditor *pSelf) {
   DasherEditorInternalPrivate *pPrivate = DASHER_EDITOR_INTERNAL_GET_PRIVATE(pSelf);
-  return idasher_buffer_set_get_offset(pPrivate->pBufferSet);
+  GtkTextIter iter1,iter2;
+  gtk_text_buffer_get_iter_at_mark(pPrivate->pBuffer, &iter1, gtk_text_buffer_get_insert(pPrivate->pBuffer));
+  gtk_text_buffer_get_iter_at_mark(pPrivate->pBuffer, &iter2, gtk_text_buffer_get_selection_bound(pPrivate->pBuffer));
+  return std::min(gtk_text_iter_get_offset(&iter1),gtk_text_iter_get_offset(&iter2));
+}
+
+void dasher_editor_internal_mark_changed(DasherEditorInternal *pSelf, GtkTextIter *pIter, GtkTextMark *pMark) {
+  const char *szMarkName(gtk_text_mark_get_name(pMark));
+  if(szMarkName && !strcmp(szMarkName,"insert")) {
+    //ACL: used to emit "offset_changed" signal from buffer, which was picked up
+    // by a callback registered by editor_internal, which then emitted a context_changed
+    // signal from the editor_internal. So just emit the context_changed directly...
+    g_signal_emit_by_name(G_OBJECT(pSelf), "context_changed", G_OBJECT(pSelf), NULL, NULL);
+  }
 }
 
+
 static void 
 dasher_editor_internal_generate_filename(DasherEditor *pSelf) {
   DasherEditorInternalPrivate *pPrivate = DASHER_EDITOR_INTERNAL_GET_PRIVATE(pSelf);
@@ -1571,21 +1636,137 @@ dasher_editor_internal_set_filename(DasherEditor *pSelf, const gchar *szFilename
 }
 
 static void 
-dasher_editor_internal_convert(DasherEditor *pSelf) {
+dasher_editor_internal_edit_convert(DasherEditor *pSelf) {
   DasherEditorInternalPrivate *pPrivate = DASHER_EDITOR_INTERNAL_GET_PRIVATE(pSelf);
 
-  if(pPrivate->pBufferSet)
-    idasher_buffer_set_edit_convert(pPrivate->pBufferSet);
+  if(!(pPrivate->bConversionMode))
+    return;
+
+  GtkTextIter sStartIter;
+  GtkTextIter sEndIter;
+  gtk_text_buffer_get_iter_at_offset(pPrivate->pBuffer, &sStartIter, pPrivate->iLastOffset);
+  gtk_text_buffer_get_iter_at_offset(pPrivate->pBuffer, &sEndIter, -1);
+  gtk_text_buffer_apply_tag(pPrivate->pBuffer, pPrivate->pHiddenTag, &sStartIter, &sEndIter);
+
+  pPrivate->iCurrentState = 1;
+  pPrivate->iLastOffset = gtk_text_buffer_get_char_count(pPrivate->pBuffer);
 }
 
 static void 
-dasher_editor_internal_protect(DasherEditor *pSelf) {
+dasher_editor_internal_edit_protect(DasherEditor *pSelf) {
+  DasherEditorInternalPrivate *pPrivate = DASHER_EDITOR_INTERNAL_GET_PRIVATE(pSelf);
+
+  if(!(pPrivate->bConversionMode))
+    return;
+
+  pPrivate->iCurrentState = 0;
+  pPrivate->iLastOffset = gtk_text_buffer_get_char_count(pPrivate->pBuffer);
+}
+
+static void
+dasher_editor_internal_edit_delete(DasherEditor *pSelf, int iDirection, int iDist) { 
   DasherEditorInternalPrivate *pPrivate = DASHER_EDITOR_INTERNAL_GET_PRIVATE(pSelf);
+  
+  GtkTextIter sPosStart;
+  GtkTextIter sPosEnd;
+
+  gtk_text_buffer_get_iter_at_mark(pPrivate->pBuffer, &sPosStart, gtk_text_buffer_get_insert(pPrivate->pBuffer));
+
+  sPosEnd = sPosStart;
+  
+  if(iDirection == EDIT_FORWARDS) {
+    switch(iDist) {
+    case EDIT_CHAR:
+      gtk_text_iter_forward_char(&sPosStart);
+      break;
+    case EDIT_WORD:
+      gtk_text_iter_forward_word_end(&sPosStart);
+      break;
+    case EDIT_LINE:
+      if(!gtk_text_view_forward_display_line_end(GTK_TEXT_VIEW(pPrivate->pTextView), &sPosStart))
+      {
+        gtk_text_view_forward_display_line (GTK_TEXT_VIEW(pPrivate->pTextView), &sPosStart);
+        gtk_text_view_forward_display_line_end(GTK_TEXT_VIEW(pPrivate->pTextView), &sPosStart);
+      }
+      break;
+    case EDIT_FILE:
+      gtk_text_iter_forward_to_end(&sPosStart);
+      break;
+    }
+  }
+  else { 
+    switch(iDist) {
+    case EDIT_CHAR:
+      gtk_text_iter_backward_char(&sPosStart);
+      break;
+    case EDIT_WORD:
+      gtk_text_iter_backward_word_start(&sPosStart);
+      break;
+    case EDIT_LINE:
+      if(!gtk_text_view_backward_display_line_start(GTK_TEXT_VIEW(pPrivate->pTextView), &sPosStart))
+        gtk_text_view_backward_display_line(GTK_TEXT_VIEW(pPrivate->pTextView), &sPosStart);
+      break;
+    case EDIT_FILE:
+      gtk_text_buffer_get_start_iter(pPrivate->pBuffer, &sPosStart);
+      break;
+    }
+  }
+
+  gtk_text_buffer_delete(pPrivate->pBuffer, &sPosStart, &sPosEnd);
+  gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(pPrivate->pTextView), gtk_text_buffer_get_insert(pPrivate->pBuffer));
+}
+
+static void
+dasher_editor_internal_edit_move(DasherEditor *pSelf, int iDirection, int iDist) {
+  DasherEditorInternalPrivate *pPrivate = DASHER_EDITOR_INTERNAL_GET_PRIVATE(pSelf);  
+  GtkTextIter sPos;
+
+  gtk_text_buffer_get_iter_at_mark(pPrivate->pBuffer, &sPos, gtk_text_buffer_get_insert(pPrivate->pBuffer));
+  
+  if(iDirection == EDIT_FORWARDS) {
+    switch(iDist) {
+    case EDIT_CHAR:
+      gtk_text_iter_forward_char(&sPos);
+      break;
+    case EDIT_WORD:
+      gtk_text_iter_forward_word_end(&sPos);
+      break;
+    case EDIT_LINE:
+      if(!gtk_text_view_forward_display_line_end(GTK_TEXT_VIEW(pPrivate->pTextView), &sPos))
+      {
+        gtk_text_view_forward_display_line (GTK_TEXT_VIEW(pPrivate->pTextView), &sPos);
+        gtk_text_view_forward_display_line_end(GTK_TEXT_VIEW(pPrivate->pTextView), &sPos);
+      }
+      break;
+    case EDIT_FILE:
+      gtk_text_iter_forward_to_end(&sPos);
+      break;
+    }
+  }
+  else { 
+    switch(iDist) {
+    case EDIT_CHAR:
+      gtk_text_iter_backward_char(&sPos);
+      break;
+    case EDIT_WORD:
+      gtk_text_iter_backward_word_start(&sPos);
+      break;
+    case EDIT_LINE:
+    
+      if(!gtk_text_view_backward_display_line_start(GTK_TEXT_VIEW(pPrivate->pTextView), &sPos))
+        gtk_text_view_backward_display_line(GTK_TEXT_VIEW(pPrivate->pTextView), &sPos);
+      break;
+    case EDIT_FILE:
+      gtk_text_buffer_get_start_iter(pPrivate->pBuffer, &sPos);
+      break;
+    }
+  }
 
-  if(pPrivate->pBufferSet)
-    idasher_buffer_set_edit_protect(pPrivate->pBufferSet);
+  gtk_text_buffer_place_cursor(pPrivate->pBuffer, &sPos);
+  gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(pPrivate->pTextView), gtk_text_buffer_get_insert(pPrivate->pBuffer));
 }
 
+
 static void 
 dasher_editor_internal_new_buffer(DasherEditor *pSelf, const gchar *szFilename) {
   /* TODO: eventually rewrite this without references to external functions */
@@ -1629,24 +1810,10 @@ action_button_callback(GtkWidget *pWidget, gpointer pUserData) {
   dasher_editor_internal_action_button((DasherEditor *)pPointers[0], (DasherAction *)pPointers[1]);
 }
 
-extern "C" void 
-context_changed_handler(GObject *pSource, gpointer pUserData) {
-  DasherEditorInternal *pSelf = DASHER_EDITOR_INTERNAL(pUserData);
-
-  // TODO: plumb signal back into control
-  g_signal_emit_by_name(G_OBJECT(pSelf), "context_changed", G_OBJECT(pSelf), NULL, NULL);
-}
-
-
-extern "C" void 
-buffer_changed_handler(GObject *pSource, gpointer pUserData) {
-  DasherEditorInternal *pSelf = DASHER_EDITOR_INTERNAL(pUserData);
-
-  // TODO: plumb signal back into control
-  g_signal_emit_by_name(G_OBJECT(pSelf), "buffer_changed", G_OBJECT(pSelf), NULL, NULL);
+extern "C" void mark_set_handler(GtkWidget *widget, GtkTextIter *pIter, GtkTextMark *pMark, gpointer pUserData) {
+  dasher_editor_internal_mark_changed(DASHER_EDITOR_INTERNAL(pUserData), pIter, pMark);
 }
 
 
 
 
-
diff --git a/Src/Gtk2/dasher_editor_internal.h b/Src/Gtk2/dasher_editor_internal.h
index 4e610c6..2e7373e 100644
--- a/Src/Gtk2/dasher_editor_internal.h
+++ b/Src/Gtk2/dasher_editor_internal.h
@@ -7,7 +7,6 @@
 
 #include "DasherAppSettings.h"
 #include "dasher_action.h"
-#include "dasher_buffer_set.h"
 #include "dasher_editor.h"
 
 /* Forward declaration */
@@ -49,12 +48,8 @@ struct _DasherEditorInternalClass {
 DasherEditorInternal *dasher_editor_internal_new();
 void dasher_editor_internal_initialise(DasherEditorInternal *pSelf, DasherAppSettings *pAppSettings, DasherMain *pDasherMain, GtkBuilder *pXML, const gchar *szFullPath);
 
-void dasher_editor_internal_cleartext(DasherEditorInternal *pSelf);
 GType dasher_editor_internal_get_type();
 
-/* Replace this with GTK text buffer */
-//IDasherBufferSet *dasher_editor_internal_get_buffer_set(DasherEditorInternal *pSelf);
-
 /* // TODO: Just have one 'handle event' method? */
 /* gboolean dasher_editor_internal_command(DasherEditorInternal *pSelf, const gchar *szCommand); */
 
diff --git a/Src/Gtk2/dasher_main.cpp b/Src/Gtk2/dasher_main.cpp
index 0852e01..ab34718 100644
--- a/Src/Gtk2/dasher_main.cpp
+++ b/Src/Gtk2/dasher_main.cpp
@@ -1432,26 +1432,24 @@ gtk2_edit_output_callback(GtkDasherControl *pDasherControl, const gchar *szText,
   }
 }
 
-// TODO: The following aren't exported from the editor - need to fix this
-
 extern "C" void 
 convert_cb(GtkDasherControl *pDasherControl, gpointer pUserData) {
-//   if(g_pDasherMain) {
-//     DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(g_pDasherMain);
+   if(g_pDasherMain) {
+     DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(g_pDasherMain);
 
-//     if(pPrivate->pEditor) {
-//       dasher_editor_convert(pPrivate->pEditor);
-//     }
-//   }
+     if(pPrivate->pEditor) {
+       dasher_editor_edit_convert(pPrivate->pEditor);
+     }
+   }
 }
 
 extern "C" void 
 protect_cb(GtkDasherControl *pDasherControl, gpointer pUserData) {
-//   if(g_pDasherMain) {
-//     DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(g_pDasherMain);
+   if(g_pDasherMain) {
+     DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(g_pDasherMain);
 
-//     if(pPrivate->pEditor) {
-//       dasher_editor_protect(pPrivate->pEditor);
-//     }
-//   }
+     if(pPrivate->pEditor) {
+       dasher_editor_edit_protect(pPrivate->pEditor);
+     }
+   }
 }



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