5 #include "../Common/Common.h"
6 #include "dasher_buffer_set.h"
7 #include "dasher_internal_buffer.h"
9 static void dasher_internal_buffer_class_init(DasherInternalBufferClass
*pClass
);
10 static void dasher_internal_buffer_init(DasherInternalBuffer
*pAction
);
11 static void dasher_internal_buffer_destroy(GObject
*pObject
);
12 static void idasher_buffer_set_interface_init (gpointer g_iface
, gpointer iface_data
);
13 void dasher_internal_buffer_insert(DasherInternalBuffer
*pSelf
, const gchar
*szText
, int iOffset
);
14 void dasher_internal_buffer_delete(DasherInternalBuffer
*pSelf
, int iLength
, int iOffset
);
15 gchar
*dasher_internal_buffer_get_context(DasherInternalBuffer
*pSelf
, gint iOffset
, gint iLength
);
16 void dasher_internal_buffer_edit_move(DasherInternalBuffer
*pSelf
, int iDirection
, int iDist
);
17 void dasher_internal_buffer_edit_delete(DasherInternalBuffer
*pSelf
, int iDirection
, int iDist
);
18 void dasher_internal_buffer_edit_convert(DasherInternalBuffer
*pSelf
);
19 void dasher_internal_buffer_edit_protect(DasherInternalBuffer
*pSelf
);
20 void dasher_internal_buffer_conversion_mode(DasherInternalBuffer
*pSelf
, gboolean bMode
);
21 gint
dasher_internal_buffer_get_offset(DasherInternalBuffer
*pSelf
);
23 // Related signal handlers
24 extern "C" void mark_set_handler(GtkWidget
*widget
, GtkTextIter
*pIter
, GtkTextMark
*pMark
, gpointer pUserData
);
26 typedef struct _DasherInternalBufferPrivate DasherInternalBufferPrivate
;
28 struct _DasherInternalBufferPrivate
{
29 GtkTextView
*pTextView
;
30 GtkTextBuffer
*pBuffer
;
31 GtkTextTag
*pOutputTag
;
32 GtkTextTag
*pHiddenTag
;
33 GtkTextTag
*pVisibleTag
;
34 gboolean bConversionMode
;
36 gint iCurrentState
; // 0 = unconverted, 1 = converted
39 GType
dasher_internal_buffer_get_type() {
41 static GType dasher_internal_buffer_type
= 0;
43 if(!dasher_internal_buffer_type
) {
44 static const GTypeInfo dasher_internal_buffer_info
= {
45 sizeof(DasherInternalBufferClass
),
48 (GClassInitFunc
) dasher_internal_buffer_class_init
,
51 sizeof(DasherInternalBuffer
),
53 (GInstanceInitFunc
) dasher_internal_buffer_init
,
57 static const GInterfaceInfo idasher_buffer_set_info
= {
58 (GInterfaceInitFunc
) idasher_buffer_set_interface_init
,
63 dasher_internal_buffer_type
= g_type_register_static(G_TYPE_OBJECT
, "DasherInternalBuffer", &dasher_internal_buffer_info
, static_cast < GTypeFlags
> (0));
65 g_type_add_interface_static (dasher_internal_buffer_type
,
66 IDASHER_BUFFER_SET_TYPE
,
67 &idasher_buffer_set_info
);
70 return dasher_internal_buffer_type
;
73 static void dasher_internal_buffer_class_init(DasherInternalBufferClass
*pClass
) {
74 GObjectClass
*pObjectClass
= (GObjectClass
*) pClass
;
75 pObjectClass
->finalize
= dasher_internal_buffer_destroy
;
78 static void dasher_internal_buffer_init(DasherInternalBuffer
*pDasherControl
) {
79 pDasherControl
->private_data
= (void *)(new DasherInternalBufferPrivate
);
82 static void idasher_buffer_set_interface_init (gpointer g_iface
, gpointer iface_data
) {
83 IDasherBufferSetInterface
*iface
= (IDasherBufferSetInterface
*)g_iface
;
84 iface
->insert_text
= (void (*)(IDasherBufferSet
*pSelf
, const gchar
*szText
, int iOffset
))dasher_internal_buffer_insert
;
85 iface
->delete_text
= (void (*)(IDasherBufferSet
*pSelf
, gint iLength
, int iOffset
))dasher_internal_buffer_delete
;
86 iface
->get_context
= (gchar
*(*)(IDasherBufferSet
*pSelf
, gint iOffset
, gint iLength
))dasher_internal_buffer_get_context
;
87 iface
->edit_move
= (void (*)(IDasherBufferSet
*pSelf
, gint iDirection
, gint iDist
))dasher_internal_buffer_edit_move
;
88 iface
->edit_delete
= (void (*)(IDasherBufferSet
*pSelf
, gint iDirection
, gint iDist
))dasher_internal_buffer_edit_delete
;
89 iface
->edit_convert
= (void (*)(IDasherBufferSet
*pSelf
))dasher_internal_buffer_edit_convert
;
90 iface
->edit_protect
= (void (*)(IDasherBufferSet
*pSelf
))dasher_internal_buffer_edit_protect
;
91 iface
->conversion_mode
= (void (*)(IDasherBufferSet
*pSelf
, gboolean bMode
))dasher_internal_buffer_conversion_mode
;
92 iface
->get_offset
= (gint (*)(IDasherBufferSet
*pSelf
))dasher_internal_buffer_get_offset
;
95 static void dasher_internal_buffer_destroy(GObject
*pObject
) {
96 // FIXME - I think we need to chain up through the finalize methods
97 // of the parent classes here...
99 delete (DasherInternalBufferPrivate
*)(((DasherInternalBuffer
*)pObject
)->private_data
);
102 DasherInternalBuffer
*dasher_internal_buffer_new(GtkTextView
*pTextView
) {
103 DasherInternalBuffer
*pDasherControl
;
104 pDasherControl
= (DasherInternalBuffer
*)(g_object_new(dasher_internal_buffer_get_type(), NULL
));
106 DasherInternalBufferPrivate
*pPrivate
= (DasherInternalBufferPrivate
*)(pDasherControl
->private_data
);
107 pPrivate
->pTextView
= pTextView
;
108 pPrivate
->pBuffer
= gtk_text_view_get_buffer(pTextView
);
110 pPrivate
->pOutputTag
= gtk_text_buffer_create_tag(pPrivate
->pBuffer
, NULL
, NULL
);
112 #if GTK_CHECK_VERSION(2,8,0)
113 pPrivate
->pHiddenTag
= gtk_text_buffer_create_tag(pPrivate
->pBuffer
, NULL
, "invisible", TRUE
, NULL
);
115 // TODO: We really ought to do something a little more sensible with conversion in GTK < 2.8
116 pPrivate
->pHiddenTag
= gtk_text_buffer_create_tag(pPrivate
->pBuffer
, NULL
, NULL
);
119 pPrivate
->pVisibleTag
= gtk_text_buffer_create_tag(pPrivate
->pBuffer
, NULL
, "foreground", "red", NULL
);
121 pPrivate
->bConversionMode
= FALSE
;
122 pPrivate
->iLastOffset
= 1;
123 pPrivate
->iCurrentState
= 0;
125 g_signal_connect(G_OBJECT(pPrivate
->pBuffer
), "mark-set", G_CALLBACK(mark_set_handler
), pDasherControl
);
127 return pDasherControl
;
130 void dasher_internal_buffer_insert(DasherInternalBuffer
*pSelf
, const gchar
*szText
, int iOffset
) {
131 DasherInternalBufferPrivate
*pPrivate
= (DasherInternalBufferPrivate
*)(pSelf
->private_data
);
133 // std::cout << "i: " << szText << " (" << iOffset << " " << gtk_text_buffer_get_char_count(pPrivate->pBuffer) << ")" << std::endl;
135 DASHER_ASSERT(gtk_text_buffer_get_char_count(pPrivate
->pBuffer
) == iOffset
);
137 gtk_text_buffer_delete_selection(pPrivate
->pBuffer
, false, true );
140 gtk_text_buffer_get_iter_at_mark(pPrivate
->pBuffer
, &sIter
, gtk_text_buffer_get_insert(pPrivate
->pBuffer
));
142 GtkTextTag
*pCurrentTag
= NULL
;
144 if(!pPrivate
->bConversionMode
)
145 pCurrentTag
= pPrivate
->pOutputTag
;
147 switch(pPrivate
->iCurrentState
) {
149 pCurrentTag
= pPrivate
->pVisibleTag
;
152 pCurrentTag
= pPrivate
->pOutputTag
;
160 gtk_text_buffer_insert_with_tags(pPrivate
->pBuffer
, &sIter
, szText
, -1, pCurrentTag
, NULL
);
162 gtk_text_view_scroll_mark_onscreen(pPrivate
->pTextView
, gtk_text_buffer_get_insert(pPrivate
->pBuffer
));
164 // g_message("Buffer lenght: %d", gtk_text_buffer_get_char_count(pPrivate->pBuffer));
167 void dasher_internal_buffer_delete(DasherInternalBuffer
*pSelf
, int iLength
, int iOffset
) {
168 DasherInternalBufferPrivate
*pPrivate
= (DasherInternalBufferPrivate
*)(pSelf
->private_data
);
170 GtkTextIter
*start
= new GtkTextIter
;
171 GtkTextIter
*end
= new GtkTextIter
;
173 gtk_text_buffer_get_iter_at_mark(pPrivate
->pBuffer
, end
, gtk_text_buffer_get_insert(pPrivate
->pBuffer
));
177 gtk_text_iter_backward_chars(start
, iLength
);
178 // g_bIgnoreCursorMove = true;
179 gtk_text_buffer_delete(pPrivate
->pBuffer
, start
, end
);
180 gtk_text_view_scroll_mark_onscreen(pPrivate
->pTextView
, gtk_text_buffer_get_insert(pPrivate
->pBuffer
));
181 // g_bIgnoreCursorMove = false;
186 // std::cout << "d: " << iLength << " (" << iOffset << " " << gtk_text_buffer_get_char_count(pPrivate->pBuffer) << ")" << std::endl;
187 DASHER_ASSERT(gtk_text_buffer_get_char_count(pPrivate
->pBuffer
) == iOffset
);
190 gchar
*dasher_internal_buffer_get_context(DasherInternalBuffer
*pSelf
, gint iOffset
, gint iLength
) {
191 DasherInternalBufferPrivate
*pPrivate
= (DasherInternalBufferPrivate
*)(pSelf
->private_data
);
193 // g_message("Buffer lenght: %d", gtk_text_buffer_get_char_count(pPrivate->pBuffer));
196 GtkTextIter end
; // Refers to end of context, which is start of selection!
198 gtk_text_buffer_get_iter_at_offset(pPrivate
->pBuffer
, &start
, iOffset
);
199 gtk_text_buffer_get_iter_at_offset(pPrivate
->pBuffer
, &end
, iOffset
+ iLength
);
201 return gtk_text_buffer_get_text( pPrivate
->pBuffer
, &start
, &end
, false );
204 // TODO: Check that these signals are being used appropriately
205 void dasher_internal_buffer_change_context(DasherInternalBuffer
*pSelf
, GtkTextIter
*pIter
, GtkTextMark
*pMark
) {
206 const char *szMarkName(gtk_text_mark_get_name(pMark
));
207 if(szMarkName
&& !strcmp(szMarkName
,"insert")) {
208 g_signal_emit_by_name(G_OBJECT(pSelf
), "offset_changed", G_OBJECT(pSelf
), NULL
, NULL
);
212 void dasher_internal_buffer_edit_move(DasherInternalBuffer
*pSelf
, int iDirection
, int iDist
) {
213 DasherInternalBufferPrivate
*pPrivate
= (DasherInternalBufferPrivate
*)(pSelf
->private_data
);
217 gtk_text_buffer_get_iter_at_mark(pPrivate
->pBuffer
, &sPos
, gtk_text_buffer_get_insert(pPrivate
->pBuffer
));
219 if(iDirection
== EDIT_FORWARDS
) {
222 gtk_text_iter_forward_char(&sPos
);
225 gtk_text_iter_forward_word_end(&sPos
);
228 if(!gtk_text_view_forward_display_line_end(GTK_TEXT_VIEW(pPrivate
->pTextView
), &sPos
))
230 gtk_text_view_forward_display_line (GTK_TEXT_VIEW(pPrivate
->pTextView
), &sPos
);
231 gtk_text_view_forward_display_line_end(GTK_TEXT_VIEW(pPrivate
->pTextView
), &sPos
);
235 gtk_text_iter_forward_to_end(&sPos
);
242 gtk_text_iter_backward_char(&sPos
);
245 gtk_text_iter_backward_word_start(&sPos
);
249 if(!gtk_text_view_backward_display_line_start(GTK_TEXT_VIEW(pPrivate
->pTextView
), &sPos
))
250 gtk_text_view_backward_display_line(GTK_TEXT_VIEW(pPrivate
->pTextView
), &sPos
);
253 gtk_text_buffer_get_start_iter(pPrivate
->pBuffer
, &sPos
);
258 gtk_text_buffer_place_cursor(pPrivate
->pBuffer
, &sPos
);
259 gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(pPrivate
->pTextView
), gtk_text_buffer_get_insert(pPrivate
->pBuffer
));
262 void dasher_internal_buffer_edit_delete(DasherInternalBuffer
*pSelf
, int iDirection
, int iDist
) {
263 DasherInternalBufferPrivate
*pPrivate
= (DasherInternalBufferPrivate
*)(pSelf
->private_data
);
265 GtkTextIter sPosStart
;
268 gtk_text_buffer_get_iter_at_mark(pPrivate
->pBuffer
, &sPosStart
, gtk_text_buffer_get_insert(pPrivate
->pBuffer
));
272 if(iDirection
== EDIT_FORWARDS
) {
275 gtk_text_iter_forward_char(&sPosStart
);
278 gtk_text_iter_forward_word_end(&sPosStart
);
281 if(!gtk_text_view_forward_display_line_end(GTK_TEXT_VIEW(pPrivate
->pTextView
), &sPosStart
))
283 gtk_text_view_forward_display_line (GTK_TEXT_VIEW(pPrivate
->pTextView
), &sPosStart
);
284 gtk_text_view_forward_display_line_end(GTK_TEXT_VIEW(pPrivate
->pTextView
), &sPosStart
);
288 gtk_text_iter_forward_to_end(&sPosStart
);
295 gtk_text_iter_backward_char(&sPosStart
);
298 gtk_text_iter_backward_word_start(&sPosStart
);
301 if(!gtk_text_view_backward_display_line_start(GTK_TEXT_VIEW(pPrivate
->pTextView
), &sPosStart
))
302 gtk_text_view_backward_display_line(GTK_TEXT_VIEW(pPrivate
->pTextView
), &sPosStart
);
305 gtk_text_buffer_get_start_iter(pPrivate
->pBuffer
, &sPosStart
);
310 gtk_text_buffer_delete(pPrivate
->pBuffer
, &sPosStart
, &sPosEnd
);
311 gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(pPrivate
->pTextView
), gtk_text_buffer_get_insert(pPrivate
->pBuffer
));
314 void dasher_internal_buffer_edit_convert(DasherInternalBuffer
*pSelf
) {
315 DasherInternalBufferPrivate
*pPrivate
= (DasherInternalBufferPrivate
*)(pSelf
->private_data
);
317 if(!(pPrivate
->bConversionMode
))
320 GtkTextIter sStartIter
;
321 GtkTextIter sEndIter
;
322 gtk_text_buffer_get_iter_at_offset(pPrivate
->pBuffer
, &sStartIter
, pPrivate
->iLastOffset
);
323 gtk_text_buffer_get_iter_at_offset(pPrivate
->pBuffer
, &sEndIter
, -1);
324 gtk_text_buffer_apply_tag(pPrivate
->pBuffer
, pPrivate
->pHiddenTag
, &sStartIter
, &sEndIter
);
326 pPrivate
->iCurrentState
= 1;
327 pPrivate
->iLastOffset
= gtk_text_buffer_get_char_count(pPrivate
->pBuffer
);
330 void dasher_internal_buffer_edit_protect(DasherInternalBuffer
*pSelf
) {
331 DasherInternalBufferPrivate
*pPrivate
= (DasherInternalBufferPrivate
*)(pSelf
->private_data
);
333 if(!(pPrivate
->bConversionMode
))
336 pPrivate
->iCurrentState
= 0;
337 pPrivate
->iLastOffset
= gtk_text_buffer_get_char_count(pPrivate
->pBuffer
);
340 void dasher_internal_buffer_conversion_mode(DasherInternalBuffer
*pSelf
, gboolean bMode
) {
341 DasherInternalBufferPrivate
*pPrivate
= (DasherInternalBufferPrivate
*)(pSelf
->private_data
);
344 pPrivate
->bConversionMode
= TRUE
;
345 pPrivate
->iCurrentState
= 0;
346 pPrivate
->iLastOffset
= gtk_text_buffer_get_char_count(pPrivate
->pBuffer
);
349 pPrivate
->bConversionMode
= FALSE
;
350 pPrivate
->iCurrentState
= 1;
354 void dasher_internal_buffer_clear(DasherInternalBuffer
*pSelf
) {
355 DasherInternalBufferPrivate
*pPrivate
= (DasherInternalBufferPrivate
*)(pSelf
->private_data
);
356 GtkTextIter start
, end
;
358 gtk_text_buffer_get_iter_at_offset(pPrivate
->pBuffer
, &start
, 0);
359 gtk_text_buffer_get_iter_at_offset(pPrivate
->pBuffer
, &end
, -1);
361 gtk_text_buffer_delete(pPrivate
->pBuffer
, &start
, &end
);
363 /* TODO: this probably shouldn't emit a signal */
364 g_signal_emit_by_name(G_OBJECT(pSelf
), "buffer_changed", G_OBJECT(pSelf
), NULL
, NULL
);
366 pPrivate
->iCurrentState
= 0;
367 pPrivate
->iLastOffset
= 0;
370 gint
dasher_internal_buffer_get_offset(DasherInternalBuffer
*pSelf
) {
371 DasherInternalBufferPrivate
*pPrivate
= (DasherInternalBufferPrivate
*)(pSelf
->private_data
);
374 gtk_text_buffer_get_iter_at_mark(pPrivate
->pBuffer
, &oIter
, gtk_text_buffer_get_mark(pPrivate
->pBuffer
, "insert"));
375 return gtk_text_iter_get_offset(&oIter
);
381 extern "C" void mark_set_handler(GtkWidget
*widget
, GtkTextIter
*pIter
, GtkTextMark
*pMark
, gpointer pUserData
) {
382 dasher_internal_buffer_change_context(DASHER_INTERNAL_BUFFER(pUserData
), pIter
, pMark
);