3 #include <glib/gi18n.h>
5 /* TODO: r4epair gnome libs flags (or get rid of entirely) */
7 #include <libgnomevfs/gnome-vfs.h>
10 #include "dasher_action_keyboard.h"
12 #include "dasher_action_keyboard_maemo.h"
14 #include "dasher_action_script.h"
17 #include "dasher_action_speech.h"
19 #include "dasher_editor.h"
20 #include "dasher_external_buffer.h"
21 #include "dasher_internal_buffer.h"
22 #include "dasher_lock_dialogue.h"
23 #include "dasher_main.h"
24 #include "game_mode_helper.h"
26 // TODO: Maybe reimplement something along the lines of the following, which used to be in edit.cc
29 // GtkTextIter oBufferEnd;
30 // GtkTextIter oBufferStart;
31 // gtk_text_buffer_get_bounds( the_text_buffer, &oBufferStart, &oBufferEnd);
32 // gtk_text_buffer_create_mark(the_text_buffer, "new_start", &oBufferEnd, true);
35 // const gchar *get_new_text() {
36 // GtkTextIter oNewStart;
37 // GtkTextIter oNewEnd;
38 // GtkTextIter oDummy;
40 // gtk_text_buffer_get_bounds( the_text_buffer, &oDummy, &oNewEnd);
41 // gtk_text_buffer_get_iter_at_mark( the_text_buffer, &oNewStart, gtk_text_buffer_get_mark(the_text_buffer, "new_start"));
43 // return gtk_text_buffer_get_text( the_text_buffer, &oNewStart, &oNewEnd, false );
49 #define ACTION_STATE_SHOW 1
50 #define ACTION_STATE_CONTROL 2
51 #define ACTION_STATE_AUTO 4
53 typedef struct _EditorAction EditorAction
;
55 struct _EditorAction
{
56 DasherAction
*pAction
;
58 EditorAction
*pPrevious
;
60 gint iID
; // TODO: does this need to be separate from iControlID?
67 typedef struct _DasherEditorPrivate DasherEditorPrivate
;
69 struct _DasherEditorPrivate
{
70 DasherMain
*pDasherMain
;
71 GtkTextView
*pTextView
;
72 GtkTextBuffer
*pBuffer
;
74 GtkClipboard
*pTextClipboard
;
75 GtkClipboard
*pPrimarySelection
;
76 EditorAction
*pActionRing
;
77 EditorAction
*pActionIter
;
78 gboolean bActionIterStarted
;
80 IDasherBufferSet
*pBufferSet
;
81 IDasherBufferSet
*pExternalBuffer
;
82 IDasherBufferSet
*pInternalBuffer
;
83 GameModeHelper
*pGameModeHelper
;
84 GtkTextMark
*pNewMark
;
85 DasherAppSettings
*pAppSettings
;
87 gboolean bFileModified
; // TODO: Make this work properly, export to main for quit etc
98 static guint dasher_editor_signals
[SIGNAL_NUM
];
100 static DasherEditor
*g_pEditor
;
102 /* TODO: Use appropriate macros here */
103 /* G-object boilerplate code */
104 static void dasher_editor_class_init(DasherEditorClass
*pClass
);
105 static void dasher_editor_init(DasherEditor
*pEditor
);
106 static void dasher_editor_destroy(GObject
*pObject
);
108 /* Private methods */
109 static void dasher_editor_select_all(DasherEditor
*pSelf
);
110 static void dasher_editor_setup_actions(DasherEditor
*pSelf
);
111 static void dasher_editor_add_action(DasherEditor
*pSelf
, DasherAction
*pNewAction
);
112 static EditorAction
*dasher_editor_get_action_by_id(DasherEditor
*pSelf
, int iID
);
113 static void dasher_editor_rebuild_action_pane(DasherEditor
*pSelf
);
114 static void dasher_editor_display_message(DasherEditor
*pSelf
, DasherMessageInfo
*pMessageInfo
);
115 static void dasher_editor_check_activity(DasherEditor
*pSelf
, EditorAction
*pAction
);
116 static void dasher_editor_action_save_state(DasherEditor
*pSelf
, EditorAction
*pAction
);
118 static void dasher_editor_command_new(DasherEditor
*pSelf
);
119 static void dasher_editor_command_open(DasherEditor
*pSelf
);
120 static void dasher_editor_command_save(DasherEditor
*pSelf
, gboolean bPrompt
, gboolean bAppend
);
122 static gboolean
dasher_editor_unix_vfs_open_file(DasherEditor
*pSelf
, const char *filename
, gchar
** buffer
, unsigned long long *size
);
123 static gboolean
dasher_editor_unix_vfs_save_file(DasherEditor
*pSelf
, const char *filename
, gchar
* buffer
, unsigned long long length
, bool append
);
125 static void dasher_editor_vfs_print_error(DasherEditor
*pSelf
, GnomeVFSResult
* result
, const char *myfilename
);
126 static gboolean
dasher_editor_gnome_vfs_open_file(DasherEditor
*pSelf
, const char *filename
, gchar
** buffer
, unsigned long long *size
);
127 static gboolean
dasher_editor_gnome_vfs_save_file(DasherEditor
*pSelf
, const char *filename
, gchar
* buffer
, unsigned long long length
, bool append
);
128 static void dasher_editor_set_filename(DasherEditor
*pSelf
, const gchar
*szFilename
);
130 // TODO: Should these be public?
131 static void dasher_editor_convert(DasherEditor
*pSelf
);
132 static void dasher_editor_protect(DasherEditor
*pSelf
);
134 static void dasher_editor_new_buffer(DasherEditor
*pSelf
, const gchar
*szFilename
);
136 static void dasher_editor_generate_filename(DasherEditor
*pSelf
);
137 static void dasher_editor_open(DasherEditor
*pSelf
, const gchar
*szFilename
);
138 static bool dasher_editor_save_as(DasherEditor
*pSelf
, const gchar
*szFilename
, bool bAppend
);
139 static void dasher_editor_create_buffer(DasherEditor
*pSelf
);
140 static void dasher_editor_clear(DasherEditor
*pSelf
, gboolean bStore
);
141 static void dasher_editor_clipboard(DasherEditor
*pSelf
, clipboard_action act
);
144 // Private methods not in class
145 extern "C" void delete_children_callback(GtkWidget
*pWidget
, gpointer pUserData
);
146 extern "C" void main_window_realized(DasherMain
*pMain
, gpointer pUserData
);
147 extern "C" void action_button_callback(GtkWidget
*pWidget
, gpointer pUserData
);
148 extern "C" void context_changed_handler(GObject
*pSource
, gpointer pUserData
);
149 extern "C" void handle_start_event(GtkDasherControl
*pDasherControl
, gpointer data
);
150 extern "C" void handle_stop_event(GtkDasherControl
*pDasherControl
, gpointer data
);
151 extern "C" void on_message(GtkDasherControl
*pDasherControl
, gpointer pMessageInfo
, gpointer pUserData
);
152 extern "C" void on_command(GtkDasherControl
*pDasherControl
, gchar
*szCommand
, gpointer pUserData
);
153 extern "C" void handle_request_settings(GtkDasherControl
* pDasherControl
, gpointer data
);
154 extern "C" void gtk2_edit_delete_callback(GtkDasherControl
*pDasherControl
, const gchar
*szText
, gpointer user_data
);
155 extern "C" void gtk2_edit_output_callback(GtkDasherControl
*pDasherControl
, const gchar
*szText
, gpointer user_data
);
156 extern "C" void convert_cb(GtkDasherControl
*pDasherControl
, gpointer pUserData
);
157 extern "C" void protect_cb(GtkDasherControl
*pDasherControl
, gpointer pUserData
);
160 dasher_editor_class_init(DasherEditorClass
*pClass
) {
161 g_debug("Initialising DasherEditor");
163 GObjectClass
*pObjectClass
= (GObjectClass
*) pClass
;
164 pObjectClass
->finalize
= dasher_editor_destroy
;
167 dasher_editor_signals
[FILENAME_CHANGED
] = g_signal_new("filename-changed", G_TYPE_FROM_CLASS(pClass
),
168 static_cast < GSignalFlags
> (G_SIGNAL_RUN_FIRST
| G_SIGNAL_ACTION
),
169 G_STRUCT_OFFSET(DasherEditorClass
, filename_changed
),
170 NULL
, NULL
, g_cclosure_marshal_VOID__VOID
,
173 dasher_editor_signals
[BUFFER_CHANGED
] = g_signal_new("buffer-changed", G_TYPE_FROM_CLASS(pClass
),
174 static_cast < GSignalFlags
> (G_SIGNAL_RUN_FIRST
| G_SIGNAL_ACTION
),
175 G_STRUCT_OFFSET(DasherEditorClass
, buffer_changed
),
176 NULL
, NULL
, g_cclosure_marshal_VOID__VOID
,
179 dasher_editor_signals
[CONTEXT_CHANGED
] = g_signal_new("context-changed", G_TYPE_FROM_CLASS(pClass
),
180 static_cast < GSignalFlags
> (G_SIGNAL_RUN_FIRST
| G_SIGNAL_ACTION
),
181 G_STRUCT_OFFSET(DasherEditorClass
, context_changed
),
182 NULL
, NULL
, g_cclosure_marshal_VOID__VOID
,
187 dasher_editor_init(DasherEditor
*pDasherControl
) {
188 DasherEditorPrivate
*pPrivate
= new DasherEditorPrivate
;
189 pDasherControl
->private_data
= pPrivate
;
191 pPrivate
->pBufferSet
= NULL
;
192 pPrivate
->pInternalBuffer
= NULL
;
193 pPrivate
->pExternalBuffer
= NULL
;
194 pPrivate
->bFileModified
= FALSE
;
195 pPrivate
->szFilename
= NULL
;
199 dasher_editor_destroy(GObject
*pObject
) {
200 g_debug("Finalising DasherEditor");
202 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(((DasherEditor
*)pObject
)->private_data
);
204 EditorAction
*pCurrentAction
= pPrivate
->pActionRing
;
207 bool bStarted
= false;
209 while(!bStarted
|| (pCurrentAction
!= pPrivate
->pActionRing
)) {
211 dasher_action_deactivate(pCurrentAction
->pAction
);
212 g_object_unref(G_OBJECT(pCurrentAction
->pAction
));
213 pCurrentAction
= pCurrentAction
->pNext
;
217 if(pPrivate
->pBufferSet
)
218 g_object_unref(G_OBJECT(pPrivate
->pBufferSet
));
220 delete (DasherEditorPrivate
*)(((DasherEditor
*)pObject
)->private_data
);
225 dasher_editor_new(DasherAppSettings
*pAppSettings
, DasherMain
*pDasherMain
, GladeXML
*pGladeXML
, const gchar
*szFullPath
) {
226 DasherEditor
*pDasherEditor
;
227 pDasherEditor
= (DasherEditor
*)(g_object_new(dasher_editor_get_type(), NULL
));
229 g_pEditor
= pDasherEditor
;
231 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pDasherEditor
->private_data
);
232 pPrivate
->pAppSettings
= pAppSettings
;
233 pPrivate
->pDasherMain
= pDasherMain
;
235 GtkTextView
*pTextView
= GTK_TEXT_VIEW(glade_xml_get_widget(pGladeXML
, "the_text_view"));
236 GtkVBox
*pActionPane
= GTK_VBOX(glade_xml_get_widget(pGladeXML
, "vbox39"));
238 pPrivate
->pTextView
= pTextView
;
239 pPrivate
->pBuffer
= gtk_text_view_get_buffer(pTextView
);
241 GtkTextIter oStartIter
;
242 gtk_text_buffer_get_start_iter(pPrivate
->pBuffer
, &oStartIter
);
243 pPrivate
->pNewMark
= gtk_text_buffer_create_mark(pPrivate
->pBuffer
, NULL
, &oStartIter
, TRUE
);
245 pPrivate
->pActionPane
= pActionPane
;
246 pPrivate
->pTextClipboard
= gtk_clipboard_get(GDK_SELECTION_CLIPBOARD
);
247 pPrivate
->pPrimarySelection
= gtk_clipboard_get(GDK_SELECTION_PRIMARY
);
248 pPrivate
->pActionRing
= NULL
;
249 pPrivate
->iNextActionID
= 0;
250 pPrivate
->pGameModeHelper
= 0;
252 // TODO: is this still needed?
253 dasher_editor_create_buffer(pDasherEditor
);
255 dasher_editor_setup_actions(pDasherEditor
);
257 // TODO: see note in command_new method
259 dasher_editor_open(pDasherEditor
, szFullPath
);
261 dasher_editor_generate_filename(pDasherEditor
);
262 dasher_editor_clear(pDasherEditor
, false);
265 return pDasherEditor
;
269 dasher_editor_get_type() {
270 static GType dasher_editor_type
= 0;
272 if(!dasher_editor_type
) {
273 static const GTypeInfo dasher_editor_info
= {
274 sizeof(DasherEditorClass
),
277 (GClassInitFunc
) dasher_editor_class_init
,
280 sizeof(DasherEditor
),
282 (GInstanceInitFunc
) dasher_editor_init
,
286 dasher_editor_type
= g_type_register_static(G_TYPE_OBJECT
, "DasherEditor", &dasher_editor_info
, static_cast < GTypeFlags
> (0));
289 return dasher_editor_type
;
292 // IDasherBufferSet *
293 // dasher_editor_get_buffer_set(DasherEditor *pSelf) {
294 // DasherEditorPrivate *pPrivate = (DasherEditorPrivate *)(pSelf->private_data);
295 // return IDASHER_BUFFER_SET(dasher_internal_buffer_new(pPrivate->pTextView));
299 dasher_editor_clipboard(DasherEditor
*pSelf
, clipboard_action act
) {
300 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
302 GtkTextIter
*start
= new GtkTextIter
;
303 GtkTextIter
*end
= new GtkTextIter
;
305 gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(pPrivate
->pBuffer
), start
, 0);
306 gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(pPrivate
->pBuffer
), end
, -1);
308 gchar
*the_text
= gtk_text_buffer_get_text(pPrivate
->pBuffer
, start
, end
, TRUE
);
312 gtk_text_buffer_cut_clipboard(pPrivate
->pBuffer
, pPrivate
->pTextClipboard
, TRUE
);
315 gtk_text_buffer_copy_clipboard(pPrivate
->pBuffer
, pPrivate
->pTextClipboard
);
317 case CLIPBOARD_PASTE
:
318 gtk_text_buffer_paste_clipboard(pPrivate
->pBuffer
, pPrivate
->pTextClipboard
, NULL
, TRUE
);
320 case CLIPBOARD_COPYALL
:
321 gtk_clipboard_set_text(pPrivate
->pTextClipboard
, the_text
, strlen(the_text
));
322 gtk_clipboard_set_text(pPrivate
->pPrimarySelection
, the_text
, strlen(the_text
));
325 case CLIPBOARD_SELECTALL
:
326 dasher_editor_select_all(pSelf
);
328 case CLIPBOARD_CLEAR
:
329 gtk_text_buffer_set_text(pPrivate
->pBuffer
, "", 0);
339 dasher_editor_handle_stop(DasherEditor
*pSelf
) {
340 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
342 // See if anything is set to auto:
343 EditorAction
*pCurrentAction
= pPrivate
->pActionRing
;
346 bool bStarted
= false;
348 while(!bStarted
|| (pCurrentAction
!= pPrivate
->pActionRing
)) {
350 if(pCurrentAction
->bAuto
)
351 dasher_action_execute(pCurrentAction
->pAction
, pSelf
, -1);
352 pCurrentAction
= pCurrentAction
->pNext
;
358 dasher_editor_handle_start(DasherEditor
*pSelf
) {
359 // The edit box keeps track of where we started
361 // TODO: This should be filtered through the buffer, rather than directly to the edit box
365 /* TODO: This is obsolete - sort this out when commands are reconsidered */
367 dasher_editor_handle_control(DasherEditor
*pSelf
, int iNodeID
) {
368 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
370 if(iNodeID
== Dasher::CControlManager::CTL_USER
+ 1)
371 dasher_editor_clear(pSelf
, false); // Clear node is a special case (it shouldn't be)
373 EditorAction
*pCurrentAction
= pPrivate
->pActionRing
;
374 bool bStarted
= false;
376 while(!bStarted
|| (pCurrentAction
!= pPrivate
->pActionRing
)) {
378 if((iNodeID
>= pCurrentAction
->iControlID
) && (iNodeID
<= pCurrentAction
->iControlID
+ pCurrentAction
->iNSub
)) {
379 dasher_action_execute(pCurrentAction
->pAction
, pSelf
, iNodeID
- pCurrentAction
->iControlID
- 1);
380 // dasher_editor_clear(pSelf, true);
382 pCurrentAction
= pCurrentAction
->pNext
;
387 // TODO: Think about changing signals so we don't need to do this translation
396 static struct SControlMap sMap
[] = {
397 {Dasher::CControlManager::CTL_MOVE_FORWARD_CHAR
, EDIT_FORWARDS
, EDIT_CHAR
, false},
398 {Dasher::CControlManager::CTL_MOVE_FORWARD_WORD
, EDIT_FORWARDS
, EDIT_WORD
, false},
399 {Dasher::CControlManager::CTL_MOVE_FORWARD_LINE
, EDIT_FORWARDS
, EDIT_LINE
, false},
400 {Dasher::CControlManager::CTL_MOVE_FORWARD_FILE
, EDIT_FORWARDS
, EDIT_FILE
, false},
401 {Dasher::CControlManager::CTL_MOVE_BACKWARD_CHAR
, EDIT_BACKWARDS
, EDIT_CHAR
, false},
402 {Dasher::CControlManager::CTL_MOVE_BACKWARD_WORD
, EDIT_BACKWARDS
, EDIT_WORD
, false},
403 {Dasher::CControlManager::CTL_MOVE_BACKWARD_LINE
, EDIT_BACKWARDS
, EDIT_LINE
, false},
404 {Dasher::CControlManager::CTL_MOVE_BACKWARD_FILE
, EDIT_BACKWARDS
, EDIT_FILE
, false},
405 {Dasher::CControlManager::CTL_DELETE_FORWARD_CHAR
, EDIT_FORWARDS
, EDIT_CHAR
, true},
406 {Dasher::CControlManager::CTL_DELETE_FORWARD_WORD
, EDIT_FORWARDS
, EDIT_WORD
, true},
407 {Dasher::CControlManager::CTL_DELETE_FORWARD_LINE
, EDIT_FORWARDS
, EDIT_LINE
, true},
408 {Dasher::CControlManager::CTL_DELETE_FORWARD_FILE
, EDIT_FORWARDS
, EDIT_FILE
, true},
409 {Dasher::CControlManager::CTL_DELETE_BACKWARD_CHAR
, EDIT_BACKWARDS
, EDIT_CHAR
, true},
410 {Dasher::CControlManager::CTL_DELETE_BACKWARD_WORD
, EDIT_BACKWARDS
, EDIT_WORD
, true},
411 {Dasher::CControlManager::CTL_DELETE_BACKWARD_LINE
, EDIT_BACKWARDS
, EDIT_LINE
, true},
412 {Dasher::CControlManager::CTL_DELETE_BACKWARD_FILE
, EDIT_BACKWARDS
, EDIT_FILE
, true}
415 if(pPrivate
->pBufferSet
) {
416 for(unsigned int i(0); i
< sizeof(sMap
)/sizeof(struct SControlMap
); ++i
) {
417 if(sMap
[i
].iEvent
== iNodeID
) {
419 idasher_buffer_set_edit_delete(pPrivate
->pBufferSet
, sMap
[i
].iDir
, sMap
[i
].iDist
);
421 idasher_buffer_set_edit_move(pPrivate
->pBufferSet
, sMap
[i
].iDir
, sMap
[i
].iDist
);
429 dasher_editor_action_button(DasherEditor
*pSelf
, DasherAction
*pAction
) {
431 dasher_action_execute(pAction
, pSelf
, -1);
432 dasher_editor_clear(pSelf
, true);
434 else { // Clear button
435 dasher_editor_clear(pSelf
, false);
440 dasher_editor_clear(DasherEditor
*pSelf
, gboolean bStore
) {
441 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
443 if(IS_DASHER_INTERNAL_BUFFER(pPrivate
->pBufferSet
))
444 dasher_internal_buffer_clear(DASHER_INTERNAL_BUFFER(pPrivate
->pBufferSet
));
449 dasher_editor_actions_start(DasherEditor
*pSelf
) {
450 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
452 pPrivate
->bActionIterStarted
= false;
453 pPrivate
->pActionIter
= pPrivate
->pActionRing
;
457 dasher_editor_actions_more(DasherEditor
*pSelf
) {
458 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
460 return(!pPrivate
->bActionIterStarted
|| (pPrivate
->pActionIter
!= pPrivate
->pActionRing
));
464 dasher_editor_actions_get_next(DasherEditor
*pSelf
, const gchar
**szName
, gint
*iID
, gboolean
*bShow
, gboolean
*bControl
, gboolean
*bAuto
) {
465 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
467 *szName
= dasher_action_get_name(pPrivate
->pActionIter
->pAction
);
468 *iID
= pPrivate
->pActionIter
->iID
;
469 *bShow
= pPrivate
->pActionIter
->bShow
;
470 *bControl
= pPrivate
->pActionIter
->bControl
;
471 *bAuto
= pPrivate
->pActionIter
->bAuto
;
473 pPrivate
->pActionIter
= pPrivate
->pActionIter
->pNext
;
474 pPrivate
->bActionIterStarted
= true;
478 dasher_editor_action_set_show(DasherEditor
*pSelf
, int iActionID
, bool bValue
) {
479 EditorAction
*pAction
;
480 pAction
= dasher_editor_get_action_by_id(pSelf
, iActionID
);
483 pAction
->bShow
= bValue
;
484 dasher_editor_check_activity(pSelf
, pAction
);
485 dasher_editor_rebuild_action_pane(pSelf
);
487 dasher_editor_action_save_state(pSelf
, pAction
);
492 dasher_editor_action_set_control(DasherEditor
*pSelf
, int iActionID
, bool bValue
) {
493 // TODO: Need to actually change behaviour in resonse to these calls
497 // EditorAction *pAction;
498 // pAction = dasher_editor_get_action_by_id(pSelf, iActionID);
501 // pAction->bControl = bValue;
502 // dasher_editor_check_activity(pSelf, pAction);
504 // gtk_dasher_control_connect_node(GTK_DASHER_CONTROL(pDasherWidget), pAction->iControlID, Dasher::CControlManager::CTL_USER, -2);
506 // gtk_dasher_control_disconnect_node(GTK_DASHER_CONTROL(pDasherWidget), pAction->iControlID, Dasher::CControlManager::CTL_USER);
508 // dasher_editor_action_save_state(pSelf, pAction);
513 dasher_editor_action_set_auto(DasherEditor
*pSelf
, int iActionID
, bool bValue
) {
514 EditorAction
*pAction
;
515 pAction
= dasher_editor_get_action_by_id(pSelf
, iActionID
);
518 pAction
->bAuto
= bValue
;
519 dasher_editor_check_activity(pSelf
, pAction
);
521 dasher_editor_action_save_state(pSelf
, pAction
);
526 dasher_editor_create_buffer(DasherEditor
*pSelf
) {
527 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
529 /* Make an external buffer anyway, for keyboard command */
530 /* TODO: Review this */
531 if(!(pPrivate
->pExternalBuffer
))
532 pPrivate
->pExternalBuffer
= IDASHER_BUFFER_SET(dasher_external_buffer_new());
534 if(dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_STYLE
) == 2) {
535 pPrivate
->pBufferSet
= pPrivate
->pExternalBuffer
;
538 if(!(pPrivate
->pInternalBuffer
))
539 pPrivate
->pInternalBuffer
= IDASHER_BUFFER_SET(dasher_internal_buffer_new(pPrivate
->pTextView
));
541 pPrivate
->pBufferSet
= pPrivate
->pInternalBuffer
;
545 g_signal_connect(G_OBJECT(pPrivate
->pBufferSet
), "context_changed", G_CALLBACK(context_changed_handler
), pSelf
);
549 dasher_editor_output(DasherEditor
*pSelf
, const gchar
*szText
) {
550 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
552 if(pPrivate
->pBufferSet
)
553 idasher_buffer_set_insert(pPrivate
->pBufferSet
, szText
);
555 if(pPrivate
->pGameModeHelper
)
556 game_mode_helper_output(pPrivate
->pGameModeHelper
, szText
);
558 pPrivate
->bFileModified
= TRUE
;
562 dasher_editor_delete(DasherEditor
*pSelf
, int iLength
) {
563 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
565 if(pPrivate
->pBufferSet
)
566 idasher_buffer_set_delete(pPrivate
->pBufferSet
, iLength
);
568 if(pPrivate
->pGameModeHelper
)
569 game_mode_helper_delete(pPrivate
->pGameModeHelper
, iLength
);
571 pPrivate
->bFileModified
= TRUE
;
575 dasher_editor_get_context(DasherEditor
*pSelf
, int iOffset
, int iLength
) {
576 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
580 if(pPrivate
->pBufferSet
)
581 szContext
= idasher_buffer_set_get_context(pPrivate
->pBufferSet
, iOffset
, iLength
);
586 // if(szContext && (strlen(szContext) > 0))
587 // gtk_dasher_control_set_context( GTK_DASHER_CONTROL(pDasherWidget), szContext );
591 dasher_editor_get_offset(DasherEditor
*pSelf
) {
592 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
593 return idasher_buffer_set_get_offset(pPrivate
->pBufferSet
);
597 dasher_editor_generate_filename(DasherEditor
*pSelf
) {
598 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
600 gchar
*szNewFilename
= NULL
;
602 if( dasher_app_settings_get_bool(pPrivate
->pAppSettings
, APP_BP_TIME_STAMP
)) {
603 // Build a filename based on the current time and date
611 t_struct
= localtime(&ctime
);
614 snprintf(tbuffer
, 200, "dasher-%04d%02d%02d-%02d%02d.txt", (t_struct
->tm_year
+ 1900), (t_struct
->tm_mon
+ 1), t_struct
->tm_mday
, t_struct
->tm_hour
, t_struct
->tm_min
);
616 szNewFilename
= g_build_path("/", cwd
, tbuffer
, NULL
);
619 dasher_editor_set_filename(pSelf
, szNewFilename
);
621 g_free(szNewFilename
);
625 dasher_editor_open(DasherEditor
*pSelf
, const gchar
*szFilename
) {
626 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
628 unsigned long long size
;
632 if(!dasher_editor_gnome_vfs_open_file(pSelf
, szFilename
, &buffer
, &size
)) {
636 if(!dasher_editor_unix_vfs_open_file(pSelf
, szFilename
, &buffer
, &size
)) {
641 // FIXME - REIMPLEMENT (shouldn't happen through core)
645 // Don't attempt to insert new text if the file is empty as it makes
647 if(!g_utf8_validate(buffer
, size
, NULL
)) {
648 // It's not UTF8, so we do the best we can...
650 // If there are zero bytes in the file then we have a problem -
651 // for now, just assert that we can't load these files.
652 for(unsigned int i(0); i
< size
; ++i
)
654 // GtkWidget *pErrorBox = gtk_message_dialog_new(GTK_WINDOW(window),
656 // GTK_MESSAGE_ERROR,
658 // "Could not open the file \"%s\". Please note that Dasher cannot load files containing binary data, which may be the cause of this error.\n",
660 GtkWidget
*pErrorBox
= gtk_message_dialog_new(NULL
,
664 "Could not open the file \"%s\". Please note that Dasher cannot load files containing binary data, which may be the cause of this error.\n",
666 gtk_dialog_run(GTK_DIALOG(pErrorBox
));
667 gtk_widget_destroy(pErrorBox
);
671 pPrivate
->bFileModified
= TRUE
;
674 gchar
*buffer2
= g_strdup(g_locale_to_utf8(buffer
, size
, NULL
, &iNewSize
, NULL
));
676 // TODO: This function probably needs more thought
678 // const gchar *pEnd;
679 //gboolean bValid = g_utf8_validate(buffer2, -1, &pEnd);
685 gtk_text_buffer_insert_at_cursor(GTK_TEXT_BUFFER(pPrivate
->pBuffer
), buffer
, size
);
686 gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(pPrivate
->pTextView
), gtk_text_buffer_get_insert(GTK_TEXT_BUFFER(pPrivate
->pBuffer
)));
689 dasher_editor_set_filename(pSelf
, szFilename
);
693 dasher_editor_save_as(DasherEditor
*pSelf
, const gchar
*szFilename
, bool bAppend
) {
694 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
696 unsigned long long length
;
697 gchar
*inbuffer
, *outbuffer
= NULL
;
698 // gsize bytes_read, bytes_written;
700 // GError *error = NULL;
701 GtkTextIter
*start
, *end
;
704 start
= new GtkTextIter
;
705 end
= new GtkTextIter
;
707 gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(pPrivate
->pBuffer
), start
, 0);
708 gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(pPrivate
->pBuffer
), end
, -1);
710 inbuffer
= gtk_text_iter_get_slice(start
, end
);
712 // g_message("String %s", inbuffer);
714 //length = gtk_text_iter_get_offset(end) - gtk_text_iter_get_offset(start);
715 //length = gtk_text_buffer_get_byte_count(GTK_TEXT_BUFFER(the_text_buffer));
717 // I'm pretty certain that this is null terminated, but not 100%
718 length
= strlen(inbuffer
);
720 // g_message("Length is %d", length);
722 outbuffer
= (char *)malloc((length
+ 1) * sizeof(gchar
));
723 memcpy((void *)outbuffer
, (void *)inbuffer
, length
* sizeof(gchar
));
724 outbuffer
[length
] = 0;
726 inbuffer
= outbuffer
;
729 // switch (fileencoding) {
730 // case Dasher::Opts::UserDefault:
731 // case Dasher::Opts::AlphabetDefault:
732 // //FIXME - need to call GetAlphabetType and do appropriate stuff regarding
733 // //the character set. Arguably we should always be saving in either UTF-8 or
734 // //the user's locale (which may, of course, be UTF-8) because otherwise
735 // //we're going to read in rubbish, and we shouldn't be encouraging weird
736 // //codepage madness any further
738 // //FIXME - error handling
739 // outbuffer = g_locale_from_utf8(inbuffer, -1, &bytes_read, &bytes_written, &error);
740 // if(outbuffer == NULL) {
741 // // We can't represent the text in the current locale, so fall back to
743 // outbuffer = inbuffer;
744 // bytes_written = length;
746 // case Dasher::Opts::UTF8:
747 // outbuffer = inbuffer;
748 // bytes_written = length;
750 // // Does /anyone/ want to save text files in UTF16?
751 // // (in any case, my opinions regarding encouragement of data formats with
752 // // endianness damage are almost certainly unprintable)
754 // case Dasher::Opts::UTF16LE:
755 // cd = g_iconv_open("UTF16LE", "UTF8");
756 // outbuffer = g_convert_with_iconv(inbuffer, -1, cd, &bytes_read, &bytes_written, &error);
758 // case Dasher::Opts::UTF16BE:
759 // cd = g_iconv_open("UTF16BE", "UTF8");
760 // outbuffer = g_convert_with_iconv(inbuffer, -1, cd, &bytes_read, &bytes_written, &error);
763 outbuffer
= inbuffer
;
764 bytes_written
= length
;
768 if(!dasher_editor_gnome_vfs_save_file(pSelf
, szFilename
, outbuffer
, bytes_written
, bAppend
)) {
772 if(!dasher_editor_unix_vfs_save_file(pSelf
, szFilename
, outbuffer
, bytes_written
, bAppend
)) {
777 pPrivate
->bFileModified
= FALSE
;
779 // gtk_window_set_title(GTK_WINDOW(window), myfilename);
781 dasher_editor_set_filename(pSelf
, szFilename
);
783 // if(filename != myfilename) {
784 // g_free((void *)filename);
785 // filename = g_strdup(myfilename);
792 // dasher_editor_start_tutorial(DasherEditor *pSelf) {
793 // DasherEditorPrivate *pPrivate = (DasherEditorPrivate *)(pSelf->private_data);
795 // // TODO: reimplement
796 // // pPrivate->pGameModeHelper = GAME_MODE_HELPER(game_mode_helper_new(GTK_DASHER_CONTROL(pDasherWidget)));
800 dasher_editor_command(DasherEditor
*pSelf
, const gchar
*szCommand
) {
801 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
803 if(!strcmp(szCommand
, "new")) { //select_new_file
804 dasher_editor_command_new(pSelf
);
808 if(!strcmp(szCommand
, "open")) { //select open file
809 dasher_editor_command_open(pSelf
);
813 if(!strcmp(szCommand
, "save")) { //save_file
814 dasher_editor_command_save(pSelf
, FALSE
, FALSE
);
818 if(!strcmp(szCommand
, "saveas")) { // select_save_file_as
819 dasher_editor_command_save(pSelf
, TRUE
, FALSE
);
823 if(!strcmp(szCommand
, "append")) { // select_append_file
824 dasher_editor_command_save(pSelf
, TRUE
, TRUE
);
828 if(!strcmp(szCommand
, "cut")) { // clipboard_cut
829 dasher_editor_clipboard(pSelf
, CLIPBOARD_CUT
);
833 if(!strcmp(szCommand
, "copy")) { // clipboard_copy
834 dasher_editor_clipboard(pSelf
, CLIPBOARD_COPY
);
838 if(!strcmp(szCommand
, "copyall")) { // clipboard_copyall
839 dasher_editor_clipboard(pSelf
, CLIPBOARD_COPYALL
);
843 if(!strcmp(szCommand
, "paste")) { // clipboard_paste
844 dasher_editor_clipboard(pSelf
, CLIPBOARD_PASTE
);
848 // TODO: This isn't actually accessible from anywhere
849 if(!strcmp(szCommand
, "selectall")) { // clipboard_paste
850 dasher_editor_clipboard(pSelf
, CLIPBOARD_SELECTALL
);
855 /* TODO: We need a rethink here */
856 const gchar
*szForwardCommand
= NULL
;
857 gint iSubCommand
= 0;
859 if(!strcmp(szCommand
, "speakall")) {
860 szForwardCommand
= "Speak";
863 else if(!strcmp(szCommand
, "speaklast")) {
864 szForwardCommand
= "Speak";
867 else if(!strcmp(szCommand
, "speakrepeat")) {
868 szForwardCommand
= "Speak";
872 if(szForwardCommand
) {
873 gboolean bActionIterStarted
= false;
874 EditorAction
*pActionIter
= pPrivate
->pActionRing
;
876 while((pActionIter
!= pPrivate
->pActionRing
) || !bActionIterStarted
) {
877 bActionIterStarted
= true;
879 if(!strcmp(dasher_action_get_name(pActionIter
->pAction
), szForwardCommand
)) {
880 dasher_action_execute(pActionIter
->pAction
, pSelf
, iSubCommand
);
884 pActionIter
= pActionIter
->pNext
;
893 dasher_editor_file_changed(DasherEditor
*pSelf
) {
894 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
896 return pPrivate
->bFileModified
;
900 dasher_editor_get_filename(DasherEditor
*pSelf
) {
901 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
903 return pPrivate
->szFilename
;
906 // TODO: We shouldn't need to know about the buffer here - make this a method of the buffer set
908 dasher_editor_get_all_text(DasherEditor
*pSelf
) {
909 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
914 gtk_text_buffer_get_start_iter(pPrivate
->pBuffer
, &oStart
);
915 gtk_text_buffer_get_end_iter(pPrivate
->pBuffer
, &oEnd
);
917 pPrivate
->pNewMark
= gtk_text_buffer_create_mark(pPrivate
->pBuffer
, NULL
, &oEnd
, TRUE
);
919 return gtk_text_buffer_get_text(pPrivate
->pBuffer
, &oStart
, &oEnd
, false );
923 dasher_editor_get_new_text(DasherEditor
*pSelf
) {
924 // TODO: Implement this properly
925 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
930 gtk_text_buffer_get_end_iter(pPrivate
->pBuffer
, &oEnd
);
931 gtk_text_buffer_get_iter_at_mark(pPrivate
->pBuffer
, &oStart
, pPrivate
->pNewMark
);
933 const gchar
*szRetVal
= gtk_text_buffer_get_text(pPrivate
->pBuffer
, &oStart
, &oEnd
, false );
935 pPrivate
->pNewMark
= gtk_text_buffer_create_mark(pPrivate
->pBuffer
, NULL
, &oEnd
, TRUE
);
941 /* Private methods */
943 dasher_editor_select_all(DasherEditor
*pSelf
) {
944 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
945 GtkTextIter
*start
, *end
;
947 start
= new GtkTextIter
;
948 end
= new GtkTextIter
;
950 gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(pPrivate
->pBuffer
), start
, 0);
951 gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(pPrivate
->pBuffer
), end
, -1);
953 GtkTextMark
*selection
= gtk_text_buffer_get_mark(pPrivate
->pBuffer
, "selection_bound");
954 GtkTextMark
*cursor
= gtk_text_buffer_get_mark(pPrivate
->pBuffer
, "insert");
956 gtk_text_buffer_move_mark(pPrivate
->pBuffer
, selection
, start
);
957 gtk_text_buffer_move_mark(pPrivate
->pBuffer
, cursor
, end
);
964 dasher_editor_setup_actions(DasherEditor
*pSelf
) {
965 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
967 // TODO: Activate and deactivate methods for actions
968 // TODO: Clear shouldn't be a special case (include support for false in clear method)
971 dasher_editor_add_action(pSelf
, DASHER_ACTION(dasher_action_speech_new()));
974 dasher_editor_add_action(pSelf
, DASHER_ACTION(dasher_action_keyboard_new(pPrivate
->pExternalBuffer
)));
977 dasher_editor_add_action(pSelf
, DASHER_ACTION(dasher_action_keyboard_maemo_new()));
979 // dasher_editor_add_action(pSelf, DASHER_ACTION(dasher_action_copy_new(pSelf)));
982 G_CONST_RETURN gchar
*szFilename
;
984 gchar
*szUserScriptDir
= new gchar
[strlen(dasher_app_settings_get_string(pPrivate
->pAppSettings
, SP_USER_LOC
))+9];
985 strcpy(szUserScriptDir
, dasher_app_settings_get_string(pPrivate
->pAppSettings
, SP_USER_LOC
));
986 strcat(szUserScriptDir
, "scripts/");
988 pDirectory
= g_dir_open(szUserScriptDir
, 0, NULL
);
991 while((szFilename
= g_dir_read_name(pDirectory
))) {
992 dasher_editor_add_action(pSelf
, DASHER_ACTION(dasher_action_script_new(szUserScriptDir
, szFilename
)));
995 g_dir_close(pDirectory
);
998 delete[] szUserScriptDir
;
1000 gchar
*szSystemScriptDir
= new gchar
[strlen(dasher_app_settings_get_string(pPrivate
->pAppSettings
, SP_SYSTEM_LOC
))+9];
1001 strcpy(szSystemScriptDir
, dasher_app_settings_get_string(pPrivate
->pAppSettings
, SP_SYSTEM_LOC
));
1002 strcat(szSystemScriptDir
, "scripts/");
1004 pDirectory
= g_dir_open(szSystemScriptDir
, 0, NULL
);
1007 while((szFilename
= g_dir_read_name(pDirectory
))) {
1008 dasher_editor_add_action(pSelf
, DASHER_ACTION(dasher_action_script_new(szSystemScriptDir
, szFilename
)));
1011 g_dir_close(pDirectory
);
1014 delete[] szSystemScriptDir
;
1017 // TODO: Reimplement
1019 // // TODO: This doesn't get re-called if the preferences change
1021 // gtk_dasher_control_register_node( GTK_DASHER_CONTROL(pDasherWidget), Dasher::CControlManager::CTL_USER, "Actions", -1 );
1022 // gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pDasherWidget), Dasher::CControlManager::CTL_USER, Dasher::CControlManager::CTL_ROOT, -2);
1023 // int iControlOffset(1);
1025 // gtk_dasher_control_register_node( GTK_DASHER_CONTROL(pDasherWidget), Dasher::CControlManager::CTL_USER + iControlOffset, "Clear", -1 );
1026 // gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pDasherWidget), Dasher::CControlManager::CTL_USER + iControlOffset, Dasher::CControlManager::CTL_USER, -2);
1027 // gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pDasherWidget), -1, Dasher::CControlManager::CTL_USER + iControlOffset, -2);
1028 // ++iControlOffset;
1030 // EditorAction *pCurrentAction = pPrivate->pActionRing;
1031 // bool bStarted = false;
1033 // while(!bStarted || (pCurrentAction != pPrivate->pActionRing)) {
1036 // if(pCurrentAction->bControl) {
1037 // gtk_dasher_control_register_node( GTK_DASHER_CONTROL(pDasherWidget), Dasher::CControlManager::CTL_USER + iControlOffset, dasher_action_get_name(pCurrentAction->pAction), -1 );
1038 // gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pDasherWidget), Dasher::CControlManager::CTL_USER + iControlOffset, Dasher::CControlManager::CTL_USER, -2);
1040 // int iNSub(dasher_action_get_sub_count(pCurrentAction->pAction));
1043 // gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pDasherWidget), -1, Dasher::CControlManager::CTL_USER + iControlOffset, -2);
1046 // for(int i(0); i < iNSub; ++i) {
1047 // gtk_dasher_control_register_node( GTK_DASHER_CONTROL(pDasherWidget), Dasher::CControlManager::CTL_USER + iControlOffset + i + 1, dasher_action_get_sub_name(pCurrentAction->pAction, i), -1 );
1048 // gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pDasherWidget), Dasher::CControlManager::CTL_USER + iControlOffset + i + 1, Dasher::CControlManager::CTL_USER + iControlOffset, -2);
1049 // gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pDasherWidget), -1, Dasher::CControlManager::CTL_USER + iControlOffset + i + 1, -2);
1053 // pCurrentAction->iControlID = Dasher::CControlManager::CTL_USER + iControlOffset;
1054 // pCurrentAction->iNSub = iNSub;
1055 // iControlOffset += iNSub + 1;
1058 // pCurrentAction = pCurrentAction->pNext;
1061 #ifndef WITH_MAEMOFULLSCREEN
1062 // dasher_editor_rebuild_action_pane(pSelf);
1067 dasher_editor_add_action(DasherEditor
*pSelf
, DasherAction
*pNewAction
) {
1068 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
1070 EditorAction
*pNewEditorAction
= new EditorAction
;
1071 pNewEditorAction
->pAction
= pNewAction
;
1072 pNewEditorAction
->iID
= pPrivate
->iNextActionID
;
1073 ++pPrivate
->iNextActionID
;
1075 gchar szRegistryName
[256];
1076 strncpy(szRegistryName
, "Action_", 256);
1077 strncat(szRegistryName
, dasher_action_get_name(pNewEditorAction
->pAction
), 255 - strlen(szRegistryName
));
1079 for(unsigned int i(0); i
< strlen(szRegistryName
); ++i
)
1080 if(szRegistryName
[i
] == ' ')
1081 szRegistryName
[i
] = '_';
1085 if(!dasher_app_settings_get_free_long(pPrivate
->pAppSettings
, szRegistryName
, iState
)) {
1086 if(!strcmp(dasher_action_get_name(pNewEditorAction
->pAction
), "Speak"))
1089 iState
= ACTION_STATE_SHOW
| ACTION_STATE_CONTROL
;
1091 dasher_app_settings_set_free_long(pPrivate
->pAppSettings
, szRegistryName
, iState
);
1094 pNewEditorAction
->bShow
= iState
& ACTION_STATE_SHOW
;
1095 pNewEditorAction
->bControl
= iState
& ACTION_STATE_CONTROL
;
1096 pNewEditorAction
->bAuto
= iState
& ACTION_STATE_AUTO
;
1098 dasher_editor_check_activity(pSelf
, pNewEditorAction
);
1100 if(pPrivate
->pActionRing
) {
1101 pNewEditorAction
->pNext
= pPrivate
->pActionRing
;
1102 pNewEditorAction
->pPrevious
= pPrivate
->pActionRing
->pPrevious
;
1103 pPrivate
->pActionRing
->pPrevious
->pNext
= pNewEditorAction
;
1104 pPrivate
->pActionRing
->pPrevious
= pNewEditorAction
;
1107 pNewEditorAction
->pNext
= pNewEditorAction
;
1108 pNewEditorAction
->pPrevious
= pNewEditorAction
;
1111 pPrivate
->pActionRing
= pNewEditorAction
;
1113 // TODO: Reimplement
1114 // if(iState & ACTION_STATE_SHOW)
1115 // gtk_dasher_control_add_action_button(GTK_DASHER_CONTROL(pDasherWidget), dasher_action_get_name(pNewEditorAction->pAction));
1118 static EditorAction
*
1119 dasher_editor_get_action_by_id(DasherEditor
*pSelf
, int iID
){
1120 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
1122 EditorAction
*pCurrentAction
= pPrivate
->pActionRing
;
1123 bool bStarted
= false;
1125 while(!bStarted
|| (pCurrentAction
!= pPrivate
->pActionRing
)) {
1127 if(pCurrentAction
->iID
== iID
)
1128 return pCurrentAction
;
1129 pCurrentAction
= pCurrentAction
->pNext
;
1136 dasher_editor_rebuild_action_pane(DasherEditor
*pSelf
) {
1137 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
1139 // Delete any existing widgets
1140 gtk_container_foreach(GTK_CONTAINER(pPrivate
->pActionPane
), delete_children_callback
, 0);
1142 // Add the cancel button
1143 GtkButton
*pNewButton
= GTK_BUTTON(gtk_button_new_with_label("Clear"));
1144 gtk_widget_show(GTK_WIDGET(pNewButton
));
1146 void **pUserData
= new void *[2];
1147 pUserData
[0] = (void *)pSelf
;
1150 g_signal_connect(G_OBJECT(pNewButton
), "clicked", G_CALLBACK(action_button_callback
), pUserData
);
1152 // For Maemo we want the packing to expand
1153 gtk_box_pack_start(GTK_BOX(pPrivate
->pActionPane
), GTK_WIDGET(pNewButton
), true, true, 0);
1155 gtk_box_pack_start(GTK_BOX(pPrivate
->pActionPane
), GTK_WIDGET(pNewButton
), false, false, 0);
1159 EditorAction
*pCurrentAction
= pPrivate
->pActionRing
;
1160 bool bStarted
= false;
1162 while(!bStarted
|| (pCurrentAction
!= pPrivate
->pActionRing
)) {
1164 if(pCurrentAction
->bShow
) {
1165 GtkButton
*pNewButton
= GTK_BUTTON(gtk_button_new_with_label(dasher_action_get_name(pCurrentAction
->pAction
)));
1166 gtk_widget_show(GTK_WIDGET(pNewButton
));
1168 pUserData
= new void *[2];
1169 pUserData
[0] = (void *)pSelf
;
1170 pUserData
[1] = (void *)(pCurrentAction
->pAction
);
1172 g_signal_connect(G_OBJECT(pNewButton
), "clicked", G_CALLBACK(action_button_callback
), pUserData
);
1174 // For Maemo we want the packing to expand
1175 gtk_box_pack_start(GTK_BOX(pPrivate
->pActionPane
), GTK_WIDGET(pNewButton
), true, true, 0);
1177 gtk_box_pack_start(GTK_BOX(pPrivate
->pActionPane
), GTK_WIDGET(pNewButton
), false, false, 0);
1180 pCurrentAction
= pCurrentAction
->pNext
;
1184 // TODO: This shouldn't be a part of the editor
1186 dasher_editor_display_message(DasherEditor
*pSelf
, DasherMessageInfo
*pMessageInfo
) {
1187 GtkMessageDialog
*pDialog
= GTK_MESSAGE_DIALOG(gtk_message_dialog_new(0, GTK_DIALOG_MODAL
, GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, pMessageInfo
->szMessage
));
1188 gtk_dialog_run(GTK_DIALOG(pDialog
));
1189 gtk_widget_destroy(GTK_WIDGET(pDialog
));
1193 dasher_editor_check_activity(DasherEditor
*pSelf
, EditorAction
*pAction
) {
1194 gboolean
bNeedActive(pAction
->bShow
|| pAction
->bControl
|| pAction
->bAuto
);
1195 gboolean
bActive(dasher_action_get_active(pAction
->pAction
));
1197 if(bNeedActive
&& !bActive
)
1198 dasher_action_activate(pAction
->pAction
);
1199 else if(!bNeedActive
&& bActive
)
1200 dasher_action_deactivate(pAction
->pAction
);
1204 dasher_editor_action_save_state(DasherEditor
*pSelf
, EditorAction
*pAction
) {
1205 gchar szRegistryName
[256];
1206 strncpy(szRegistryName
, "Action_", 256);
1207 strncat(szRegistryName
, dasher_action_get_name(pAction
->pAction
), 255 - strlen(szRegistryName
));
1209 for(unsigned int i(0); i
< strlen(szRegistryName
); ++i
)
1210 if(szRegistryName
[i
] == ' ')
1211 szRegistryName
[i
] = '_';
1216 iState
+= ACTION_STATE_SHOW
;
1218 if(pAction
->bControl
)
1219 iState
+= ACTION_STATE_CONTROL
;
1222 iState
+= ACTION_STATE_AUTO
;
1224 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
1225 dasher_app_settings_set_free_long(pPrivate
->pAppSettings
, szRegistryName
, iState
);
1229 dasher_editor_command_new(DasherEditor
*pSelf
) {
1230 dasher_editor_new_buffer(pSelf
, NULL
);
1234 dasher_editor_command_open(DasherEditor
*pSelf
) {
1235 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
1237 // GtkWidget *filesel = gtk_file_chooser_dialog_new(_("Select File"), GTK_WINDOW(pPrivate->pMainWindow), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL);
1238 GtkWidget
*filesel
= gtk_file_chooser_dialog_new(_("Select File"), NULL
, GTK_FILE_CHOOSER_ACTION_OPEN
, GTK_STOCK_OPEN
, GTK_RESPONSE_ACCEPT
, GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
, NULL
);
1241 gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(filesel
), FALSE
);
1244 if(gtk_dialog_run(GTK_DIALOG(filesel
)) == GTK_RESPONSE_ACCEPT
) {
1246 char *filename
= gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(filesel
));
1248 char *filename
= gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filesel
));
1250 dasher_editor_new_buffer(pSelf
, filename
);
1253 gtk_widget_destroy(filesel
);
1257 dasher_editor_command_save(DasherEditor
*pSelf
, gboolean bPrompt
, gboolean bAppend
) {
1258 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
1259 gchar
*szFilename
= NULL
;
1261 if(bPrompt
|| !szFilename
) {
1262 // GtkWidget *filesel = gtk_file_chooser_dialog_new(_("Select File"), GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL);
1263 GtkWidget
*filesel
= gtk_file_chooser_dialog_new(_("Select File"), NULL
, GTK_FILE_CHOOSER_ACTION_SAVE
, GTK_STOCK_SAVE
, GTK_RESPONSE_ACCEPT
, GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
, NULL
);
1266 gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(filesel
), FALSE
);
1269 if(gtk_dialog_run(GTK_DIALOG(filesel
)) == GTK_RESPONSE_ACCEPT
) {
1271 szFilename
= gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(filesel
));
1273 szFilename
= gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filesel
));
1280 gtk_widget_destroy(filesel
);
1283 dasher_editor_save_as(pSelf
, szFilename
, bAppend
);
1288 dasher_editor_unix_vfs_open_file(DasherEditor
*pSelf
, const char *myfilename
, gchar
**buffer
, unsigned long long *size
) {
1289 GtkWidget
*error_dialog
;
1291 struct stat file_stat
;
1294 stat(myfilename
, &file_stat
);
1295 fp
= fopen(myfilename
, "r");
1297 if(fp
== NULL
|| S_ISDIR(file_stat
.st_mode
)) {
1298 // error_dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Could not open the file \"%s\".\n", myfilename);
1299 error_dialog
= gtk_message_dialog_new(NULL
, GTK_DIALOG_MODAL
, GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "Could not open the file \"%s\".\n", myfilename
);
1300 gtk_dialog_set_default_response(GTK_DIALOG(error_dialog
), GTK_RESPONSE_OK
);
1301 gtk_window_set_resizable(GTK_WINDOW(error_dialog
), FALSE
);
1302 gtk_dialog_run(GTK_DIALOG(error_dialog
));
1303 gtk_widget_destroy(error_dialog
);
1307 *size
= file_stat
.st_size
;
1308 *buffer
= (gchar
*) g_malloc(*size
);
1309 fread(*buffer
, *size
, 1, fp
);
1315 dasher_editor_unix_vfs_save_file(DasherEditor
*pSelf
, const char *myfilename
, gchar
*buffer
, unsigned long long length
, bool append
) {
1317 GtkWidget
*error_dialog
;
1321 if(append
== true) {
1322 fp
= fopen(myfilename
, "a");
1329 fp
= fopen(myfilename
, "w");
1336 // error_dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Could not save the file \"%s\".\n", myfilename);
1337 error_dialog
= gtk_message_dialog_new(NULL
, GTK_DIALOG_MODAL
, GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "Could not save the file \"%s\".\n", myfilename
);
1338 gtk_dialog_set_default_response(GTK_DIALOG(error_dialog
), GTK_RESPONSE_OK
);
1339 gtk_window_set_resizable(GTK_WINDOW(error_dialog
), FALSE
);
1340 gtk_dialog_run(GTK_DIALOG(error_dialog
));
1341 gtk_widget_destroy(error_dialog
);
1345 fwrite(buffer
, 1, length
, fp
);
1353 dasher_editor_vfs_print_error(DasherEditor
*pSelf
, GnomeVFSResult
*result
, const char *myfilename
) {
1354 // Turns a Gnome VFS error into English
1355 GtkWidget
*error_dialog
;
1356 // error_dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Could not open the file \"%s\"\n%s\n", myfilename, gnome_vfs_result_to_string(*result));
1357 error_dialog
= gtk_message_dialog_new(NULL
, GTK_DIALOG_MODAL
, GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "Could not open the file \"%s\"\n%s\n", myfilename
, gnome_vfs_result_to_string(*result
));
1358 gtk_dialog_set_default_response(GTK_DIALOG(error_dialog
), GTK_RESPONSE_OK
);
1359 gtk_window_set_resizable(GTK_WINDOW(error_dialog
), FALSE
);
1360 gtk_dialog_run(GTK_DIALOG(error_dialog
));
1361 gtk_widget_destroy(error_dialog
);
1366 dasher_editor_gnome_vfs_open_file(DasherEditor
*pSelf
, const char *myfilename
, gchar
**buffer
, unsigned long long *size
) {
1367 GnomeVFSHandle
*read_handle
;
1368 GnomeVFSResult result
;
1369 GnomeVFSFileInfo info
;
1370 GnomeVFSFileSize bytes_read
;
1373 uri
= gnome_vfs_uri_new(myfilename
);
1375 if(uri
== NULL
) { // It's not a URI we can cope with - assume it's a filename
1376 char *tmpfilename
= gnome_vfs_get_uri_from_local_path(myfilename
);
1377 // TODO: figure out how this is supposed to work, and reimplement
1378 // if(myfilename != filename) {
1379 // g_free((void *)myfilename);
1381 myfilename
= tmpfilename
;
1382 uri
= gnome_vfs_uri_new(myfilename
);
1388 result
= gnome_vfs_open_uri(&read_handle
, uri
, GNOME_VFS_OPEN_READ
);
1389 if(result
!= GNOME_VFS_OK
) {
1390 dasher_editor_vfs_print_error(pSelf
, &result
, myfilename
);
1395 result
= gnome_vfs_get_file_info_uri(uri
, &info
, GNOME_VFS_FILE_INFO_FOLLOW_LINKS
);
1396 if(result
!= GNOME_VFS_OK
) {
1397 dasher_editor_vfs_print_error(pSelf
, &result
, myfilename
);
1402 *size
= (gint
) info
.size
;
1403 *buffer
= (gchar
*) g_malloc(*size
);
1404 result
= gnome_vfs_read(read_handle
, *buffer
, *size
, &bytes_read
);
1406 if(result
!= GNOME_VFS_OK
) {
1407 dasher_editor_vfs_print_error(pSelf
, &result
, myfilename
);
1411 gnome_vfs_close(read_handle
);
1417 dasher_editor_gnome_vfs_save_file(DasherEditor
*pSelf
, const char *myfilename
, gchar
*buffer
, unsigned long long length
, bool append
) {
1418 GnomeVFSHandle
*write_handle
;
1419 GnomeVFSResult result
;
1420 GnomeVFSFileSize bytes_written
;
1423 uri
= gnome_vfs_uri_new(myfilename
);
1425 if(uri
== NULL
) { // It's not a URI we can cope with - assume it's a filename
1426 char *tmpfilename
= gnome_vfs_get_uri_from_local_path(myfilename
);
1427 // TODO: figure out what this is supposed to do and reimplement
1428 // if(myfilename != filename) {
1429 // g_free((void *)myfilename);
1431 myfilename
= tmpfilename
;
1432 uri
= gnome_vfs_uri_new(myfilename
);
1438 result
= gnome_vfs_create_uri(&write_handle
, uri
, GnomeVFSOpenMode(GNOME_VFS_OPEN_WRITE
| GNOME_VFS_OPEN_RANDOM
), TRUE
, 0666);
1440 if(result
== GNOME_VFS_ERROR_FILE_EXISTS
) {
1442 result
= gnome_vfs_open_uri(&write_handle
, uri
, GnomeVFSOpenMode(GNOME_VFS_OPEN_WRITE
| GNOME_VFS_OPEN_RANDOM
));
1445 result
= gnome_vfs_create_uri(&write_handle
, uri
, GnomeVFSOpenMode(GNOME_VFS_OPEN_WRITE
| GNOME_VFS_OPEN_RANDOM
), FALSE
, 0666);
1449 if(result
!= GNOME_VFS_OK
) {
1450 dasher_editor_vfs_print_error(pSelf
, &result
, myfilename
);
1456 result
= gnome_vfs_seek(write_handle
, GNOME_VFS_SEEK_END
, 0);
1457 if(result
!= GNOME_VFS_OK
) {
1458 dasher_editor_vfs_print_error(pSelf
, &result
, myfilename
);
1464 result
= gnome_vfs_write(write_handle
, buffer
, length
, &bytes_written
);
1465 if(result
!= GNOME_VFS_OK
) {
1466 dasher_editor_vfs_print_error(pSelf
, &result
, myfilename
);
1471 gnome_vfs_close(write_handle
);
1478 dasher_editor_set_filename(DasherEditor
*pSelf
, const gchar
*szFilename
) {
1479 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
1481 if(pPrivate
->szFilename
)
1482 g_free((void *)pPrivate
->szFilename
);
1485 pPrivate
->szFilename
= g_strdup(szFilename
);
1487 pPrivate
->szFilename
= NULL
;
1489 g_signal_emit_by_name(G_OBJECT(pSelf
), "filename_changed", G_OBJECT(pSelf
), NULL
, NULL
);
1493 dasher_editor_convert(DasherEditor
*pSelf
) {
1494 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
1496 if(pPrivate
->pBufferSet
)
1497 idasher_buffer_set_edit_convert(pPrivate
->pBufferSet
);
1501 dasher_editor_protect(DasherEditor
*pSelf
) {
1502 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
1504 if(pPrivate
->pBufferSet
)
1505 idasher_buffer_set_edit_protect(pPrivate
->pBufferSet
);
1509 dasher_editor_new_buffer(DasherEditor
*pSelf
, const gchar
*szFilename
) {
1510 /* TODO: eventually rewrite this without references to external functions */
1513 dasher_editor_open(pSelf
, szFilename
);
1516 dasher_editor_generate_filename(pSelf
);
1517 dasher_editor_clear(pSelf
, false);
1520 g_signal_emit_by_name(G_OBJECT(pSelf
), "buffer_changed", G_OBJECT(pSelf
), NULL
, NULL
);
1523 /* Callback Functions */
1526 delete_children_callback(GtkWidget
*pWidget
, gpointer pUserData
) {
1527 gtk_widget_destroy(pWidget
);
1531 main_window_realized(DasherMain
*pMain
, gpointer pUserData
) {
1535 action_button_callback(GtkWidget
*pWidget
, gpointer pUserData
) {
1536 void **pPointers((void **)pUserData
);
1537 dasher_editor_action_button((DasherEditor
*)pPointers
[0], (DasherAction
*)pPointers
[1]);
1541 context_changed_handler(GObject
*pSource
, gpointer pUserData
) {
1542 DasherEditor
*pSelf
= DASHER_EDITOR(pUserData
);
1544 // TODO: plumb signal back into control
1545 g_signal_emit_by_name(G_OBJECT(pSelf
), "context_changed", G_OBJECT(pSelf
), NULL
, NULL
);
1549 handle_start_event(GtkDasherControl
*pDasherControl
, gpointer data
) {
1551 dasher_editor_handle_start(g_pEditor
);
1555 handle_stop_event(GtkDasherControl
*pDasherControl
, gpointer data
) {
1557 dasher_editor_handle_stop(g_pEditor
);
1561 on_message(GtkDasherControl
*pDasherControl
, gpointer pMessageInfo
, gpointer pUserData
) {
1563 dasher_editor_display_message(g_pEditor
, (DasherMessageInfo
*)pMessageInfo
);
1567 on_command(GtkDasherControl
*pDasherControl
, gchar
*szCommand
, gpointer pUserData
) {
1569 dasher_editor_command(g_pEditor
, szCommand
);
1572 // TODO: The following two should probably be made the same
1574 handle_request_settings(GtkDasherControl
* pDasherControl
, gpointer data
) {
1575 // TODO: reimplement
1576 // dasher_preferences_dialogue_show(g_pPreferencesDialogue);
1580 gtk2_edit_delete_callback(GtkDasherControl
*pDasherControl
, const gchar
*szText
, gpointer user_data
) {
1581 gint displaylength
= g_utf8_strlen(szText
, -1);
1582 dasher_editor_delete(g_pEditor
, displaylength
);
1586 gtk2_edit_output_callback(GtkDasherControl
*pDasherControl
, const gchar
*szText
, gpointer user_data
) {
1587 dasher_editor_output(g_pEditor
, szText
);
1591 convert_cb(GtkDasherControl
*pDasherControl
, gpointer pUserData
) {
1592 dasher_editor_convert(g_pEditor
);
1596 protect_cb(GtkDasherControl
*pDasherControl
, gpointer pUserData
) {
1597 dasher_editor_protect(g_pEditor
);