6 #include "dasher_action_copy.h"
8 #include "dasher_action_keyboard.h"
10 #include "dasher_action_keyboard_maemo.h"
12 #include "dasher_action_script.h"
15 #include "dasher_action_speech.h"
17 #include "dasher_editor.h"
18 #include "dasher_external_buffer.h"
19 #include "dasher_internal_buffer.h"
20 #include "dasher_lock_dialogue.h"
22 #include "game_mode_helper.h"
23 #include "FontDialogues.h"
24 #include "GtkDasherControl.h"
26 #include "Preferences.h"
28 // TODO: Maybe reimplement something along the lines of the following, which used to be in edit.cc
31 // GtkTextIter oBufferEnd;
32 // GtkTextIter oBufferStart;
33 // gtk_text_buffer_get_bounds( the_text_buffer, &oBufferStart, &oBufferEnd);
34 // gtk_text_buffer_create_mark(the_text_buffer, "new_start", &oBufferEnd, true);
37 // const gchar *get_new_text() {
38 // GtkTextIter oNewStart;
39 // GtkTextIter oNewEnd;
40 // GtkTextIter oDummy;
42 // gtk_text_buffer_get_bounds( the_text_buffer, &oDummy, &oNewEnd);
43 // gtk_text_buffer_get_iter_at_mark( the_text_buffer, &oNewStart, gtk_text_buffer_get_mark(the_text_buffer, "new_start"));
45 // return gtk_text_buffer_get_text( the_text_buffer, &oNewStart, &oNewEnd, false );
51 #define ACTION_STATE_SHOW 1
52 #define ACTION_STATE_CONTROL 2
53 #define ACTION_STATE_AUTO 4
55 typedef struct _EditorAction EditorAction
;
57 struct _EditorAction
{
58 DasherAction
*pAction
;
60 EditorAction
*pPrevious
;
62 gint iID
; // TODO: does this need to be separate from iControlID?
68 static void dasher_editor_class_init(DasherEditorClass
*pClass
);
69 static void dasher_editor_init(DasherEditor
*pEditor
);
70 static void dasher_editor_destroy(GObject
*pObject
);
72 void dasher_editor_select_all(DasherEditor
*pSelf
);
73 void dasher_editor_setup_actions(DasherEditor
*pSelf
);
74 void dasher_editor_add_action(DasherEditor
*pSelf
, DasherAction
*pNewAction
);
75 EditorAction
*dasher_editor_get_action_by_id(DasherEditor
*pSelf
, int iID
);
76 void dasher_editor_rebuild_action_pane(DasherEditor
*pSelf
);
77 void dasher_editor_display_message(DasherEditor
*pSelf
, DasherMessageInfo
*pMessageInfo
);
78 void dasher_editor_handle_parameter_change(DasherEditor
*pSelf
, int iParameter
);
79 void dasher_editor_handle_pre_parameter_change(DasherEditor
*pSelf
, int iParameter
);
80 void dasher_editor_check_activity(DasherEditor
*pSelf
, EditorAction
*pAction
);
81 void dasher_editor_action_save_state(DasherEditor
*pSelf
, EditorAction
*pAction
);
83 // TODO: Should these be public?
84 void dasher_editor_convert(DasherEditor
*pSelf
);
85 void dasher_editor_protect(DasherEditor
*pSelf
);
87 // Private methods not in class
88 extern "C" void action_button_callback(GtkWidget
*pWidget
, gpointer pUserData
);
89 extern "C" void context_changed_handler(GObject
*pSource
, gpointer pUserData
);
90 extern "C" void main_window_realized(DasherMain
*pMain
, gpointer pUserData
);
92 typedef struct _DasherEditorPrivate DasherEditorPrivate
;
94 struct _DasherEditorPrivate
{
95 GtkTextView
*pTextView
;
96 GtkTextBuffer
*pBuffer
;
98 GtkClipboard
*pTextClipboard
;
99 GtkClipboard
*pPrimarySelection
;
100 EditorAction
*pActionRing
;
101 EditorAction
*pActionIter
;
102 gboolean bActionIterStarted
;
104 IDasherBufferSet
*pBufferSet
;
105 IDasherBufferSet
*pExternalBuffer
;
106 IDasherBufferSet
*pInternalBuffer
;
107 GameModeHelper
*pGameModeHelper
;
110 GType
dasher_editor_get_type() {
111 static GType dasher_editor_type
= 0;
113 if(!dasher_editor_type
) {
114 static const GTypeInfo dasher_editor_info
= {
115 sizeof(DasherEditorClass
),
118 (GClassInitFunc
) dasher_editor_class_init
,
121 sizeof(DasherEditor
),
123 (GInstanceInitFunc
) dasher_editor_init
,
127 dasher_editor_type
= g_type_register_static(G_TYPE_OBJECT
, "DasherEditor", &dasher_editor_info
, static_cast < GTypeFlags
> (0));
130 return dasher_editor_type
;
133 static void dasher_editor_class_init(DasherEditorClass
*pClass
) {
134 GObjectClass
*pObjectClass
= (GObjectClass
*) pClass
;
135 pObjectClass
->finalize
= dasher_editor_destroy
;
138 static void dasher_editor_init(DasherEditor
*pDasherControl
) {
139 pDasherControl
->private_data
= new DasherEditorPrivate
;
141 ((DasherEditorPrivate
*)(pDasherControl
->private_data
))->pBufferSet
= 0;
142 ((DasherEditorPrivate
*)(pDasherControl
->private_data
))->pInternalBuffer
= 0;
143 ((DasherEditorPrivate
*)(pDasherControl
->private_data
))->pExternalBuffer
= 0;
146 static void dasher_editor_destroy(GObject
*pObject
) {
147 // FIXME - I think we need to chain up through the finalize methods
148 // of the parent classes here...
149 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(((DasherEditor
*)pObject
)->private_data
);
151 EditorAction
*pCurrentAction
= pPrivate
->pActionRing
;
154 bool bStarted
= false;
156 while(!bStarted
|| (pCurrentAction
!= pPrivate
->pActionRing
)) {
158 dasher_action_deactivate(pCurrentAction
->pAction
);
159 g_object_unref(G_OBJECT(pCurrentAction
->pAction
));
160 pCurrentAction
= pCurrentAction
->pNext
;
164 if(pPrivate
->pBufferSet
)
165 g_object_unref(G_OBJECT(pPrivate
->pBufferSet
));
167 delete (DasherEditorPrivate
*)(((DasherEditor
*)pObject
)->private_data
);
170 DasherEditor
*dasher_editor_new(int argc
, char **argv
) {
171 DasherEditor
*pDasherControl
;
172 pDasherControl
= (DasherEditor
*)(g_object_new(dasher_editor_get_type(), NULL
));
174 return pDasherControl
;
177 void dasher_editor_initialise(DasherEditor
*pSelf
) {
178 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
180 GladeXML
*pGladeXML
= dasher_main_get_glade(g_pDasherMain
);
182 GtkTextView
*pTextView
= GTK_TEXT_VIEW(glade_xml_get_widget(pGladeXML
, "the_text_view"));
183 GtkVBox
*pActionPane
= GTK_VBOX(glade_xml_get_widget(pGladeXML
, "vbox39"));
185 pPrivate
->pTextView
= pTextView
;
186 pPrivate
->pBuffer
= gtk_text_view_get_buffer(pTextView
);
187 pPrivate
->pActionPane
= pActionPane
;
188 pPrivate
->pTextClipboard
= gtk_clipboard_get(GDK_SELECTION_CLIPBOARD
);
189 pPrivate
->pPrimarySelection
= gtk_clipboard_get(GDK_SELECTION_PRIMARY
);
190 pPrivate
->pActionRing
= NULL
;
191 pPrivate
->iNextActionID
= 0;
192 pPrivate
->pGameModeHelper
= 0;
194 dasher_editor_create_buffer(pSelf
);
195 dasher_editor_setup_actions(pSelf
);
199 IDasherBufferSet
*dasher_editor_get_buffer_set(DasherEditor
*pSelf
) {
200 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
201 return IDASHER_BUFFER_SET(dasher_internal_buffer_new(pPrivate
->pTextView
));
205 void dasher_editor_clipboard(DasherEditor
*pSelf
, clipboard_action act
) {
206 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
208 GtkTextIter
*start
= new GtkTextIter
;
209 GtkTextIter
*end
= new GtkTextIter
;
211 gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(pPrivate
->pBuffer
), start
, 0);
212 gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(pPrivate
->pBuffer
), end
, -1);
214 gchar
*the_text
= gtk_text_buffer_get_text(pPrivate
->pBuffer
, start
, end
, TRUE
);
218 gtk_text_buffer_cut_clipboard(pPrivate
->pBuffer
, pPrivate
->pTextClipboard
, TRUE
);
221 gtk_text_buffer_copy_clipboard(pPrivate
->pBuffer
, pPrivate
->pTextClipboard
);
223 case CLIPBOARD_PASTE
:
224 gtk_text_buffer_paste_clipboard(pPrivate
->pBuffer
, pPrivate
->pTextClipboard
, NULL
, TRUE
);
226 case CLIPBOARD_COPYALL
:
227 gtk_clipboard_set_text(pPrivate
->pTextClipboard
, the_text
, strlen(the_text
));
228 gtk_clipboard_set_text(pPrivate
->pPrimarySelection
, the_text
, strlen(the_text
));
231 case CLIPBOARD_SELECTALL
:
232 dasher_editor_select_all(pSelf
);
234 case CLIPBOARD_CLEAR
:
235 gtk_text_buffer_set_text(pPrivate
->pBuffer
, "", 0);
244 void dasher_editor_select_all(DasherEditor
*pSelf
) {
245 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
246 GtkTextIter
*start
, *end
;
248 start
= new GtkTextIter
;
249 end
= new GtkTextIter
;
251 gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(pPrivate
->pBuffer
), start
, 0);
252 gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(pPrivate
->pBuffer
), end
, -1);
254 GtkTextMark
*selection
= gtk_text_buffer_get_mark(pPrivate
->pBuffer
, "selection_bound");
255 GtkTextMark
*cursor
= gtk_text_buffer_get_mark(pPrivate
->pBuffer
, "insert");
257 gtk_text_buffer_move_mark(pPrivate
->pBuffer
, selection
, start
);
258 gtk_text_buffer_move_mark(pPrivate
->pBuffer
, cursor
, end
);
264 void dasher_editor_handle_stop(DasherEditor
*pSelf
) {
265 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
267 // See if anything is set to auto:
268 EditorAction
*pCurrentAction
= pPrivate
->pActionRing
;
271 bool bStarted
= false;
273 while(!bStarted
|| (pCurrentAction
!= pPrivate
->pActionRing
)) {
275 if(pCurrentAction
->bAuto
)
276 dasher_action_execute(pCurrentAction
->pAction
, dasher_editor_get_all_text(pSelf
));
277 pCurrentAction
= pCurrentAction
->pNext
;
282 void dasher_editor_handle_start(DasherEditor
*pSelf
) {
283 // The edit box keeps track of where we started
285 // TODO: This should be filtered through the buffer, rather than directly to the edit box
289 void dasher_editor_handle_control(DasherEditor
*pSelf
, int iNodeID
) {
290 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
292 if(iNodeID
== Dasher::CControlManager::CTL_USER
+ 1)
293 dasher_editor_clear(pSelf
, false); // Clear node is a special case (it shouldn't be)
295 EditorAction
*pCurrentAction
= pPrivate
->pActionRing
;
296 bool bStarted
= false;
298 while(!bStarted
|| (pCurrentAction
!= pPrivate
->pActionRing
)) {
300 if(pCurrentAction
->iControlID
== iNodeID
) {
301 dasher_action_execute(pCurrentAction
->pAction
, dasher_editor_get_all_text(pSelf
));
302 dasher_editor_clear(pSelf
, true);
304 pCurrentAction
= pCurrentAction
->pNext
;
309 // TODO: Think about changing signals so we don't need to do this translation
318 static struct SControlMap sMap
[] = {
319 {Dasher::CControlManager::CTL_MOVE_FORWARD_CHAR
, EDIT_FORWARDS
, EDIT_CHAR
, false},
320 {Dasher::CControlManager::CTL_MOVE_FORWARD_WORD
, EDIT_FORWARDS
, EDIT_WORD
, false},
321 {Dasher::CControlManager::CTL_MOVE_FORWARD_LINE
, EDIT_FORWARDS
, EDIT_LINE
, false},
322 {Dasher::CControlManager::CTL_MOVE_FORWARD_FILE
, EDIT_FORWARDS
, EDIT_FILE
, false},
323 {Dasher::CControlManager::CTL_MOVE_BACKWARD_CHAR
, EDIT_BACKWARDS
, EDIT_CHAR
, false},
324 {Dasher::CControlManager::CTL_MOVE_BACKWARD_WORD
, EDIT_BACKWARDS
, EDIT_WORD
, false},
325 {Dasher::CControlManager::CTL_MOVE_BACKWARD_LINE
, EDIT_BACKWARDS
, EDIT_LINE
, false},
326 {Dasher::CControlManager::CTL_MOVE_BACKWARD_FILE
, EDIT_BACKWARDS
, EDIT_FILE
, false},
327 {Dasher::CControlManager::CTL_DELETE_FORWARD_CHAR
, EDIT_FORWARDS
, EDIT_CHAR
, true},
328 {Dasher::CControlManager::CTL_DELETE_FORWARD_WORD
, EDIT_FORWARDS
, EDIT_WORD
, true},
329 {Dasher::CControlManager::CTL_DELETE_FORWARD_LINE
, EDIT_FORWARDS
, EDIT_LINE
, true},
330 {Dasher::CControlManager::CTL_DELETE_FORWARD_FILE
, EDIT_FORWARDS
, EDIT_FILE
, true},
331 {Dasher::CControlManager::CTL_DELETE_BACKWARD_CHAR
, EDIT_BACKWARDS
, EDIT_CHAR
, true},
332 {Dasher::CControlManager::CTL_DELETE_BACKWARD_WORD
, EDIT_BACKWARDS
, EDIT_WORD
, true},
333 {Dasher::CControlManager::CTL_DELETE_BACKWARD_LINE
, EDIT_BACKWARDS
, EDIT_LINE
, true},
334 {Dasher::CControlManager::CTL_DELETE_BACKWARD_FILE
, EDIT_BACKWARDS
, EDIT_FILE
, true}
337 if(pPrivate
->pBufferSet
) {
338 for(unsigned int i(0); i
< sizeof(sMap
)/sizeof(struct SControlMap
); ++i
) {
339 if(sMap
[i
].iEvent
== iNodeID
) {
341 idasher_buffer_set_edit_delete(pPrivate
->pBufferSet
, sMap
[i
].iDir
, sMap
[i
].iDist
);
343 idasher_buffer_set_edit_move(pPrivate
->pBufferSet
, sMap
[i
].iDir
, sMap
[i
].iDist
);
349 void dasher_editor_handle_parameter_change(DasherEditor
*pSelf
, int iParameter
) {
350 // switch(iParameter) {
351 // case APP_LP_STYLE:
352 // dasher_editor_create_buffer(pSelf);
356 dasher_preferences_dialogue_handle_parameter_change(g_pPreferencesDialogue
, iParameter
);
357 dasher_main_handle_parameter_change(g_pDasherMain
, iParameter
);
360 void dasher_editor_handle_pre_parameter_change(DasherEditor
*pSelf
, int iParameter
) {
361 dasher_main_handle_pre_parameter_change(g_pDasherMain
, iParameter
);
364 void dasher_editor_add_action(DasherEditor
*pSelf
, DasherAction
*pNewAction
) {
365 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
367 EditorAction
*pNewEditorAction
= new EditorAction
;
368 pNewEditorAction
->pAction
= pNewAction
;
369 pNewEditorAction
->iID
= pPrivate
->iNextActionID
;
370 ++pPrivate
->iNextActionID
;
372 gchar szRegistryName
[256];
373 strncpy(szRegistryName
, "Action_", 256);
374 strncat(szRegistryName
, dasher_action_get_name(pNewEditorAction
->pAction
), 255 - strlen(szRegistryName
));
376 for(unsigned int i(0); i
< strlen(szRegistryName
); ++i
)
377 if(szRegistryName
[i
] == ' ')
378 szRegistryName
[i
] = '_';
382 if(!dasher_app_settings_get_free_long(g_pDasherAppSettings
, szRegistryName
, iState
)) {
383 if(!strcmp(dasher_action_get_name(pNewEditorAction
->pAction
), "Speak"))
386 iState
= ACTION_STATE_SHOW
| ACTION_STATE_CONTROL
;
388 dasher_app_settings_set_free_long(g_pDasherAppSettings
, szRegistryName
, iState
);
391 pNewEditorAction
->bShow
= iState
& ACTION_STATE_SHOW
;
392 pNewEditorAction
->bControl
= iState
& ACTION_STATE_CONTROL
;
393 pNewEditorAction
->bAuto
= iState
& ACTION_STATE_AUTO
;
395 dasher_editor_check_activity(pSelf
, pNewEditorAction
);
397 if(pPrivate
->pActionRing
) {
398 pNewEditorAction
->pNext
= pPrivate
->pActionRing
;
399 pNewEditorAction
->pPrevious
= pPrivate
->pActionRing
->pPrevious
;
400 pPrivate
->pActionRing
->pPrevious
->pNext
= pNewEditorAction
;
401 pPrivate
->pActionRing
->pPrevious
= pNewEditorAction
;
404 pNewEditorAction
->pNext
= pNewEditorAction
;
405 pNewEditorAction
->pPrevious
= pNewEditorAction
;
408 pPrivate
->pActionRing
= pNewEditorAction
;
410 if(iState
& ACTION_STATE_SHOW
)
411 gtk_dasher_control_add_action_button(GTK_DASHER_CONTROL(pDasherWidget
), dasher_action_get_name(pNewEditorAction
->pAction
));
414 void dasher_editor_setup_actions(DasherEditor
*pSelf
) {
415 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
417 // TODO: Activate and deactivate methods for actions
418 // TODO: Clear shouldn't be a special case (include support for false in clear method)
421 dasher_editor_add_action(pSelf
, DASHER_ACTION(dasher_action_speech_new()));
424 dasher_editor_add_action(pSelf
, DASHER_ACTION(dasher_action_keyboard_new(pPrivate
->pExternalBuffer
)));
427 dasher_editor_add_action(pSelf
, DASHER_ACTION(dasher_action_keyboard_maemo_new()));
429 dasher_editor_add_action(pSelf
, DASHER_ACTION(dasher_action_copy_new(pSelf
)));
432 G_CONST_RETURN gchar
*szFilename
;
434 gchar
*szUserScriptDir
= new gchar
[strlen(dasher_app_settings_get_string(g_pDasherAppSettings
, SP_USER_LOC
))+9];
435 strcpy(szUserScriptDir
, dasher_app_settings_get_string(g_pDasherAppSettings
, SP_USER_LOC
));
436 strcat(szUserScriptDir
, "scripts/");
438 pDirectory
= g_dir_open(szUserScriptDir
, 0, NULL
);
441 while((szFilename
= g_dir_read_name(pDirectory
))) {
442 dasher_editor_add_action(pSelf
, DASHER_ACTION(dasher_action_script_new(szUserScriptDir
, szFilename
)));
445 g_dir_close(pDirectory
);
448 delete[] szUserScriptDir
;
450 gchar
*szSystemScriptDir
= new gchar
[strlen(dasher_app_settings_get_string(g_pDasherAppSettings
, SP_SYSTEM_LOC
))+9];
451 strcpy(szSystemScriptDir
, dasher_app_settings_get_string(g_pDasherAppSettings
, SP_SYSTEM_LOC
));
452 strcat(szSystemScriptDir
, "scripts/");
454 pDirectory
= g_dir_open(szSystemScriptDir
, 0, NULL
);
457 while((szFilename
= g_dir_read_name(pDirectory
))) {
458 dasher_editor_add_action(pSelf
, DASHER_ACTION(dasher_action_script_new(szSystemScriptDir
, szFilename
)));
461 g_dir_close(pDirectory
);
464 delete[] szSystemScriptDir
;
467 gtk_dasher_control_register_node( GTK_DASHER_CONTROL(pDasherWidget
), Dasher::CControlManager::CTL_USER
, "Actions", -1 );
468 gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pDasherWidget
), Dasher::CControlManager::CTL_USER
, Dasher::CControlManager::CTL_ROOT
, -2);
469 int iControlOffset(1);
471 gtk_dasher_control_register_node( GTK_DASHER_CONTROL(pDasherWidget
), Dasher::CControlManager::CTL_USER
+ iControlOffset
, "Clear", -1 );
472 gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pDasherWidget
), Dasher::CControlManager::CTL_USER
+ iControlOffset
, Dasher::CControlManager::CTL_USER
, -2);
473 gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pDasherWidget
), -1, Dasher::CControlManager::CTL_USER
+ iControlOffset
, -2);
476 EditorAction
*pCurrentAction
= pPrivate
->pActionRing
;
477 bool bStarted
= false;
479 while(!bStarted
|| (pCurrentAction
!= pPrivate
->pActionRing
)) {
482 gtk_dasher_control_register_node( GTK_DASHER_CONTROL(pDasherWidget
), Dasher::CControlManager::CTL_USER
+ iControlOffset
, dasher_action_get_name(pCurrentAction
->pAction
), -1 );
483 gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pDasherWidget
), Dasher::CControlManager::CTL_USER
+ iControlOffset
, Dasher::CControlManager::CTL_USER
, -2);
484 gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pDasherWidget
), -1, Dasher::CControlManager::CTL_USER
+ iControlOffset
, -2);
485 pCurrentAction
->iControlID
= Dasher::CControlManager::CTL_USER
+ iControlOffset
;
488 pCurrentAction
= pCurrentAction
->pNext
;
491 #ifndef WITH_MAEMOFULLSCREEN
492 // dasher_editor_rebuild_action_pane(pSelf);
496 extern "C" void delete_children_callback(GtkWidget
*pWidget
, gpointer pUserData
) {
497 gtk_widget_destroy(pWidget
);
500 extern "C" void main_window_realized(DasherMain
*pMain
, gpointer pUserData
) {
504 void dasher_editor_rebuild_action_pane(DasherEditor
*pSelf
) {
505 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
507 // Delete any existing widgets
508 gtk_container_foreach(GTK_CONTAINER(pPrivate
->pActionPane
), delete_children_callback
, 0);
510 // Add the cancel button
511 GtkButton
*pNewButton
= GTK_BUTTON(gtk_button_new_with_label("Clear"));
512 gtk_widget_show(GTK_WIDGET(pNewButton
));
514 void **pUserData
= new void *[2];
515 pUserData
[0] = (void *)pSelf
;
518 g_signal_connect(G_OBJECT(pNewButton
), "clicked", G_CALLBACK(action_button_callback
), pUserData
);
520 // For Maemo we want the packing to expand
521 gtk_box_pack_start(GTK_BOX(pPrivate
->pActionPane
), GTK_WIDGET(pNewButton
), true, true, 0);
523 gtk_box_pack_start(GTK_BOX(pPrivate
->pActionPane
), GTK_WIDGET(pNewButton
), false, false, 0);
527 EditorAction
*pCurrentAction
= pPrivate
->pActionRing
;
528 bool bStarted
= false;
530 while(!bStarted
|| (pCurrentAction
!= pPrivate
->pActionRing
)) {
532 if(pCurrentAction
->bShow
) {
533 GtkButton
*pNewButton
= GTK_BUTTON(gtk_button_new_with_label(dasher_action_get_name(pCurrentAction
->pAction
)));
534 gtk_widget_show(GTK_WIDGET(pNewButton
));
536 pUserData
= new void *[2];
537 pUserData
[0] = (void *)pSelf
;
538 pUserData
[1] = (void *)(pCurrentAction
->pAction
);
540 g_signal_connect(G_OBJECT(pNewButton
), "clicked", G_CALLBACK(action_button_callback
), pUserData
);
542 // For Maemo we want the packing to expand
543 gtk_box_pack_start(GTK_BOX(pPrivate
->pActionPane
), GTK_WIDGET(pNewButton
), true, true, 0);
545 gtk_box_pack_start(GTK_BOX(pPrivate
->pActionPane
), GTK_WIDGET(pNewButton
), false, false, 0);
548 pCurrentAction
= pCurrentAction
->pNext
;
552 // TODO: We shouldn't need to know about the buffer here - make this a method of the buffer set
553 const gchar
*dasher_editor_get_all_text(DasherEditor
*pSelf
) {
554 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
559 gtk_text_buffer_get_start_iter(pPrivate
->pBuffer
, &oStart
);
560 gtk_text_buffer_get_end_iter(pPrivate
->pBuffer
, &oEnd
);
562 return gtk_text_buffer_get_text(pPrivate
->pBuffer
, &oStart
, &oEnd
, false );
565 void dasher_editor_action_button(DasherEditor
*pSelf
, DasherAction
*pAction
) {
567 dasher_action_execute(pAction
, dasher_editor_get_all_text(pSelf
));
568 dasher_editor_clear(pSelf
, true);
570 else { // Clear button
571 dasher_editor_clear(pSelf
, false);
575 void dasher_editor_clear(DasherEditor
*pSelf
, gboolean bStore
) {
576 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
578 if(IS_DASHER_INTERNAL_BUFFER(pPrivate
->pBufferSet
))
579 dasher_internal_buffer_clear(DASHER_INTERNAL_BUFFER(pPrivate
->pBufferSet
));
583 void dasher_editor_actions_start(DasherEditor
*pSelf
) {
584 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
586 pPrivate
->bActionIterStarted
= false;
587 pPrivate
->pActionIter
= pPrivate
->pActionRing
;
590 bool dasher_editor_actions_more(DasherEditor
*pSelf
) {
591 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
593 return(!pPrivate
->bActionIterStarted
|| (pPrivate
->pActionIter
!= pPrivate
->pActionRing
));
596 void dasher_editor_actions_get_next(DasherEditor
*pSelf
, const gchar
**szName
, gint
*iID
, gboolean
*bShow
, gboolean
*bControl
, gboolean
*bAuto
) {
597 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
599 *szName
= dasher_action_get_name(pPrivate
->pActionIter
->pAction
);
600 *iID
= pPrivate
->pActionIter
->iID
;
601 *bShow
= pPrivate
->pActionIter
->bShow
;
602 *bControl
= pPrivate
->pActionIter
->bControl
;
603 *bAuto
= pPrivate
->pActionIter
->bAuto
;
605 pPrivate
->pActionIter
= pPrivate
->pActionIter
->pNext
;
606 pPrivate
->bActionIterStarted
= true;
609 void dasher_editor_action_set_show(DasherEditor
*pSelf
, int iActionID
, bool bValue
) {
610 EditorAction
*pAction
;
611 pAction
= dasher_editor_get_action_by_id(pSelf
, iActionID
);
614 pAction
->bShow
= bValue
;
615 dasher_editor_check_activity(pSelf
, pAction
);
616 dasher_editor_rebuild_action_pane(pSelf
);
618 dasher_editor_action_save_state(pSelf
, pAction
);
622 void dasher_editor_action_set_control(DasherEditor
*pSelf
, int iActionID
, bool bValue
) {
623 // TODO: Need to actually change behaviour in resonse to these calls
625 EditorAction
*pAction
;
626 pAction
= dasher_editor_get_action_by_id(pSelf
, iActionID
);
629 pAction
->bControl
= bValue
;
630 dasher_editor_check_activity(pSelf
, pAction
);
632 gtk_dasher_control_connect_node(GTK_DASHER_CONTROL(pDasherWidget
), pAction
->iControlID
, Dasher::CControlManager::CTL_USER
, -2);
634 gtk_dasher_control_disconnect_node(GTK_DASHER_CONTROL(pDasherWidget
), pAction
->iControlID
, Dasher::CControlManager::CTL_USER
);
636 dasher_editor_action_save_state(pSelf
, pAction
);
640 void dasher_editor_action_set_auto(DasherEditor
*pSelf
, int iActionID
, bool bValue
) {
641 EditorAction
*pAction
;
642 pAction
= dasher_editor_get_action_by_id(pSelf
, iActionID
);
645 pAction
->bAuto
= bValue
;
646 dasher_editor_check_activity(pSelf
, pAction
);
648 dasher_editor_action_save_state(pSelf
, pAction
);
652 void dasher_editor_action_save_state(DasherEditor
*pSelf
, EditorAction
*pAction
) {
653 gchar szRegistryName
[256];
654 strncpy(szRegistryName
, "Action_", 256);
655 strncat(szRegistryName
, dasher_action_get_name(pAction
->pAction
), 255 - strlen(szRegistryName
));
657 for(unsigned int i(0); i
< strlen(szRegistryName
); ++i
)
658 if(szRegistryName
[i
] == ' ')
659 szRegistryName
[i
] = '_';
664 iState
+= ACTION_STATE_SHOW
;
666 if(pAction
->bControl
)
667 iState
+= ACTION_STATE_CONTROL
;
670 iState
+= ACTION_STATE_AUTO
;
672 dasher_app_settings_set_free_long(g_pDasherAppSettings
, szRegistryName
, iState
);
675 void dasher_editor_output(DasherEditor
*pSelf
, const gchar
*szText
) {
676 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
678 if(pPrivate
->pBufferSet
)
679 idasher_buffer_set_insert(pPrivate
->pBufferSet
, szText
);
681 if(pPrivate
->pGameModeHelper
)
682 game_mode_helper_output(pPrivate
->pGameModeHelper
, szText
);
685 void dasher_editor_delete(DasherEditor
*pSelf
, int iLength
) {
686 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
688 if(pPrivate
->pBufferSet
)
689 idasher_buffer_set_delete(pPrivate
->pBufferSet
, iLength
);
691 if(pPrivate
->pGameModeHelper
)
692 game_mode_helper_delete(pPrivate
->pGameModeHelper
, iLength
);
695 void dasher_editor_convert(DasherEditor
*pSelf
) {
696 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
698 if(pPrivate
->pBufferSet
)
699 idasher_buffer_set_edit_convert(pPrivate
->pBufferSet
);
702 void dasher_editor_protect(DasherEditor
*pSelf
) {
703 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
705 if(pPrivate
->pBufferSet
)
706 idasher_buffer_set_edit_protect(pPrivate
->pBufferSet
);
709 EditorAction
*dasher_editor_get_action_by_id(DasherEditor
*pSelf
, int iID
){
710 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
712 EditorAction
*pCurrentAction
= pPrivate
->pActionRing
;
713 bool bStarted
= false;
715 while(!bStarted
|| (pCurrentAction
!= pPrivate
->pActionRing
)) {
717 if(pCurrentAction
->iID
== iID
)
718 return pCurrentAction
;
719 pCurrentAction
= pCurrentAction
->pNext
;
725 void dasher_editor_create_buffer(DasherEditor
*pSelf
) {
726 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
728 if(!(pPrivate
->pExternalBuffer
))
729 pPrivate
->pExternalBuffer
= IDASHER_BUFFER_SET(dasher_external_buffer_new());
731 if(!(pPrivate
->pInternalBuffer
)) {
732 pPrivate
->pInternalBuffer
= dasher_editor_get_buffer_set(pSelf
);
733 idasher_buffer_set_conversion_mode(pPrivate
->pInternalBuffer
, gtk_dasher_control_get_parameter_bool(GTK_DASHER_CONTROL(pDasherWidget
), BP_CONVERSION_MODE
));
736 if(dasher_app_settings_get_long(g_pDasherAppSettings
, APP_LP_STYLE
) == 2)
737 pPrivate
->pBufferSet
= pPrivate
->pExternalBuffer
;
739 pPrivate
->pBufferSet
= pPrivate
->pInternalBuffer
;
743 g_signal_connect(G_OBJECT(pPrivate
->pBufferSet
), "context_changed", G_CALLBACK(context_changed_handler
), NULL
);
747 void dasher_editor_refresh_context(DasherEditor
*pSelf
, int iMaxLength
) {
748 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
752 if(pPrivate
->pBufferSet
)
753 szContext
= idasher_buffer_set_get_context(pPrivate
->pBufferSet
, iMaxLength
);
757 if(szContext
&& (strlen(szContext
) > 0))
758 gtk_dasher_control_set_context( GTK_DASHER_CONTROL(pDasherWidget
), szContext
);
761 void dasher_editor_display_message(DasherEditor
*pSelf
, DasherMessageInfo
*pMessageInfo
) {
762 GtkMessageDialog
*pDialog
= GTK_MESSAGE_DIALOG(gtk_message_dialog_new(0, GTK_DIALOG_MODAL
, GTK_MESSAGE_INFO
, GTK_BUTTONS_OK
, pMessageInfo
->szMessage
));
763 gtk_dialog_run(GTK_DIALOG(pDialog
));
764 gtk_widget_destroy(GTK_WIDGET(pDialog
));
767 void dasher_editor_generate_filename(DasherEditor
*pSelf
) {
768 if( dasher_app_settings_get_bool(g_pDasherAppSettings
, APP_BP_TIME_STAMP
)) {
769 // Build a filename based on the current time and date
777 t_struct
= localtime(&ctime
);
780 g_free((void *)filename
);
784 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
);
786 filename
= g_build_path("/", cwd
, tbuffer
, NULL
);
790 g_free((void *)filename
);
795 // TODO: Rationalise this - should probably be in 'new' function rather than here
796 dasher_main_set_filename(g_pDasherMain
, filename
);
799 // TODO: Rationalise this
800 void dasher_editor_open(DasherEditor
*pSelf
, const gchar
*szFilename
) {
801 open_file(szFilename
);
804 // TODO: Rationalise this
805 bool dasher_editor_save_as(DasherEditor
*pSelf
, const gchar
*szFilename
, bool bAppend
) {
806 return save_file_as(szFilename
, bAppend
);
809 void dasher_editor_check_activity(DasherEditor
*pSelf
, EditorAction
*pAction
) {
810 gboolean
bNeedActive(pAction
->bShow
|| pAction
->bControl
|| pAction
->bAuto
);
811 gboolean
bActive(dasher_action_get_active(pAction
->pAction
));
813 if(bNeedActive
&& !bActive
)
814 dasher_action_activate(pAction
->pAction
);
815 else if(!bNeedActive
&& bActive
)
816 dasher_action_deactivate(pAction
->pAction
);
819 void dasher_editor_start_tutorial(DasherEditor
*pSelf
) {
820 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
822 pPrivate
->pGameModeHelper
= GAME_MODE_HELPER(game_mode_helper_new(GTK_DASHER_CONTROL(pDasherWidget
)));
825 void dasher_editor_command(DasherEditor
*pSelf
, const gchar
*szCommand
) {
826 DasherEditorPrivate
*pPrivate
= (DasherEditorPrivate
*)(pSelf
->private_data
);
828 if(!strcmp(szCommand
, "Preferences")) {
829 dasher_preferences_dialogue_show(g_pPreferencesDialogue
);
831 else if(!strcmp(szCommand
, "Exit")) {
832 ask_save_before_exit(NULL
, NULL
);
834 else if(!strcmp(szCommand
, "Help")) {
835 show_help(NULL
, NULL
);
837 else if(!strcmp(szCommand
, "About")) {
838 about_dasher(NULL
, NULL
);
841 bool bActionIterStarted
= false;
842 EditorAction
*pActionIter
= pPrivate
->pActionRing
;
844 while((pActionIter
!= pPrivate
->pActionRing
) || !bActionIterStarted
) {
845 bActionIterStarted
= true;
847 if(!strcmp(dasher_action_get_name(pActionIter
->pAction
), szCommand
)) {
848 dasher_action_execute(pActionIter
->pAction
, dasher_editor_get_all_text(pSelf
));
852 pActionIter
= pActionIter
->pNext
;
859 extern "C" void action_button_callback(GtkWidget
*pWidget
, gpointer pUserData
) {
860 void **pPointers((void **)pUserData
);
861 dasher_editor_action_button((DasherEditor
*)pPointers
[0], (DasherAction
*)pPointers
[1]);
864 // NOTE: The next two aren't real signals
865 extern "C" void pre_parameter_notification(GtkDasherControl
*pDasherControl
, gint iParameter
, gpointer data
) {
867 dasher_editor_handle_pre_parameter_change(g_pEditor
, iParameter
);
870 extern "C" void parameter_notification(GtkDasherControl
*pDasherControl
, gint iParameter
, gpointer data
) {
872 dasher_editor_handle_parameter_change(g_pEditor
, iParameter
);
875 extern "C" void handle_start_event(GtkDasherControl
*pDasherControl
, gpointer data
) {
877 dasher_editor_handle_start(g_pEditor
);
880 extern "C" void handle_stop_event(GtkDasherControl
*pDasherControl
, gpointer data
) {
882 dasher_editor_handle_stop(g_pEditor
);
885 extern "C" void handle_context_request(GtkDasherControl
* pDasherControl
, gint iMaxLength
, gpointer data
) {
887 dasher_editor_refresh_context(g_pEditor
, iMaxLength
);
890 extern "C" void handle_control_event(GtkDasherControl
*pDasherControl
, gint iEvent
, gpointer data
) {
892 dasher_editor_handle_control(g_pEditor
, iEvent
);
895 extern "C" void on_message(GtkDasherControl
*pDasherControl
, gpointer pMessageInfo
, gpointer pUserData
) {
897 dasher_editor_display_message(g_pEditor
, (DasherMessageInfo
*)pMessageInfo
);
901 extern "C" void on_command(GtkDasherControl
*pDasherControl
, gchar
*szCommand
, gpointer pUserData
) {
903 dasher_editor_command(g_pEditor
, szCommand
);
907 // TODO: The following two should probably be made the same
908 extern "C" void handle_request_settings(GtkDasherControl
* pDasherControl
, gpointer data
) {
909 dasher_preferences_dialogue_show(g_pPreferencesDialogue
);
912 extern "C" void preferences_display(GtkWidget
*widget
, gpointer user_data
) {
913 dasher_preferences_dialogue_show(g_pPreferencesDialogue
);
916 extern "C" void gtk2_edit_delete_callback(GtkDasherControl
*pDasherControl
, const gchar
*szText
, gpointer user_data
) {
917 gint displaylength
= g_utf8_strlen(szText
, -1);
918 dasher_editor_delete(g_pEditor
, displaylength
);
921 extern "C" void gtk2_edit_output_callback(GtkDasherControl
*pDasherControl
, const gchar
*szText
, gpointer user_data
) {
922 dasher_editor_output(g_pEditor
, szText
);
925 extern "C" void convert_cb(GtkDasherControl
*pDasherControl
, gpointer pUserData
) {
926 dasher_editor_convert(g_pEditor
);
929 extern "C" void protect_cb(GtkDasherControl
*pDasherControl
, gpointer pUserData
) {
930 dasher_editor_protect(g_pEditor
);
933 // TODO: This should call back into editor, not directly into Dasher control
934 extern "C" void context_changed_handler(GObject
*pSource
, gpointer pUserData
) {
935 gtk_dasher_control_invalidate_context(GTK_DASHER_CONTROL(pDasherWidget
), false);