4 #include "dasher_buffer_set.h"
5 #include "dasher_internal_buffer.h"
7 static void dasher_internal_buffer_class_init(DasherInternalBufferClass
*pClass
);
8 static void dasher_internal_buffer_init(DasherInternalBuffer
*pAction
);
9 static void dasher_internal_buffer_destroy(GObject
*pObject
);
10 static void idasher_buffer_set_interface_init (gpointer g_iface
, gpointer iface_data
);
11 void dasher_internal_buffer_insert(DasherInternalBuffer
*pSelf
, const gchar
*szText
);
12 void dasher_internal_buffer_delete(DasherInternalBuffer
*pSelf
, int iLength
);
13 gchar
*dasher_internal_buffer_get_context(DasherInternalBuffer
*pSelf
, gint iOffset
, gint iLength
);
14 void dasher_internal_buffer_edit_move(DasherInternalBuffer
*pSelf
, int iDirection
, int iDist
);
15 void dasher_internal_buffer_edit_delete(DasherInternalBuffer
*pSelf
, int iDirection
, int iDist
);
16 void dasher_internal_buffer_edit_convert(DasherInternalBuffer
*pSelf
);
17 void dasher_internal_buffer_edit_protect(DasherInternalBuffer
*pSelf
);
18 void dasher_internal_buffer_conversion_mode(DasherInternalBuffer
*pSelf
, gboolean bMode
);
19 gint
dasher_internal_buffer_get_offset(DasherInternalBuffer
*pSelf
);
21 // Related signal handlers
22 extern "C" void mark_set_handler(GtkWidget
*widget
, GtkTextIter
*pIter
, GtkTextMark
*pMark
, gpointer pUserData
);
24 typedef struct _DasherInternalBufferPrivate DasherInternalBufferPrivate
;
26 struct _DasherInternalBufferPrivate
{
27 GtkTextView
*pTextView
;
28 GtkTextBuffer
*pBuffer
;
29 GtkTextTag
*pOutputTag
;
30 GtkTextTag
*pHiddenTag
;
31 GtkTextTag
*pVisibleTag
;
32 gboolean bConversionMode
;
34 gint iCurrentState
; // 0 = unconverted, 1 = converted
37 GType
dasher_internal_buffer_get_type() {
39 static GType dasher_internal_buffer_type
= 0;
41 if(!dasher_internal_buffer_type
) {
42 static const GTypeInfo dasher_internal_buffer_info
= {
43 sizeof(DasherInternalBufferClass
),
46 (GClassInitFunc
) dasher_internal_buffer_class_init
,
49 sizeof(DasherInternalBuffer
),
51 (GInstanceInitFunc
) dasher_internal_buffer_init
,
55 static const GInterfaceInfo idasher_buffer_set_info
= {
56 (GInterfaceInitFunc
) idasher_buffer_set_interface_init
,
61 dasher_internal_buffer_type
= g_type_register_static(G_TYPE_OBJECT
, "DasherInternalBuffer", &dasher_internal_buffer_info
, static_cast < GTypeFlags
> (0));
63 g_type_add_interface_static (dasher_internal_buffer_type
,
64 IDASHER_BUFFER_SET_TYPE
,
65 &idasher_buffer_set_info
);
68 return dasher_internal_buffer_type
;
71 static void dasher_internal_buffer_class_init(DasherInternalBufferClass
*pClass
) {
72 GObjectClass
*pObjectClass
= (GObjectClass
*) pClass
;
73 pObjectClass
->finalize
= dasher_internal_buffer_destroy
;
76 static void dasher_internal_buffer_init(DasherInternalBuffer
*pDasherControl
) {
77 pDasherControl
->private_data
= (void *)(new DasherInternalBufferPrivate
);
80 static void idasher_buffer_set_interface_init (gpointer g_iface
, gpointer iface_data
) {
81 IDasherBufferSetInterface
*iface
= (IDasherBufferSetInterface
*)g_iface
;
82 iface
->insert_text
= (void (*)(IDasherBufferSet
*pSelf
, const gchar
*szText
))dasher_internal_buffer_insert
;
83 iface
->delete_text
= (void (*)(IDasherBufferSet
*pSelf
, gint iLength
))dasher_internal_buffer_delete
;
84 iface
->get_context
= (gchar
*(*)(IDasherBufferSet
*pSelf
, gint iOffset
, gint iLength
))dasher_internal_buffer_get_context
;
85 iface
->edit_move
= (void (*)(IDasherBufferSet
*pSelf
, gint iDirection
, gint iDist
))dasher_internal_buffer_edit_move
;
86 iface
->edit_delete
= (void (*)(IDasherBufferSet
*pSelf
, gint iDirection
, gint iDist
))dasher_internal_buffer_edit_delete
;
87 iface
->edit_convert
= (void (*)(IDasherBufferSet
*pSelf
))dasher_internal_buffer_edit_convert
;
88 iface
->edit_protect
= (void (*)(IDasherBufferSet
*pSelf
))dasher_internal_buffer_edit_protect
;
89 iface
->conversion_mode
= (void (*)(IDasherBufferSet
*pSelf
, gboolean bMode
))dasher_internal_buffer_conversion_mode
;
90 iface
->get_offset
= (gint (*)(IDasherBufferSet
*pSelf
))dasher_internal_buffer_get_offset
;
93 static void dasher_internal_buffer_destroy(GObject
*pObject
) {
94 // FIXME - I think we need to chain up through the finalize methods
95 // of the parent classes here...
97 delete (DasherInternalBufferPrivate
*)(((DasherInternalBuffer
*)pObject
)->private_data
);
100 DasherInternalBuffer
*dasher_internal_buffer_new(GtkTextView
*pTextView
) {
101 DasherInternalBuffer
*pDasherControl
;
102 pDasherControl
= (DasherInternalBuffer
*)(g_object_new(dasher_internal_buffer_get_type(), NULL
));
104 DasherInternalBufferPrivate
*pPrivate
= (DasherInternalBufferPrivate
*)(pDasherControl
->private_data
);
105 pPrivate
->pTextView
= pTextView
;
106 pPrivate
->pBuffer
= gtk_text_view_get_buffer(pTextView
);
108 pPrivate
->pOutputTag
= gtk_text_buffer_create_tag(pPrivate
->pBuffer
, NULL
, NULL
);
110 #if GTK_CHECK_VERSION(2,8,0)
111 pPrivate
->pHiddenTag
= gtk_text_buffer_create_tag(pPrivate
->pBuffer
, NULL
, "invisible", TRUE
, NULL
);
113 // TODO: We really ought to do something a little more sensible with conversion in GTK < 2.8
114 pPrivate
->pHiddenTag
= gtk_text_buffer_create_tag(pPrivate
->pBuffer
, NULL
, NULL
);
117 pPrivate
->pVisibleTag
= gtk_text_buffer_create_tag(pPrivate
->pBuffer
, NULL
, "foreground", "red", NULL
);
119 pPrivate
->bConversionMode
= FALSE
;
120 pPrivate
->iLastOffset
= 1;
121 pPrivate
->iCurrentState
= 0;
123 g_signal_connect(G_OBJECT(pPrivate
->pBuffer
), "mark-set", G_CALLBACK(mark_set_handler
), pDasherControl
);
125 return pDasherControl
;
128 void dasher_internal_buffer_insert(DasherInternalBuffer
*pSelf
, const gchar
*szText
) {
129 DasherInternalBufferPrivate
*pPrivate
= (DasherInternalBufferPrivate
*)(pSelf
->private_data
);
131 gtk_text_buffer_delete_selection(pPrivate
->pBuffer
, false, true );
134 gtk_text_buffer_get_iter_at_mark(pPrivate
->pBuffer
, &sIter
, gtk_text_buffer_get_insert(pPrivate
->pBuffer
));
136 GtkTextTag
*pCurrentTag
= NULL
;
138 if(!pPrivate
->bConversionMode
)
139 pCurrentTag
= pPrivate
->pOutputTag
;
141 switch(pPrivate
->iCurrentState
) {
143 pCurrentTag
= pPrivate
->pVisibleTag
;
146 pCurrentTag
= pPrivate
->pOutputTag
;
154 gtk_text_buffer_insert_with_tags(pPrivate
->pBuffer
, &sIter
, szText
, -1, pCurrentTag
, NULL
);
156 gtk_text_view_scroll_mark_onscreen(pPrivate
->pTextView
, gtk_text_buffer_get_insert(pPrivate
->pBuffer
));
158 // g_message("Buffer lenght: %d", gtk_text_buffer_get_char_count(pPrivate->pBuffer));
161 void dasher_internal_buffer_delete(DasherInternalBuffer
*pSelf
, int iLength
) {
162 DasherInternalBufferPrivate
*pPrivate
= (DasherInternalBufferPrivate
*)(pSelf
->private_data
);
164 GtkTextIter
*start
= new GtkTextIter
;
165 GtkTextIter
*end
= new GtkTextIter
;
167 gtk_text_buffer_get_iter_at_mark(pPrivate
->pBuffer
, end
, gtk_text_buffer_get_insert(pPrivate
->pBuffer
));
171 gtk_text_iter_backward_chars(start
, iLength
);
172 // g_bIgnoreCursorMove = true;
173 gtk_text_buffer_delete(pPrivate
->pBuffer
, start
, end
);
174 gtk_text_view_scroll_mark_onscreen(pPrivate
->pTextView
, gtk_text_buffer_get_insert(pPrivate
->pBuffer
));
175 // g_bIgnoreCursorMove = false;
181 gchar
*dasher_internal_buffer_get_context(DasherInternalBuffer
*pSelf
, gint iOffset
, gint iLength
) {
182 DasherInternalBufferPrivate
*pPrivate
= (DasherInternalBufferPrivate
*)(pSelf
->private_data
);
184 // g_message("Buffer lenght: %d", gtk_text_buffer_get_char_count(pPrivate->pBuffer));
187 GtkTextIter end
; // Refers to end of context, which is start of selection!
189 gtk_text_buffer_get_iter_at_offset(pPrivate
->pBuffer
, &start
, iOffset
);
190 gtk_text_buffer_get_iter_at_offset(pPrivate
->pBuffer
, &end
, iOffset
+ iLength
);
192 return gtk_text_buffer_get_text( pPrivate
->pBuffer
, &start
, &end
, false );
195 void dasher_internal_buffer_change_context(DasherInternalBuffer
*pSelf
, GtkTextIter
*pIter
, GtkTextMark
*pMark
) {
196 const char *szMarkName(gtk_text_mark_get_name(pMark
));
197 if(szMarkName
&& !strcmp(szMarkName
,"insert")) {
198 g_signal_emit_by_name(G_OBJECT(pSelf
), "context_changed", G_OBJECT(pSelf
), NULL
, NULL
);
202 void dasher_internal_buffer_edit_move(DasherInternalBuffer
*pSelf
, int iDirection
, int iDist
) {
203 DasherInternalBufferPrivate
*pPrivate
= (DasherInternalBufferPrivate
*)(pSelf
->private_data
);
207 gtk_text_buffer_get_iter_at_mark(pPrivate
->pBuffer
, &sPos
, gtk_text_buffer_get_insert(pPrivate
->pBuffer
));
209 if(iDirection
== EDIT_FORWARDS
) {
212 gtk_text_iter_forward_char(&sPos
);
215 gtk_text_iter_forward_word_end(&sPos
);
218 if(!gtk_text_view_forward_display_line_end(GTK_TEXT_VIEW(pPrivate
->pTextView
), &sPos
))
220 gtk_text_view_forward_display_line (GTK_TEXT_VIEW(pPrivate
->pTextView
), &sPos
);
221 gtk_text_view_forward_display_line_end(GTK_TEXT_VIEW(pPrivate
->pTextView
), &sPos
);
225 gtk_text_iter_forward_to_end(&sPos
);
232 gtk_text_iter_backward_char(&sPos
);
235 gtk_text_iter_backward_word_start(&sPos
);
239 if(!gtk_text_view_backward_display_line_start(GTK_TEXT_VIEW(pPrivate
->pTextView
), &sPos
))
240 gtk_text_view_backward_display_line(GTK_TEXT_VIEW(pPrivate
->pTextView
), &sPos
);
243 gtk_text_buffer_get_start_iter(pPrivate
->pBuffer
, &sPos
);
248 gtk_text_buffer_place_cursor(pPrivate
->pBuffer
, &sPos
);
249 gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(pPrivate
->pTextView
), gtk_text_buffer_get_insert(pPrivate
->pBuffer
));
252 void dasher_internal_buffer_edit_delete(DasherInternalBuffer
*pSelf
, int iDirection
, int iDist
) {
253 DasherInternalBufferPrivate
*pPrivate
= (DasherInternalBufferPrivate
*)(pSelf
->private_data
);
255 GtkTextIter sPosStart
;
258 gtk_text_buffer_get_iter_at_mark(pPrivate
->pBuffer
, &sPosStart
, gtk_text_buffer_get_insert(pPrivate
->pBuffer
));
262 if(iDirection
== EDIT_FORWARDS
) {
265 gtk_text_iter_forward_char(&sPosStart
);
268 gtk_text_iter_forward_word_end(&sPosStart
);
271 if(!gtk_text_view_forward_display_line_end(GTK_TEXT_VIEW(pPrivate
->pTextView
), &sPosStart
))
273 gtk_text_view_forward_display_line (GTK_TEXT_VIEW(pPrivate
->pTextView
), &sPosStart
);
274 gtk_text_view_forward_display_line_end(GTK_TEXT_VIEW(pPrivate
->pTextView
), &sPosStart
);
278 gtk_text_iter_forward_to_end(&sPosStart
);
285 gtk_text_iter_backward_char(&sPosStart
);
288 gtk_text_iter_backward_word_start(&sPosStart
);
291 if(!gtk_text_view_backward_display_line_start(GTK_TEXT_VIEW(pPrivate
->pTextView
), &sPosStart
))
292 gtk_text_view_backward_display_line(GTK_TEXT_VIEW(pPrivate
->pTextView
), &sPosStart
);
295 gtk_text_buffer_get_start_iter(pPrivate
->pBuffer
, &sPosStart
);
300 gtk_text_buffer_delete(pPrivate
->pBuffer
, &sPosStart
, &sPosEnd
);
301 gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(pPrivate
->pTextView
), gtk_text_buffer_get_insert(pPrivate
->pBuffer
));
304 void dasher_internal_buffer_edit_convert(DasherInternalBuffer
*pSelf
) {
305 DasherInternalBufferPrivate
*pPrivate
= (DasherInternalBufferPrivate
*)(pSelf
->private_data
);
307 if(!(pPrivate
->bConversionMode
))
310 GtkTextIter sStartIter
;
311 GtkTextIter sEndIter
;
312 gtk_text_buffer_get_iter_at_offset(pPrivate
->pBuffer
, &sStartIter
, pPrivate
->iLastOffset
);
313 gtk_text_buffer_get_iter_at_offset(pPrivate
->pBuffer
, &sEndIter
, -1);
314 gtk_text_buffer_apply_tag(pPrivate
->pBuffer
, pPrivate
->pHiddenTag
, &sStartIter
, &sEndIter
);
316 pPrivate
->iCurrentState
= 1;
317 pPrivate
->iLastOffset
= gtk_text_buffer_get_char_count(pPrivate
->pBuffer
);
320 void dasher_internal_buffer_edit_protect(DasherInternalBuffer
*pSelf
) {
321 DasherInternalBufferPrivate
*pPrivate
= (DasherInternalBufferPrivate
*)(pSelf
->private_data
);
323 if(!(pPrivate
->bConversionMode
))
326 pPrivate
->iCurrentState
= 0;
327 pPrivate
->iLastOffset
= gtk_text_buffer_get_char_count(pPrivate
->pBuffer
);
330 void dasher_internal_buffer_conversion_mode(DasherInternalBuffer
*pSelf
, gboolean bMode
) {
331 DasherInternalBufferPrivate
*pPrivate
= (DasherInternalBufferPrivate
*)(pSelf
->private_data
);
334 pPrivate
->bConversionMode
= TRUE
;
335 pPrivate
->iCurrentState
= 0;
336 pPrivate
->iLastOffset
= gtk_text_buffer_get_char_count(pPrivate
->pBuffer
);
339 pPrivate
->bConversionMode
= FALSE
;
340 pPrivate
->iCurrentState
= 1;
344 void dasher_internal_buffer_clear(DasherInternalBuffer
*pSelf
) {
345 DasherInternalBufferPrivate
*pPrivate
= (DasherInternalBufferPrivate
*)(pSelf
->private_data
);
346 GtkTextIter
*start
, *end
;
348 start
= new GtkTextIter
;
349 end
= new GtkTextIter
;
351 gtk_text_buffer_get_iter_at_offset(pPrivate
->pBuffer
, start
, 0);
352 gtk_text_buffer_get_iter_at_offset(pPrivate
->pBuffer
, end
, -1);
354 gtk_text_buffer_delete(pPrivate
->pBuffer
, start
, end
);
356 /* TODO: this probably shouldn't emit a signal */
357 g_signal_emit_by_name(G_OBJECT(pSelf
), "context_changed", G_OBJECT(pSelf
), NULL
, NULL
);
359 pPrivate
->iCurrentState
= 0;
360 pPrivate
->iLastOffset
= 0;
363 gint
dasher_internal_buffer_get_offset(DasherInternalBuffer
*pSelf
) {
364 DasherInternalBufferPrivate
*pPrivate
= (DasherInternalBufferPrivate
*)(pSelf
->private_data
);
367 gtk_text_buffer_get_iter_at_mark(pPrivate
->pBuffer
, &oIter
, gtk_text_buffer_get_mark(pPrivate
->pBuffer
, "insert"));
368 return gtk_text_iter_get_offset(&oIter
);
374 extern "C" void mark_set_handler(GtkWidget
*widget
, GtkTextIter
*pIter
, GtkTextMark
*pMark
, gpointer pUserData
) {
375 dasher_internal_buffer_change_context(DASHER_INTERNAL_BUFFER(pUserData
), pIter
, pMark
);