#575365 - nothing happens when you click on contents, so hide it for now.
[dasher.git] / Src / Gtk2 / dasher_main.cpp
blob8dd2d1f6e87d56d87222439885f582c9d9be4e1c
1 #ifdef HAVE_CONFIG_H
2 #include <config.h>
3 #endif
5 #include <cstring>
7 #include <gdk/gdk.h>
8 #include <gdk/gdkx.h>
9 #include <glade/glade.h>
10 #include <glib/gi18n.h>
11 #include <gtk/gtk.h>
12 #ifdef WITH_MAEMOFULLSCREEN
13 #include <hildon-widgets/hildon-program.h>
14 #endif
15 #ifdef GNOME_LIBS
16 #include <libgnome/libgnome.h>
17 #endif
18 #include <unistd.h>
20 #include "GtkDasherControl.h"
21 #include "KeyboardHelper.h"
22 #include "Preferences.h"
23 #include "dasher_lock_dialogue.h"
24 #ifdef WITH_MAEMO
25 #include "dasher_maemo_helper.h"
26 #endif
27 #include "dasher_main.h"
29 #include "DasherAppSettings.h"
30 #include "dasher_editor_internal.h"
31 #include "dasher_editor_external.h"
33 /* Static instance of singleton, USE SPARINGLY */
34 static DasherMain *g_pDasherMain = NULL;
36 // TODO: The following global variable makes control mode editing work
37 // - this needs to be sorted out properly.
38 static gboolean g_bSend = true;
40 struct _DasherMainPrivate {
41 GladeXML *pGladeXML;
42 GladeXML *pPrefXML;
44 // Child objects owned here
45 DasherAppSettings *pAppSettings;
46 DasherPreferencesDialogue *pPreferencesDialogue;
47 DasherEditor *pEditor;
49 CKeyboardHelper *pKeyboardHelper;
51 // Various widgets which need to be cached:
52 GtkWidget *pBufferView;
53 GtkWidget *pDivider;
54 GtkWidget *pMainWindow;
55 GtkWidget *pToolbar;
56 GtkWidget *pSpeedBox;
57 GtkWidget *pAlphabetCombo;
58 GtkWidget *pStatusControl;
59 GtkWidget *pDasherWidget;
61 GtkListStore *pAlphabetList;
62 GtkAccelGroup *pAccel;
63 gulong iAlphabetComboHandler;
65 // Widgets used for maemo
66 #ifdef WITH_MAEMO
67 DasherMaemoHelper *pMaemoHelper;
68 #ifdef WITH_MAEMOFULLSCREEN
69 HildonProgram *pProgram;
70 HildonWindow *pHWindow;
71 #endif
72 #endif
74 // Properties of the main window
75 int iWidth;
76 int iHeight;
77 bool bWidgetsInitialised;
80 typedef struct _DasherMainPrivate DasherMainPrivate;
82 // TODO: Make sure this is actually used
83 #define DASHER_MAIN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), TYPE_DASHER_MAIN, DasherMainPrivate))
85 enum {
86 REALIZED,
87 SIGNAL_NUM
90 static guint dasher_main_signals[SIGNAL_NUM] = { 0 };
92 /* Automatic command hookups */
94 typedef struct _DasherMenuCommand DasherMenuCommand;
96 struct _DasherMenuCommand {
97 GtkWidget *pWidget;
98 const gchar *szWidgetName;
99 const gchar *szCommand;
102 static DasherMenuCommand MenuCommands[] = {
103 /* Menus */
104 {NULL, "menu_command_new", "new"},
105 {NULL, "menu_command_open", "open"},
106 {NULL, "menu_command_save", "save"},
107 {NULL, "menu_command_saveas", "saveas"},
108 {NULL, "menu_command_append", "append"},
109 {NULL, "menu_command_import", "import"},
110 {NULL, "menu_command_quit", "quit"},
111 {NULL, "menu_command_cut", "cut"},
112 {NULL, "menu_command_copy", "copy"},
113 {NULL, "menu_command_copyall", "copyall"},
114 {NULL, "menu_command_paste", "paste"},
115 {NULL, "menu_command_preferences", "preferences"},
116 {NULL, "menu_command_tutorial", "tutorial"},
117 {NULL, "menu_command_help", "help"},
118 {NULL, "menu_command_about", "about"},
120 /* Toolbar */
121 {NULL, "tb_command_new", "new"},
122 {NULL, "tb_command_open", "open"},
123 {NULL, "tb_command_save", "save"},
124 {NULL, "tb_command_saveas", "saveas"},
125 {NULL, "tb_command_cut", "cut"},
126 {NULL, "tb_command_copy", "copy"},
127 {NULL, "tb_command_paste", "paste"},
128 {NULL, "tb_command_preferences", "preferences"},
129 {NULL, "tb_command_help", "help"},
130 {NULL, "tb_command_quit", "quit"}
133 G_DEFINE_TYPE(DasherMain, dasher_main, G_TYPE_OBJECT);
135 static void dasher_main_finalize(GObject *pObject);
137 /* Private member functions */
138 static void dasher_main_setup_window_state(DasherMain *pSelf);
139 static void dasher_main_setup_window_style(DasherMain *pSelf);
140 static void dasher_main_setup_internal_layout(DasherMain *pSelf);
141 //static void dasher_main_refresh_font(DasherMain *pSelf);
142 static void dasher_main_set_window_title(DasherMain *pSelf);
144 /* ... Table based menu/toolbar commands */
145 static void dasher_main_connect_menus(DasherMain *pSelf);
146 static void dasher_main_menu_command(DasherMain *pSelf, GtkWidget *pWidget);
148 static void dasher_main_command_import(DasherMain *pSelf);
149 static void dasher_main_command_quit(DasherMain *pSelf);
150 static void dasher_main_command_preferences(DasherMain *pSelf);
151 static void dasher_main_command_preferences_alphabet(DasherMain *pSelf);
152 static void dasher_main_command_tutorial(DasherMain *pSelf);
153 static void dasher_main_command_help(DasherMain *pSelf);
154 static void dasher_main_command_about(DasherMain *pself);
156 static gboolean dasher_main_speed_changed(DasherMain *pSelf);
157 static void dasher_main_alphabet_combo_changed(DasherMain *pSelf);
158 // TODO: populate speed slider
159 static void dasher_main_populate_alphabet_combo(DasherMain *pSelf);
161 /* TODO: order these in file */
162 static GladeXML *dasher_main_open_glade_xml(const char *szGladeFilename);
163 static void dasher_main_load_interface(DasherMain *pSelf);
164 static void dasher_main_create_preferences(DasherMain *pSelf);
165 static void dasher_main_handle_parameter_change(DasherMain *pSelf, int iParameter);
166 static void dasher_main_load_state(DasherMain *pSelf);
167 static void dasher_main_save_state(DasherMain *pSelf);
168 static void dasher_main_setup_window(DasherMain *pSelf);
169 static void dasher_main_populate_controls(DasherMain *pSelf);
170 static void dasher_main_connect_control(DasherMain *pSelf);
171 static gboolean dasher_main_command(DasherMain *pSelf, const gchar *szCommand);
172 static gint dasher_main_lookup_key(DasherMain *pSelf, guint iKeyVal);
174 /* TODO: Various functions which haven't yet been rationalised */
175 gboolean grab_focus();
177 // TODO: Sort out callbacks - 1 rename, 2 check return values
179 /* Callback functions */
180 extern "C" GtkWidget *create_dasher_control(gchar *szName, gchar *szString1, gchar *szString2, gint iInt1, gint iInt2);
181 extern "C" GtkWidget *create_dasher_editor(gchar *szName, gchar *szString1, gchar *szString2, gint iInt1, gint iInt2);
183 /* ... Message handling from main window widgets */
184 extern "C" gboolean dasher_main_cb_menu_command(GtkWidget *pWidget, gpointer pUserData);
185 extern "C" gboolean speed_changed(GtkWidget *pWidget, gpointer user_data);
186 extern "C" void alphabet_combo_changed(GtkWidget *pWidget, gpointer pUserData);
187 extern "C" void dasher_main_cb_filename_changed(DasherEditor *pEditor, gpointer pUserData);
188 extern "C" void dasher_main_cb_buffer_changed(DasherEditor *pEditor, gpointer pUserData);
189 extern "C" void dasher_main_cb_context_changed(DasherEditor *pEditor, gpointer pUserData);
190 extern "C" gboolean dasher_main_cb_window_close(GtkWidget *pWidget, gpointer pUserData);
191 extern "C" void parameter_notification(GtkDasherControl *pDasherControl, gint iParameter, gpointer data);
193 /* ... Focus management and event forwarding */
194 extern "C" bool focus_in_event(GtkWidget *widget, GdkEventFocus *event, gpointer data);
195 extern "C" bool edit_focus_in_event(GtkWidget *widget, GdkEventFocus *event, gpointer data);
196 extern "C" gboolean take_real_focus(GtkWidget *widget, GdkEventFocus *event, gpointer user_data);
198 extern "C" gboolean edit_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data);
199 extern "C" gboolean edit_key_release(GtkWidget *widget, GdkEventKey *event, gpointer user_data);
201 /* ... Temporary test/debug functions */
202 extern "C" gboolean test_focus_handler(GtkWidget *pWidget, GtkDirectionType iDirection, gpointer *pUserData);
204 extern "C" void handle_context_request(GtkDasherControl * pDasherControl, gint iOffset, gint iLength, gpointer data);
205 extern "C" void handle_control_event(GtkDasherControl *pDasherControl, gint iEvent, gpointer data);
206 extern "C" void handle_start_event(GtkDasherControl *pDasherControl, gpointer data);
207 extern "C" gint dasher_main_key_snooper(GtkWidget *pWidget, GdkEventKey *pEvent, gpointer pUserData);
209 /* Boilerplate code */
210 static void
211 dasher_main_class_init(DasherMainClass *pClass) {
212 g_type_class_add_private(pClass, sizeof(DasherMainPrivate));
214 dasher_main_signals[REALIZED] = g_signal_new("realized", G_TYPE_FROM_CLASS(pClass),
215 (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
216 G_STRUCT_OFFSET(DasherMainClass, realized),
217 NULL, NULL, g_cclosure_marshal_VOID__VOID,
218 G_TYPE_NONE, 0);
220 GObjectClass *pObjectClass = (GObjectClass *)pClass;
221 pObjectClass->finalize = dasher_main_finalize;
224 static void
225 dasher_main_init(DasherMain *pDasherMain) {
226 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pDasherMain);
228 pPrivate->pAppSettings = NULL;
229 pPrivate->pEditor = NULL;
230 pPrivate->pPreferencesDialogue = NULL;
232 pPrivate->pKeyboardHelper = new CKeyboardHelper(NULL);
234 pPrivate->bWidgetsInitialised = false;
237 static void
238 dasher_main_finalize(GObject *pObject) {
240 DasherMain *pDasherMain = DASHER_MAIN(pObject);
241 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pDasherMain);
243 dasher_main_save_state(pDasherMain);
245 /* TODO: Does unref really do the right thing - check the whole ref counting situation */
246 // if(pPrivate->pEditor)
247 // g_object_unref(pPrivate->pEditor);
249 if(pPrivate->pPreferencesDialogue)
250 g_object_unref(pPrivate->pPreferencesDialogue);
252 if(pPrivate->pAppSettings)
253 g_object_unref(pPrivate->pAppSettings);
255 gtk_widget_destroy(pPrivate->pMainWindow);
257 /* TODO: Do we need to take down anything else? */
260 /* Public methods */
261 DasherMain *
262 dasher_main_new(int *argc, char ***argv, SCommandLine *pCommandLine) {
263 if(g_pDasherMain)
264 return g_pDasherMain;
265 else {
266 DasherMain *pDasherMain = (DasherMain *)(g_object_new(dasher_main_get_type(), NULL));
267 g_pDasherMain = pDasherMain;
269 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pDasherMain);
271 /* Create the app settings object */
272 pPrivate->pAppSettings = dasher_app_settings_new(*argc, *argv);
274 /* Load the user interface from the glade file */
275 if(pCommandLine && pCommandLine->szAppStyle) {
276 if(!strcmp(pCommandLine->szAppStyle, "traditional")) {
277 dasher_app_settings_set_long(pPrivate->pAppSettings, APP_LP_STYLE, APP_STYLE_TRAD);
279 else if(!strcmp(pCommandLine->szAppStyle, "compose")) {
280 dasher_app_settings_set_long(pPrivate->pAppSettings, APP_LP_STYLE, APP_STYLE_COMPOSE);
282 else if(!strcmp(pCommandLine->szAppStyle, "direct")) {
283 dasher_app_settings_set_long(pPrivate->pAppSettings, APP_LP_STYLE, APP_STYLE_DIRECT);
285 else if(!strcmp(pCommandLine->szAppStyle, "fullscreen")) {
286 dasher_app_settings_set_long(pPrivate->pAppSettings, APP_LP_STYLE, APP_STYLE_FULLSCREEN);
288 else {
289 g_critical("Application style %s is not supported", pCommandLine->szAppStyle);
290 return 0;
293 else {
294 // By default use traditional mode
295 dasher_app_settings_set_long(pPrivate->pAppSettings, APP_LP_STYLE, APP_STYLE_TRAD);
298 dasher_main_load_interface(pDasherMain);
300 dasher_app_settings_set_widget(pPrivate->pAppSettings, GTK_DASHER_CONTROL(pPrivate->pDasherWidget));
303 /* TODO: This parsing code should really be tidied up */
304 if(pCommandLine && pCommandLine->szOptions) {
305 gchar **pszOptionTerms;
306 pszOptionTerms = g_strsplit(pCommandLine->szOptions, ",", 0);
308 gchar **pszCurrent = pszOptionTerms;
310 while(*pszCurrent) {
311 gchar *szJoin = g_strrstr(*pszCurrent, "=");
312 // Note to translators: This message will be output for command line errors when the "=" in --options=foo is missing.
313 const gchar *errorMessage = _("option setting is missing \"=\".");
315 if(szJoin) {
316 int iLength = szJoin - *pszCurrent;
318 gchar *szKey = g_new(gchar, iLength + 1);
319 memcpy(szKey, *pszCurrent, iLength);
320 szKey[iLength] = '\0';
322 errorMessage = dasher_app_settings_cl_set(pPrivate->pAppSettings, szKey, szJoin + 1);
324 g_free(szKey);
327 if (errorMessage) {
328 // Note to translators: This string will be output when --options= specifies an unknown option.
329 g_critical("%s: '%s', %s", _("Invalid option string specified"), *pszCurrent, errorMessage);
330 return 0;
333 ++pszCurrent;
336 g_strfreev(pszOptionTerms);
338 /* --- */
342 dasher_editor_initialise(pPrivate->pEditor, pPrivate->pAppSettings, pDasherMain, pPrivate->pGladeXML, NULL);
345 dasher_main_setup_window(pDasherMain);
347 /* Create the editor */
348 gchar *szFullPath = NULL;
350 if(pCommandLine) {
351 if(pCommandLine->szFilename) {
352 if(!g_path_is_absolute(pCommandLine->szFilename)) {
353 char *cwd;
354 cwd = (char *)malloc(1024 * sizeof(char));
355 getcwd(cwd, 1024);
356 szFullPath = g_build_path("/", cwd, pCommandLine->szFilename, NULL);
358 else {
359 szFullPath = g_strdup(pCommandLine->szFilename);
364 // TODO: Fix this
365 // pPrivate->pEditor = GTK_EDITOR(
368 // dasher_editor_initialise(pPrivate->pAppSettings, pDasherMain, pPrivate->pGladeXML, szFullPath);
370 g_free(szFullPath);
372 // TODO: Were these really needed?
373 // g_signal_connect(pPrivate->pEditor, "filename_changed", G_CALLBACK(dasher_main_cb_filename_changed), pDasherMain);
374 // g_signal_connect(pPrivate->pEditor, "buffer_changed", G_CALLBACK(dasher_main_cb_buffer_changed), pDasherMain);
375 // g_signal_connect(pPrivate->pEditor, "context_changed", G_CALLBACK(dasher_main_cb_context_changed), pDasherMain);
377 /* Create the preferences window */
378 dasher_main_create_preferences(pDasherMain);
380 /* Create the lock dialogue (to be removed in future versions) */
381 #ifndef WITH_MAEMO
382 dasher_lock_dialogue_new(pPrivate->pGladeXML, GTK_WINDOW(pPrivate->pMainWindow));
383 #else
384 dasher_lock_dialogue_new(pPrivate->pGladeXML, 0);
385 #endif
387 g_object_unref(pPrivate->pGladeXML);
388 pPrivate->pGladeXML = 0;
390 g_object_unref(pPrivate->pPrefXML);
391 pPrivate->pPrefXML = 0;
393 /* Set up various bits and pieces */
394 dasher_main_set_window_title(pDasherMain);
395 dasher_main_populate_controls(pDasherMain);
396 dasher_main_connect_control(pDasherMain);
398 gtk_key_snooper_install(dasher_main_key_snooper, pDasherMain);
400 return pDasherMain;
404 static GladeXML *
405 dasher_main_open_glade_xml(const char *szGladeFilename) {
406 g_message("Opening Glade file: %s", szGladeFilename);
408 GladeXML *xml = glade_xml_new(szGladeFilename, NULL, NULL);
410 if (!xml) {
411 g_error("Can't find Glade file: %s. Dasher is unlikely to be correctly installed.", szGladeFilename);
414 glade_xml_signal_autoconnect(xml);
416 return xml;
419 /* Load the window interface from the glade file, and do various initialisation bits and pieces */
420 static void
421 dasher_main_load_interface(DasherMain *pSelf) {
422 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
424 const char *szGladeFilename = NULL;
425 const char *szPrefGladeFilename = NULL;
427 #ifdef WITH_GPE
428 szGladeFilename = PROGDATA "/dashergpe.glade";
429 #elif WITH_MAEMO
430 #ifdef WITH_MAEMOFULLSCREEN
431 // szGladeFilename = "/var/lib/install" PROGDATA "/dashermaemofullscreen.glade";
432 szGladeFilename = PROGDATA "/dashermaemofullscreen.glade";
433 #else
434 //szGladeFilename = "/var/lib/install" PROGDATA "/dashermaemo.glade";
435 szGladeFilename = PROGDATA "/dashermaemo.glade";
436 #endif
437 szPrefGladeFilename = PROGDATA "/dashermaemo.preferences.glade";
438 #else
439 switch(dasher_app_settings_get_long(pPrivate->pAppSettings, APP_LP_STYLE)) {
440 case APP_STYLE_TRAD:
441 szGladeFilename = PROGDATA "/dasher.traditional.glade";
442 break;
443 case APP_STYLE_COMPOSE:
444 szGladeFilename = PROGDATA "/dasher.compose.glade";
445 break;
446 case APP_STYLE_DIRECT:
447 szGladeFilename = PROGDATA "/dasher.direct.glade";
448 break;
449 case APP_STYLE_FULLSCREEN:
450 szGladeFilename = PROGDATA "/dasher.fullscreen.glade";
451 break;
452 default:
453 g_error("Inconsistent application style specified.");
455 szPrefGladeFilename = PROGDATA "/dasher.preferences.glade";
456 #endif
458 if(!szGladeFilename) {
459 g_error("Failure to determine glade filename");
462 pPrivate->pGladeXML = dasher_main_open_glade_xml(szGladeFilename);
464 if (szPrefGladeFilename) {
465 pPrivate->pPrefXML = dasher_main_open_glade_xml(szPrefGladeFilename);
467 else {
468 // If no separate preference file, preferences widget is in main glade xml
469 pPrivate->pPrefXML = (GladeXML *) g_object_ref(pPrivate->pGladeXML);
472 // XXX PRLW: Hide the Help Contents as there is no handler to display help.
473 // #575365
474 gtk_widget_hide(glade_xml_get_widget(pPrivate->pGladeXML, "menu_command_help"));
476 // Save the details of some of the widgets for later
477 // pPrivate->pActionPane = glade_xml_get_widget(pPrivate->pGladeXML, "vbox39");
478 pPrivate->pBufferView = glade_xml_get_widget(pPrivate->pGladeXML, "the_text_view");
479 pPrivate->pDivider = glade_xml_get_widget(pPrivate->pGladeXML, "main_divider");
480 // pPrivate->pEditPane = glade_xml_get_widget(pPrivate->pGladeXML, "vbox40");
481 pPrivate->pMainWindow = glade_xml_get_widget(pPrivate->pGladeXML, "window");
482 pPrivate->pToolbar = glade_xml_get_widget(pPrivate->pGladeXML, "toolbar");
483 // pPrivate->pMenuBar = glade_xml_get_widget(pPrivate->pGladeXML, "dasher_menu_bar");
484 pPrivate->pDasherWidget = glade_xml_get_widget(pPrivate->pGladeXML, "DasherControl");
486 #ifndef WITH_MAEMO
487 pPrivate->pSpeedBox = glade_xml_get_widget(pPrivate->pGladeXML, "spinbutton1");
488 pPrivate->pAlphabetCombo = glade_xml_get_widget(pPrivate->pGladeXML, "combobox1");
489 pPrivate->pStatusControl = glade_xml_get_widget(pPrivate->pGladeXML, "hbox8");
491 pPrivate->pAlphabetList = gtk_list_store_new(1, G_TYPE_STRING);
492 gtk_combo_box_set_model(GTK_COMBO_BOX(pPrivate->pAlphabetCombo),
493 GTK_TREE_MODEL(pPrivate->pAlphabetList));
495 GtkCellRenderer *pRenderer;
496 pRenderer = gtk_cell_renderer_text_new();
497 #if GTK_CHECK_VERSION(2,6,0)
498 g_object_set(G_OBJECT(pRenderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
499 #endif
500 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(pPrivate->pAlphabetCombo), pRenderer, true);
501 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(pPrivate->pAlphabetCombo), pRenderer, "text", 0, NULL);
504 // gtk_widget_add_events(pPrivate->pDragHandle, GDK_POINTER_MOTION_MASK);
505 #else
507 #ifdef WITH_MAEMOFULLSCREEN
508 // TODO: This is horrible - no need to get it from the glade file if we're not going to use it
510 pPrivate->pProgram = HILDON_PROGRAM(hildon_program_get_instance());
511 // hildon_app_set_title(pPrivate->pApp, "Dasher");
513 pPrivate->pHWindow = HILDON_WINDOW(hildon_window_new());
514 hildon_program_add_window(pPrivate->pProgram, pPrivate->pHWindow);
516 gtk_widget_reparent(pPrivate->pInnerFrame, GTK_WIDGET(pPrivate->pHWindow));
517 // gtk_paned_set_position(GTK_PANED(window), 100);
519 /* Do menu setup */
520 GtkMenu *main_menu;
521 GtkWidget *file_menu;
522 GtkWidget *file_menu_item;
523 GtkWidget *options_menu;
524 GtkWidget *options_menu_item;
525 GtkWidget *help_menu;
526 GtkWidget *help_menu_item;
529 // main_menu = hildon_appview_get_menu(appview);
531 main_menu = GTK_MENU(gtk_menu_new());
532 file_menu = glade_xml_get_widget(pPrivate->pGladeXML, "menuitem4_menu");
533 options_menu = glade_xml_get_widget(pPrivate->pGladeXML, "options1_menu");
534 help_menu = glade_xml_get_widget(pPrivate->pGladeXML, "menuitem7_menu");
535 file_menu_item = gtk_menu_item_new_with_label ("File");
536 options_menu_item = gtk_menu_item_new_with_label ("Options");
537 help_menu_item = gtk_menu_item_new_with_label ("Help");
539 g_object_ref(file_menu);
540 g_object_ref(options_menu);
541 g_object_ref(help_menu);
543 gtk_menu_item_set_submenu(GTK_MENU_ITEM(glade_xml_get_widget(pPrivate->pGladeXML, "menuitem4")), NULL);
544 gtk_menu_item_set_submenu(GTK_MENU_ITEM(glade_xml_get_widget(pPrivate->pGladeXML, "options1")), NULL);
545 gtk_menu_item_set_submenu(GTK_MENU_ITEM(glade_xml_get_widget(pPrivate->pGladeXML, "menuitem7")), NULL);
547 gtk_menu_item_set_submenu(GTK_MENU_ITEM(file_menu_item),file_menu);
548 gtk_menu_item_set_submenu(GTK_MENU_ITEM(options_menu_item),options_menu);
549 gtk_menu_item_set_submenu(GTK_MENU_ITEM(help_menu_item),help_menu);
550 gtk_menu_shell_append((GtkMenuShell *)main_menu, file_menu_item);
551 gtk_menu_shell_append((GtkMenuShell *)main_menu, options_menu_item);
552 gtk_menu_shell_append((GtkMenuShell *)main_menu, help_menu_item);
554 g_object_unref(file_menu);
555 g_object_unref(options_menu);
556 g_object_unref(help_menu);
558 hildon_program_set_common_menu(pPrivate->pProgram, main_menu);
560 gtk_widget_show_all( GTK_WIDGET( main_menu ) );
562 // /* And toolbar */
563 // GtkWidget *toolbar;
564 // toolbar = glade_xml_get_widget(pPrivate->pGladeXML, "toolbar");
565 // g_print("Got %p\n",toolbar);
566 // gtk_widget_reparent (toolbar, appview->vbox);
568 gtk_widget_show_all(GTK_WIDGET(pPrivate->pHWindow));
570 gtk_widget_destroy(pPrivate->pMainWindow);
571 pPrivate->pMainWindow = GTK_WIDGET(pPrivate->pHWindow);
573 g_signal_connect(G_OBJECT(pPrivate->pHWindow), "delete_event", G_CALLBACK(ask_save_before_exit), NULL);
575 #endif // Maemo fullscreen
576 #endif // Maemo
578 // pPrivate->bHidden = false;
579 // pPrivate->bGrabbed = false;
581 // pPrivate->iPosition = 100; // FIXME - make this persistant
583 // TODO: Specify callbacks in glade file
584 // TODO: Rationalise focus
585 // g_signal_connect(G_OBJECT(pPrivate->pBufferView), "button-release-event", G_CALLBACK(take_real_focus), NULL);
586 // g_signal_connect(G_OBJECT(pPrivate->pBufferView), "key-press-event", G_CALLBACK(edit_key_press), NULL);
587 //g_signal_connect(G_OBJECT(pPrivate->pBufferView), "key-release-event", G_CALLBACK(edit_key_release), NULL);
589 pPrivate->iAlphabetComboHandler = g_signal_connect(G_OBJECT(pPrivate->pAlphabetCombo), "changed", G_CALLBACK(alphabet_combo_changed), NULL);
591 // dasher_main_build_context_menu(pSelf);
593 // Create a Maemo helper if necessary
594 #if defined WITH_MAEMO && !defined WITH_MAEMOFULLSCREEN
595 pPrivate->pMaemoHelper = dasher_maemo_helper_new(GTK_WINDOW(pPrivate->pMainWindow));
596 #endif
598 // Set up any non-registry-dependent options
599 #ifdef WITH_GPE
600 gtk_window_set_decorated(GTK_WINDOW(pPrivate->pMainWindow), false);
601 #endif
603 // Hide any widgets which aren't appropriate for this mode
605 if(dasher_app_settings_get_long(pPrivate->pAppSettings, APP_LP_STYLE) == APP_STYLE_DIRECT) {
606 gtk_widget_hide(glade_xml_get_widget(pPrivate->pGladeXML, "dasher_menu_bar"));
608 gtk_widget_hide(glade_xml_get_widget(pPrivate->pGladeXML, "tb_command_new"));
609 gtk_widget_hide(glade_xml_get_widget(pPrivate->pGladeXML, "tb_command_open"));
610 gtk_widget_hide(glade_xml_get_widget(pPrivate->pGladeXML, "tb_command_save"));
611 gtk_widget_hide(glade_xml_get_widget(pPrivate->pGladeXML, "tb_command_saveas"));
612 gtk_widget_hide(glade_xml_get_widget(pPrivate->pGladeXML, "separatortoolitem1"));
613 gtk_widget_hide(glade_xml_get_widget(pPrivate->pGladeXML, "tb_command_cut"));
614 gtk_widget_hide(glade_xml_get_widget(pPrivate->pGladeXML, "tb_command_copy"));
615 gtk_widget_hide(glade_xml_get_widget(pPrivate->pGladeXML, "tb_command_paste"));
616 gtk_widget_hide(glade_xml_get_widget(pPrivate->pGladeXML, "separatortoolitem2"));
620 dasher_main_connect_menus(pSelf);
623 pPrivate->pEditor = DASHER_EDITOR(glade_xml_get_widget(pPrivate->pGladeXML, "DasherEditor"));
624 // TODO: szFullPath
625 pPrivate->bWidgetsInitialised = true;
628 static void
629 dasher_main_create_preferences(DasherMain *pSelf) {
630 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
631 pPrivate->pPreferencesDialogue = dasher_preferences_dialogue_new(pPrivate->pPrefXML, pPrivate->pEditor, pPrivate->pAppSettings, GTK_WINDOW(pPrivate->pMainWindow));
634 // DasherEditor *
635 // dasher_main_get_editor(DasherMain *pSelf) {
636 // DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
637 // return pPrivate->pEditor;
638 // }
640 static void
641 dasher_main_handle_parameter_change(DasherMain *pSelf, int iParameter) {
642 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
644 switch( iParameter ) {
645 case APP_BP_SHOW_TOOLBAR:
646 if( dasher_app_settings_get_bool(pPrivate->pAppSettings, APP_BP_SHOW_TOOLBAR))
647 gtk_widget_show(pPrivate->pToolbar);
648 else
649 gtk_widget_hide(pPrivate->pToolbar);
650 break;
651 case BP_SHOW_SLIDER: // TODO: Shouldn't be a core parmeter
652 if( dasher_app_settings_get_bool(pPrivate->pAppSettings, BP_SHOW_SLIDER))
653 gtk_widget_show(pPrivate->pStatusControl);
654 else
655 gtk_widget_hide(pPrivate->pStatusControl);
656 break;
657 // case APP_SP_EDIT_FONT:
658 // TODO: Editor should handle this directly
659 // dasher_main_refresh_font(pSelf);
660 // break;
661 #ifndef WITH_MAEMO
662 case LP_MAX_BITRATE:
663 gtk_spin_button_set_value(GTK_SPIN_BUTTON(pPrivate->pSpeedBox), dasher_app_settings_get_long(pPrivate->pAppSettings, LP_MAX_BITRATE) / 100.0);
664 break;
665 #endif
666 case SP_ALPHABET_ID:
667 dasher_main_populate_alphabet_combo(pSelf);
668 break;
669 case BP_GLOBAL_KEYBOARD:
670 dasher_main_setup_window(pSelf);
671 break;
672 #if defined WITH_MAEMO && !defined WITH_MAEMOFULLSCREEN
673 case APP_LP_MAEMO_SIZE: {
674 g_message("Maemo size");
676 bool bVisible = GTK_WIDGET_VISIBLE(pPrivate->pMainWindow);
677 gtk_widget_hide(pPrivate->pMainWindow);
678 if(dasher_app_settings_get_long(pPrivate->pAppSettings, APP_LP_MAEMO_SIZE) == 0) {
679 int iWidth;
680 gtk_window_get_size(GTK_WINDOW(pPrivate->pMainWindow), &iWidth, NULL);
681 gtk_widget_set_size_request(pPrivate->pMainWindow, -1, 150);
682 gtk_window_resize(GTK_WINDOW(pPrivate->pMainWindow), iWidth, 150);
683 gtk_widget_set_size_request(pPrivate->pDasherWidget, 175, -1);
685 else {
686 int iWidth;
687 gtk_window_get_size(GTK_WINDOW(pPrivate->pMainWindow), &iWidth, NULL);
688 gtk_widget_set_size_request(pPrivate->pMainWindow, -1, 250);
689 gtk_window_resize(GTK_WINDOW(pPrivate->pMainWindow), iWidth, 250);
690 gtk_widget_set_size_request(pPrivate->pDasherWidget, 280, -1);
692 if(bVisible)
693 gtk_widget_show(pPrivate->pMainWindow);
694 break;
696 #endif
699 if(pPrivate->pPreferencesDialogue)
700 dasher_preferences_dialogue_handle_parameter_change(pPrivate->pPreferencesDialogue, iParameter);
702 if(pPrivate->pEditor)
703 dasher_editor_handle_parameter_change(pPrivate->pEditor, iParameter);
706 static void
707 dasher_main_load_state(DasherMain *pSelf) {
708 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
710 int iWindowWidth;
711 int iWindowHeight;
712 int iEditHeight;
714 if(dasher_app_settings_get_long(pPrivate->pAppSettings, APP_LP_STYLE) != APP_STYLE_COMPOSE) {
715 iEditHeight = dasher_app_settings_get_long(pPrivate->pAppSettings, APP_LP_EDIT_HEIGHT);
716 iWindowWidth = dasher_app_settings_get_long(pPrivate->pAppSettings, APP_LP_SCREEN_WIDTH);
717 iWindowHeight = dasher_app_settings_get_long(pPrivate->pAppSettings, APP_LP_SCREEN_HEIGHT);
719 else {
720 iEditHeight = dasher_app_settings_get_long(pPrivate->pAppSettings, APP_LP_EDIT_WIDTH);
721 iWindowWidth = dasher_app_settings_get_long(pPrivate->pAppSettings, APP_LP_SCREEN_WIDTH_H);
722 iWindowHeight = dasher_app_settings_get_long(pPrivate->pAppSettings, APP_LP_SCREEN_HEIGHT_H);
725 #ifndef WITH_MAEMO
726 gtk_window_resize(GTK_WINDOW(pPrivate->pMainWindow), iWindowWidth, iWindowHeight);
727 #endif
729 gtk_paned_set_position(GTK_PANED(pPrivate->pDivider), iEditHeight);
731 pPrivate->iWidth = iWindowWidth;
732 pPrivate->iHeight = iWindowHeight;
735 int iWindowX;
736 int iWindowY;
738 iWindowX = dasher_app_settings_get_long(pPrivate->pAppSettings, APP_LP_X);
739 iWindowY = dasher_app_settings_get_long(pPrivate->pAppSettings, APP_LP_Y);
741 gtk_window_move(GTK_WINDOW(pPrivate->pMainWindow), iWindowX, iWindowY);
744 // pPrivate->iPosition = dasher_app_settings_get_long(pPrivate->pAppSettings, APP_LP_DOCK_POSITION);
747 static void
748 dasher_main_save_state(DasherMain *pSelf) {
749 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
751 if(!pPrivate->bWidgetsInitialised)
752 return;
754 int iWindowWidth;
755 int iWindowHeight;
756 int iEditHeight;
758 gtk_window_get_size(GTK_WINDOW(pPrivate->pMainWindow), &iWindowWidth, &iWindowHeight);
759 iEditHeight = gtk_paned_get_position(GTK_PANED(pPrivate->pDivider));
761 if(dasher_app_settings_get_long(pPrivate->pAppSettings, APP_LP_STYLE) != APP_STYLE_COMPOSE) {
762 // APP_STYLE_DIRECT doesn't have an edit window.
763 if (dasher_app_settings_get_long(pPrivate->pAppSettings, APP_LP_STYLE) != APP_STYLE_DIRECT)
764 dasher_app_settings_set_long(pPrivate->pAppSettings, APP_LP_EDIT_HEIGHT, iEditHeight);
765 dasher_app_settings_set_long(pPrivate->pAppSettings, APP_LP_SCREEN_WIDTH, iWindowWidth);
766 dasher_app_settings_set_long(pPrivate->pAppSettings, APP_LP_SCREEN_HEIGHT, iWindowHeight);
768 else {
769 dasher_app_settings_set_long(pPrivate->pAppSettings, APP_LP_EDIT_WIDTH, iEditHeight);
770 dasher_app_settings_set_long(pPrivate->pAppSettings, APP_LP_SCREEN_WIDTH_H, iWindowWidth);
771 dasher_app_settings_set_long(pPrivate->pAppSettings, APP_LP_SCREEN_HEIGHT_H, iWindowHeight);
774 int iWindowX;
775 int iWindowY;
776 gtk_window_get_position(GTK_WINDOW(pPrivate->pMainWindow), &iWindowX, &iWindowY);
778 dasher_app_settings_set_long(pPrivate->pAppSettings, APP_LP_X, iWindowX);
779 dasher_app_settings_set_long(pPrivate->pAppSettings, APP_LP_Y, iWindowY);
781 // dasher_app_settings_set_long(pPrivate->pAppSettings, APP_LP_DOCK_POSITION, pPrivate->iPosition);
784 void
785 dasher_main_show(DasherMain *pSelf) {
786 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
787 gtk_widget_show(pPrivate->pMainWindow);
790 static void
791 dasher_main_setup_window(DasherMain *pSelf) {
792 dasher_main_setup_window_style(pSelf);
793 dasher_main_setup_window_state(pSelf);
794 dasher_main_setup_internal_layout(pSelf);
796 // DasherMainPrivate *pPrivate = (DasherMainPrivate *)(pSelf->private_data);
798 // if(dasher_app_settings_get_bool(pPrivate->pAppSettings, BP_GLOBAL_KEYBOARD))
799 // gdk_window_add_filter(0, keyboard_filter_cb, 0);
800 // else
801 // gdk_window_remove_filter(0, keyboard_filter_cb, 0);
804 static void
805 dasher_main_populate_controls(DasherMain *pSelf) {
806 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
808 // Populate the alphabet chooser
809 dasher_main_populate_alphabet_combo(pSelf);
811 // Set the value of the speed spinner
812 gtk_spin_button_set_value(GTK_SPIN_BUTTON(pPrivate->pSpeedBox),
813 dasher_app_settings_get_long(pPrivate->pAppSettings, LP_MAX_BITRATE) / 100.0);
816 static void
817 dasher_main_connect_control(DasherMain *pSelf) {
818 /* TODO: This is very much temporary - we need to think of a better
819 way of presenting application commands in a unified way */
820 #ifdef GNOME_SPEECH
821 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
823 gtk_dasher_control_register_node( GTK_DASHER_CONTROL(pPrivate->pDasherWidget),
824 Dasher::CControlManager::CTL_USER,
825 "Speak", -1 );
827 gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pPrivate->pDasherWidget),
828 Dasher::CControlManager::CTL_USER,
829 Dasher::CControlManager::CTL_ROOT, -2);
832 gtk_dasher_control_register_node( GTK_DASHER_CONTROL(pPrivate->pDasherWidget),
833 Dasher::CControlManager::CTL_USER + 1,
834 "All", -1 );
836 gtk_dasher_control_register_node( GTK_DASHER_CONTROL(pPrivate->pDasherWidget),
837 Dasher::CControlManager::CTL_USER + 2,
838 "Last", -1 );
840 gtk_dasher_control_register_node( GTK_DASHER_CONTROL(pPrivate->pDasherWidget),
841 Dasher::CControlManager::CTL_USER + 3,
842 "Repeat", -1 );
844 gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pPrivate->pDasherWidget),
845 Dasher::CControlManager::CTL_USER + 1,
846 Dasher::CControlManager::CTL_USER, -2);
848 gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pPrivate->pDasherWidget),
849 -1,
850 Dasher::CControlManager::CTL_USER + 1, -2);
852 gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pPrivate->pDasherWidget),
853 Dasher::CControlManager::CTL_USER + 2,
854 Dasher::CControlManager::CTL_USER, -2);
856 gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pPrivate->pDasherWidget),
858 Dasher::CControlManager::CTL_USER + 2, -2);
860 gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pPrivate->pDasherWidget),
861 Dasher::CControlManager::CTL_USER + 3,
862 Dasher::CControlManager::CTL_USER, -2);
864 gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pPrivate->pDasherWidget),
866 Dasher::CControlManager::CTL_USER + 3, -2);
868 #endif
872 static gboolean
873 dasher_main_command(DasherMain *pSelf, const gchar *szCommand) {
874 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
876 if(!strcmp(szCommand, "import")) {
877 dasher_main_command_import(pSelf);
878 return TRUE;
881 if(!strcmp(szCommand, "quit")) {
882 dasher_main_command_quit(pSelf);
883 return TRUE;
886 if(!strcmp(szCommand, "preferences")) {
887 dasher_main_command_preferences(pSelf);
888 return TRUE;
891 if(!strcmp(szCommand, "preferences_alphabet")) {
892 dasher_main_command_preferences_alphabet(pSelf);
893 return TRUE;
896 if(!strcmp(szCommand, "tutorial")) {
897 dasher_main_command_tutorial(pSelf);
898 return TRUE;
901 if(!strcmp(szCommand, "help")) {
902 dasher_main_command_help(pSelf);
903 return TRUE;
906 if(!strcmp(szCommand, "about")) {
907 dasher_main_command_about(pSelf);
908 return TRUE;
911 if(pPrivate->pEditor)
912 return dasher_editor_command(pPrivate->pEditor, szCommand);
914 return FALSE;
917 /* Private methods */
919 /* Window state is basically size and position */
920 static void
921 dasher_main_setup_window_state(DasherMain *pSelf) {
922 dasher_main_load_state(pSelf);
924 // TODO: Setup positioning here - need to think up a policy on this
928 /* Setup the window style - this is defined to be window manager hints and the like */
929 static void
930 dasher_main_setup_window_style(DasherMain *pSelf) {
931 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
933 switch(dasher_app_settings_get_long(pPrivate->pAppSettings, APP_LP_STYLE)) {
934 case APP_STYLE_TRAD:
935 // Nothing to do
936 break;
937 case APP_STYLE_COMPOSE:
938 // Nothing to do
939 break;
940 case APP_STYLE_DIRECT:
941 // Direct mode - set always on top
942 gtk_window_set_keep_above(GTK_WINDOW(pPrivate->pMainWindow), true);
944 // Refuse focus
945 gtk_window_set_accept_focus(GTK_WINDOW(pPrivate->pMainWindow), false);
947 // Stick on all desktops
948 gtk_window_stick(GTK_WINDOW(pPrivate->pMainWindow));
949 break;
950 case APP_STYLE_FULLSCREEN:
951 // Fullscreen mode - set fullscreen
952 gtk_window_fullscreen(GTK_WINDOW(pPrivate->pMainWindow));
953 break;
954 default:
955 g_error("Inconsistent application style specified.");
959 /* Internal layout is the visibility of various widgets */
960 static void
961 dasher_main_setup_internal_layout(DasherMain *pSelf) {
962 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
964 if(pPrivate->pToolbar) {
965 if( dasher_app_settings_get_bool(pPrivate->pAppSettings, APP_BP_SHOW_TOOLBAR))
966 gtk_widget_show(pPrivate->pToolbar);
967 else
968 gtk_widget_hide(pPrivate->pToolbar);
971 if(pPrivate->pStatusControl) {
972 if( dasher_app_settings_get_bool(pPrivate->pAppSettings, BP_SHOW_SLIDER))
973 gtk_widget_show(pPrivate->pStatusControl);
974 else
975 gtk_widget_hide(pPrivate->pStatusControl);
978 // dasher_main_refresh_font(pSelf);
981 // static void
982 // dasher_main_refresh_font(DasherMain *pSelf) {
983 // DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
985 // dasher_editor_handle_font(pPrivate->pEditor,
986 // dasher_app_settings_get_string(pPrivate->pAppSettings, APP_SP_EDIT_FONT));
987 // }
989 // TODO: Fold into setup controls?
990 static void
991 dasher_main_set_window_title(DasherMain *pSelf) {
992 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
994 const gchar *szFilename = dasher_editor_get_filename(pPrivate->pEditor);
996 // Note to translators: This is the name of the dasher program as it appears
997 // in a window title.
998 gchar * dasher = _("Dasher");
999 if(szFilename == 0) {
1000 gtk_window_set_title(GTK_WINDOW(pPrivate->pMainWindow), dasher);
1002 else {
1003 gchar *title = g_strdup_printf("%s - %s", dasher, szFilename);
1004 gtk_window_set_title(GTK_WINDOW(pPrivate->pMainWindow), title);
1005 g_free (title);
1009 static void
1010 dasher_main_connect_menus(DasherMain *pSelf) {
1011 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
1013 int iNumItems = sizeof(MenuCommands) / sizeof(DasherMenuCommand);
1015 for(int i(0); i < iNumItems; ++i) {
1016 GtkWidget *pWidget;
1018 pWidget = glade_xml_get_widget(pPrivate->pGladeXML, MenuCommands[i].szWidgetName);
1020 MenuCommands[i].pWidget = pWidget;
1022 // TODO: Check that these are the right signals to connect to
1023 if(pWidget)
1024 if(GTK_IS_MENU_ITEM(pWidget))
1025 g_signal_connect(G_OBJECT(pWidget), "activate", G_CALLBACK(dasher_main_cb_menu_command), pSelf);
1026 else
1027 g_signal_connect(G_OBJECT(pWidget), "clicked", G_CALLBACK(dasher_main_cb_menu_command), pSelf);
1032 static void
1033 dasher_main_menu_command(DasherMain *pSelf, GtkWidget *pWidget) {
1034 int iNumItems = sizeof(MenuCommands) / sizeof(DasherMenuCommand);
1036 for(int i(0); i < iNumItems; ++i) {
1037 if(MenuCommands[i].pWidget == pWidget) {
1038 dasher_main_command(pSelf, MenuCommands[i].szCommand);
1039 return;
1044 static void
1045 dasher_main_command_import(DasherMain *pSelf) {
1046 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
1048 GtkWidget *pFileSel = gtk_file_chooser_dialog_new(_("Select File"),
1049 GTK_WINDOW(pPrivate->pMainWindow),
1050 GTK_FILE_CHOOSER_ACTION_OPEN,
1051 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
1052 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1053 NULL);
1055 #ifdef GNOME_LIBS
1056 gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(pFileSel), FALSE);
1057 #endif
1059 if(gtk_dialog_run(GTK_DIALOG(pFileSel)) == GTK_RESPONSE_ACCEPT) {
1061 #ifdef GNOME_LIBS
1062 gchar *szFilename = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(pFileSel));
1063 #else
1064 gchar *szFilename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(pFileSel));
1065 #endif
1067 gtk_dasher_control_train(GTK_DASHER_CONTROL(pPrivate->pDasherWidget), szFilename);
1069 g_free(szFilename);
1072 gtk_widget_destroy(pFileSel);
1075 static void dasher_main_command_quit(DasherMain *pSelf) {
1076 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
1078 GtkWidget *pDialogue = NULL;
1080 if(dasher_editor_file_changed(pPrivate->pEditor)) {
1081 // XXX PRLW: Just open the save dialogue box.
1082 #if 0
1083 const gchar *szFilename = dasher_editor_get_filename(pPrivate->pEditor);
1085 if(szFilename) {
1086 pDialogue = gtk_message_dialog_new(GTK_WINDOW(pPrivate->pMainWindow), GTK_DIALOG_MODAL,
1087 GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
1088 _("Do you want to save your changes to %s?\n\nYour changes will be lost if you don't save them."),
1089 szFilename);
1091 else {
1092 #endif
1093 pDialogue = gtk_message_dialog_new(GTK_WINDOW(pPrivate->pMainWindow), GTK_DIALOG_MODAL,
1094 GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
1095 _("Do you want to save your changes?\n\nYour changes will be lost if you don't save them."));
1096 #if 0
1098 #endif
1100 gtk_dialog_add_buttons(GTK_DIALOG(pDialogue),
1101 _("Don't save"), GTK_RESPONSE_REJECT,
1102 _("Don't quit"), GTK_RESPONSE_CANCEL,
1103 _("Save and quit"), GTK_RESPONSE_ACCEPT,
1104 NULL);
1106 switch (gtk_dialog_run(GTK_DIALOG(pDialogue))) {
1107 case GTK_RESPONSE_REJECT:
1108 gtk_main_quit();
1109 break;
1110 case GTK_RESPONSE_CANCEL:
1111 gtk_widget_destroy(GTK_WIDGET(pDialogue));
1112 break;
1113 case GTK_RESPONSE_ACCEPT:
1114 dasher_editor_command(pPrivate->pEditor, "save");
1115 gtk_main_quit();
1116 break;
1119 else {
1120 pDialogue = gtk_message_dialog_new(GTK_WINDOW(pPrivate->pMainWindow), GTK_DIALOG_MODAL,
1121 GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
1122 _("Are you sure you wish to quit?"));
1124 gtk_dialog_add_buttons(GTK_DIALOG(pDialogue),
1125 _("Don't quit"), GTK_RESPONSE_REJECT,
1126 _("Quit"), GTK_RESPONSE_ACCEPT,
1127 NULL);
1129 switch (gtk_dialog_run(GTK_DIALOG(pDialogue))) {
1130 case GTK_RESPONSE_REJECT:
1131 gtk_widget_destroy(GTK_WIDGET(pDialogue));
1132 break;
1133 case GTK_RESPONSE_ACCEPT:
1134 gtk_main_quit();
1139 static void
1140 dasher_main_command_preferences(DasherMain *pSelf) {
1141 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
1142 dasher_preferences_dialogue_show(pPrivate->pPreferencesDialogue, 0);
1145 static void
1146 dasher_main_command_preferences_alphabet(DasherMain *pSelf) {
1147 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
1148 dasher_preferences_dialogue_show(pPrivate->pPreferencesDialogue, 1);
1151 static void
1152 dasher_main_command_tutorial(DasherMain *pSelf) {
1153 // TODO: Implement this
1156 static void
1157 dasher_main_command_help(DasherMain *pSelf) {
1158 // TODO: Need to disable the menu if gnome libs aren't present (or get rid of without gnome option)
1159 #ifdef GNOME_LIBS
1160 gnome_help_display_desktop(NULL, "dasher", "dasher", NULL, NULL);
1161 #endif
1164 static void
1165 dasher_main_command_about(DasherMain *pSelf) {
1166 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
1168 #if (defined GNOME_LIBS) || (GTK_CHECK_VERSION(2,6,0))
1170 // In alphabetical order - please keep this in sync with the AUTHORS
1171 // file at root of the package tree
1172 const gchar *authors[] = {
1173 "Chris Ball",
1174 "Ignas Budvytis",
1175 "Phil Cowans",
1176 "Frederik Eaton",
1177 "Behdad Esfahbod",
1178 "Matthew Garrett",
1179 "Chris Hack",
1180 "David MacKay",
1181 "Iain Murray",
1182 "Sega Kazue",
1183 "Takashi Kaburagi",
1184 "Martijn van Veen",
1185 "Keith Vertanen",
1186 "Hanna Wallach",
1187 "David Ward",
1188 "Brian Williams",
1189 "Seb Wills",
1190 "Will Zou",
1191 NULL
1194 // Yeah, should really do some Gnome documentation for it...
1195 const gchar *documenters[] = {
1196 "Chris Ball",
1197 "Matthew Garrett",
1198 "David MacKay",
1199 NULL
1202 #if GTK_CHECK_VERSION(2,6,0)
1203 gtk_show_about_dialog(GTK_WINDOW(pPrivate->pMainWindow),
1204 "authors", authors,
1205 "comments", _("Dasher is a predictive text entry application"),
1206 "copyright", "Copyright \xC2\xA9 1998-2007 The Dasher Project",
1207 "documenters", documenters,
1208 "license", "GPL 2+",
1209 "logo-icon-name", "dasher",
1210 "translator-credits", _("translator-credits"),
1211 "version", VERSION,
1212 "website", "http://www.dasher.org.uk/",
1213 "wrap-license", true,
1214 NULL);
1215 #else
1216 gchar *translator_credits = _("translator-credits");
1218 GtkWidget *about = gnome_about_new (_("Dasher"),
1219 PACKAGE_VERSION,
1220 "Copyright The Dasher Project\n",
1221 _("Dasher is a predictive text entry application"),
1222 (const char **)authors,
1223 (const char **)documenters,
1224 strcmp (translator_credits, "translator-credits") != 0 ? (const char *)translator_credits : NULL,
1225 NULL);
1227 gtk_window_set_transient_for (GTK_WINDOW(about), GTK_WINDOW(pPrivate->pMainWindow));
1228 // g_signal_connect (G_OBJECT (about), "destory", G_CALLBACK (gtk_widget_destroyed), &about);
1229 gtk_widget_show(about);
1231 #endif
1233 #else
1234 // EAT UGLY ABOUT BOX, PHILISTINE
1235 GtkWidget *label, *button;
1236 char *tmp;
1238 GtkWidget *about = gtk_dialog_new();
1240 gtk_dialog_set_has_separator(GTK_DIALOG(about), FALSE);
1241 gtk_window_set_title(GTK_WINDOW(about), "About Dasher");
1243 tmp = g_strdup_printf("Dasher Version %s ", VERSION);
1244 label = gtk_label_new(tmp);
1245 gtk_widget_show(label);
1246 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(about)->vbox), label, FALSE, FALSE, 0);
1248 label = gtk_label_new("http://www.dasher.org.uk/");
1249 gtk_widget_show(label);
1250 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(about)->vbox), label, FALSE, FALSE, 0);
1252 label = gtk_label_new("Copyright The Dasher Project");
1253 gtk_widget_show(label);
1254 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(about)->vbox), label, TRUE, TRUE, 0);
1256 button = gtk_button_new_from_stock(GTK_STOCK_OK);
1257 gtk_widget_show(button);
1258 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(about)->vbox), button, FALSE, FALSE, 0);
1259 g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(gtk_widget_destroy), G_OBJECT(about));
1261 gtk_widget_show(about);
1262 #endif
1265 static gboolean
1266 dasher_main_speed_changed(DasherMain *pSelf) {
1267 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
1269 int iNewValue( static_cast<int>(round(gtk_spin_button_get_value(GTK_SPIN_BUTTON(pPrivate->pSpeedBox)) * 100)));
1271 if(dasher_app_settings_get_long(pPrivate->pAppSettings, LP_MAX_BITRATE) != iNewValue)
1272 dasher_app_settings_set_long(pPrivate->pAppSettings, LP_MAX_BITRATE, iNewValue);
1274 return true;
1277 static void
1278 dasher_main_alphabet_combo_changed(DasherMain *pSelf) {
1279 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
1281 GtkTreeIter sIter;
1283 if(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(pPrivate->pAlphabetCombo), &sIter)) {
1284 char *szSelected;
1285 gtk_tree_model_get(GTK_TREE_MODEL(pPrivate->pAlphabetList), &sIter, 0, &szSelected, -1);
1287 if(!strcmp("More Alphabets...", szSelected)) {
1288 gtk_combo_box_set_active(GTK_COMBO_BOX(pPrivate->pAlphabetCombo), 0);
1289 // dasher_preferences_dialogue_show(pPrivate->pPreferencesDialogue);
1290 dasher_main_command(pSelf, "preferences_alphabet");
1292 else
1293 dasher_app_settings_set_string(pPrivate->pAppSettings, SP_ALPHABET_ID, szSelected);
1295 g_free(szSelected);
1299 static void
1300 dasher_main_populate_alphabet_combo(DasherMain *pSelf) {
1301 #ifndef WITH_MAEMO
1302 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
1304 // Disconnect the event handler temporarily, otherwise this will
1305 // trigger alphabet changes
1307 g_signal_handler_block(pPrivate->pAlphabetCombo, pPrivate->iAlphabetComboHandler);
1309 gtk_list_store_clear(pPrivate->pAlphabetList);
1312 GtkTreeIter sIter;
1313 const char *szValue;
1315 szValue = dasher_app_settings_get_string(pPrivate->pAppSettings, SP_ALPHABET_ID);
1317 if(strlen(szValue) > 0) {
1318 gtk_list_store_append(pPrivate->pAlphabetList, &sIter);
1319 gtk_list_store_set(pPrivate->pAlphabetList, &sIter, 0, szValue, -1);
1320 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(pPrivate->pAlphabetCombo), &sIter);
1323 szValue = dasher_app_settings_get_string(pPrivate->pAppSettings, SP_ALPHABET_1);
1324 if(strlen(szValue) > 0) {
1325 gtk_list_store_append(pPrivate->pAlphabetList, &sIter);
1326 gtk_list_store_set(pPrivate->pAlphabetList, &sIter, 0, szValue, -1);
1329 szValue = dasher_app_settings_get_string(pPrivate->pAppSettings, SP_ALPHABET_2);
1330 if(strlen(szValue) > 0) {
1331 gtk_list_store_append(pPrivate->pAlphabetList, &sIter);
1332 gtk_list_store_set(pPrivate->pAlphabetList, &sIter, 0, szValue, -1);
1335 szValue = dasher_app_settings_get_string(pPrivate->pAppSettings, SP_ALPHABET_3);
1336 if(strlen(szValue) > 0) {
1337 gtk_list_store_append(pPrivate->pAlphabetList, &sIter);
1338 gtk_list_store_set(pPrivate->pAlphabetList, &sIter, 0, szValue, -1);
1341 szValue = dasher_app_settings_get_string(pPrivate->pAppSettings, SP_ALPHABET_4);
1342 if(strlen(szValue) > 0) {
1343 gtk_list_store_append(pPrivate->pAlphabetList, &sIter);
1344 gtk_list_store_set(pPrivate->pAlphabetList, &sIter, 0, szValue, -1);
1347 gtk_list_store_append(pPrivate->pAlphabetList, &sIter);
1348 gtk_list_store_set(pPrivate->pAlphabetList, &sIter, 0, "More Alphabets...", -1);
1350 g_signal_handler_unblock(pPrivate->pAlphabetCombo, pPrivate->iAlphabetComboHandler);
1352 #endif
1355 static gint
1356 dasher_main_lookup_key(DasherMain *pSelf, guint iKeyVal) {
1357 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
1359 if(pPrivate->pKeyboardHelper)
1360 return pPrivate->pKeyboardHelper->ConvertKeycode(iKeyVal);
1361 else
1362 return -1;
1366 gboolean
1367 grab_focus() {
1369 // TODO: reimplement (text view member of class)
1370 // gtk_widget_grab_focus(the_text_view);
1371 // g_bForwardKeyboard = true;
1372 return true;
1375 /* Callbacks */
1377 extern "C" GtkWidget *
1378 create_dasher_control(gchar *szName, gchar *szString1, gchar *szString2, gint iInt1, gint iInt2) {
1379 GtkWidget *pDasherControl = gtk_dasher_control_new();
1381 #ifdef WITH_MAEMO
1382 // TODO: Do this in glade file?
1383 gtk_widget_set_size_request(pDasherControl, 175, -1);
1384 #endif
1386 return pDasherControl;
1389 extern "C" GtkWidget *
1390 create_dasher_editor(gchar *szName, gchar *szString1, gchar *szString2, gint iInt1, gint iInt2) {
1391 g_return_val_if_fail(g_pDasherMain != NULL, NULL);
1393 DasherMain *pDasherMain = DASHER_MAIN(g_pDasherMain);
1394 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pDasherMain);
1396 if(dasher_app_settings_get_long(pPrivate->pAppSettings, APP_LP_STYLE) == APP_STYLE_DIRECT)
1397 return GTK_WIDGET(dasher_editor_external_new());
1398 else
1399 return GTK_WIDGET(dasher_editor_internal_new());
1402 extern "C" gboolean
1403 dasher_main_cb_menu_command(GtkWidget *pWidget, gpointer pUserData) {
1404 dasher_main_menu_command((DasherMain *)pUserData, pWidget);
1406 return FALSE; // TODO: Scheck semantics of return value
1409 extern "C" gboolean
1410 speed_changed(GtkWidget *pWidget, gpointer user_data) {
1411 if(g_pDasherMain)
1412 return dasher_main_speed_changed(g_pDasherMain);
1414 // TODO: Check callback return functions
1415 return false;
1418 extern "C" void
1419 alphabet_combo_changed(GtkWidget *pWidget, gpointer pUserData) {
1420 if(g_pDasherMain)
1421 dasher_main_alphabet_combo_changed(g_pDasherMain);
1424 extern "C" void
1425 dasher_main_cb_filename_changed(DasherEditor *pEditor, gpointer pUserData) {
1426 if(g_pDasherMain)
1427 dasher_main_set_window_title(g_pDasherMain);
1430 extern "C" void
1431 dasher_main_cb_buffer_changed(DasherEditor *pEditor, gpointer pUserData) {
1432 if(!g_pDasherMain)
1433 return;
1435 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(g_pDasherMain);
1437 gtk_dasher_control_set_buffer(GTK_DASHER_CONTROL(pPrivate->pDasherWidget), dasher_editor_get_offset(pPrivate->pEditor));
1440 extern "C" void
1441 dasher_main_cb_context_changed(DasherEditor *pEditor, gpointer pUserData) {
1442 if(!g_pDasherMain)
1443 return;
1445 if(!g_bSend)
1446 return;
1448 DasherMain *pDasherMain = DASHER_MAIN(g_pDasherMain);
1449 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pDasherMain);
1451 gtk_dasher_control_set_offset(GTK_DASHER_CONTROL(pPrivate->pDasherWidget), dasher_editor_get_offset(pPrivate->pEditor));
1454 extern "C" gboolean
1455 dasher_main_cb_window_close(GtkWidget *pWidget, gpointer pUserData) {
1456 dasher_main_command(g_pDasherMain, "quit");
1458 /* Returning true stops further propagation */
1459 return TRUE;
1462 extern "C" void
1463 parameter_notification(GtkDasherControl *pDasherControl, gint iParameter, gpointer data) {
1464 if(g_pDasherMain)
1465 dasher_main_handle_parameter_change(g_pDasherMain, iParameter);
1468 // TODO: Not really sure what happens here - need to sort out focus behaviour in general
1469 extern "C" bool
1470 focus_in_event(GtkWidget *widget, GdkEventFocus *event, gpointer data) {
1471 return grab_focus();
1474 extern "C" bool
1475 edit_focus_in_event(GtkWidget *widget, GdkEventFocus *event, gpointer data) {
1476 return true;
1479 extern "C" gboolean
1480 take_real_focus(GtkWidget *widget, GdkEventFocus *event, gpointer user_data) {
1481 // g_bForwardKeyboard = false;
1482 return false;
1485 extern "C" gboolean
1486 edit_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data) {
1487 // TODO: Reimplement
1489 // if(g_bForwardKeyboard) {
1490 // gboolean *returnType;
1491 // g_signal_emit_by_name(GTK_OBJECT(pPrivate->pDasherWidget), "key_press_event", event, &returnType);
1492 // return true;
1493 // }
1494 // else {
1495 // return false;
1496 // }
1498 // TODO: Check callback return functions
1499 return false;
1502 extern "C" gboolean
1503 edit_key_release(GtkWidget *widget, GdkEventKey *event, gpointer user_data) {
1504 // TODO: reimplement
1506 // if(g_bForwardKeyboard) {
1507 // gboolean *returnType;
1508 // g_signal_emit_by_name(GTK_OBJECT(pPrivate->pDasherWidget), "key_release_event", event, &returnType);
1509 // return true;
1510 // }
1511 // else {
1512 // return false;
1513 // }
1515 // TODO: Check callback return functions
1516 return false;
1519 extern "C" gboolean
1520 test_focus_handler(GtkWidget *pWidget, GtkDirectionType iDirection, gpointer *pUserData) {
1521 return FALSE;
1524 extern "C" void
1525 handle_context_request(GtkDasherControl * pDasherControl, gint iOffset, gint iLength, gpointer data) {
1526 if(!g_pDasherMain)
1527 return;
1529 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(g_pDasherMain);
1531 if(!pPrivate->pEditor || !pPrivate->pDasherWidget)
1532 return;
1534 gtk_dasher_control_set_context(GTK_DASHER_CONTROL(pPrivate->pDasherWidget), dasher_editor_get_context(pPrivate->pEditor, iOffset, iLength));
1537 extern "C" void
1538 handle_control_event(GtkDasherControl *pDasherControl, gint iEvent, gpointer data) {
1539 if(!g_pDasherMain)
1540 return;
1542 /* TODO: replace this with something a little more sensible */
1544 switch(iEvent) {
1545 case Dasher::CControlManager::CTL_USER + 1:
1546 dasher_main_command(g_pDasherMain, "speakall");
1547 return;
1548 case Dasher::CControlManager::CTL_USER + 2:
1549 dasher_main_command(g_pDasherMain, "speaklast");
1550 return;
1551 case Dasher::CControlManager::CTL_USER + 3:
1552 dasher_main_command(g_pDasherMain, "speakrepeat");
1553 return;
1554 default:
1555 break;
1559 // TODO: This is a horrible hack here to make the release work!
1561 g_bSend = false;
1563 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(g_pDasherMain);
1564 dasher_editor_handle_control(pPrivate->pEditor, iEvent);
1566 gtk_dasher_control_set_control_offset(GTK_DASHER_CONTROL(pPrivate->pDasherWidget),
1567 dasher_editor_get_offset(pPrivate->pEditor));
1569 g_bSend = true;
1570 // ---
1574 extern "C" void
1575 handle_start_event(GtkDasherControl *pDasherControl, gpointer data) {
1576 if(!g_pDasherMain)
1577 return;
1579 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(g_pDasherMain);
1581 dasher_editor_grab_focus(pPrivate->pEditor);
1585 // TODO: Make this only work for children of the main window
1586 extern "C" gint
1587 dasher_main_key_snooper(GtkWidget *pWidget, GdkEventKey *pEvent, gpointer pUserData) {
1588 DasherMain *pSelf = DASHER_MAIN(pUserData);
1590 gint iButton = dasher_main_lookup_key(pSelf, pEvent->keyval);
1592 if(iButton != -1) {
1593 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
1595 if(gdk_window_get_toplevel(pEvent->window) == pPrivate->pMainWindow->window) {
1596 if(pPrivate->pDasherWidget) {
1597 if(pEvent->type == GDK_KEY_PRESS)
1598 gtk_dasher_control_external_key_down(GTK_DASHER_CONTROL(pPrivate->pDasherWidget), iButton);
1599 else
1600 gtk_dasher_control_external_key_up(GTK_DASHER_CONTROL(pPrivate->pDasherWidget), iButton);
1603 return TRUE;
1605 else {
1606 return FALSE;
1609 else {
1610 return FALSE;
1614 // Callbacks from the Dasher widget
1616 extern "C" void
1617 handle_stop_event(GtkDasherControl *pDasherControl, gpointer data) {
1618 if(g_pDasherMain) {
1619 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(g_pDasherMain);
1621 if(pPrivate->pEditor)
1622 dasher_editor_handle_stop(pPrivate->pEditor);
1626 extern "C" void
1627 on_message(GtkDasherControl *pDasherControl, gpointer pMessageInfo, gpointer pUserData) {
1628 // TODO: I don't believe that this is widely used, but possibly need to reimplement
1630 // if(g_pDasherMain) {
1631 // DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(g_pDasherMain);
1633 // if(pPrivate->pEditor)
1634 // dasher_editor_display_message(pPrivate->pEditor, (DasherMessageInfo *)pMessageInfo);
1635 // }
1638 extern "C" void
1639 on_command(GtkDasherControl *pDasherControl, gchar *szCommand, gpointer pUserData) {
1640 if(g_pDasherMain) {
1641 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(g_pDasherMain);
1643 if(pPrivate->pEditor)
1644 dasher_editor_command(pPrivate->pEditor, szCommand);
1648 // TODO: The following two should probably be made the same
1649 extern "C" void
1650 handle_request_settings(GtkDasherControl * pDasherControl, gpointer data) {
1651 // TODO: reimplement
1652 // dasher_preferences_dialogue_show(g_pPreferencesDialogue);
1655 extern "C" void
1656 gtk2_edit_delete_callback(GtkDasherControl *pDasherControl, const gchar *szText, int iOffset, gpointer user_data) {
1657 if(g_pDasherMain) {
1658 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(g_pDasherMain);
1660 if(pPrivate->pEditor) {
1661 gint displaylength = g_utf8_strlen(szText, -1);
1662 dasher_editor_delete(pPrivate->pEditor, displaylength, iOffset);
1667 extern "C" void
1668 gtk2_edit_output_callback(GtkDasherControl *pDasherControl, const gchar *szText, int iOffset, gpointer user_data) {
1669 if(g_pDasherMain) {
1670 DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(g_pDasherMain);
1672 if(pPrivate->pEditor) {
1673 dasher_editor_output(pPrivate->pEditor, szText, iOffset);
1678 // TODO: The following aren't exported from the editor - need to fix this
1680 extern "C" void
1681 convert_cb(GtkDasherControl *pDasherControl, gpointer pUserData) {
1682 // if(g_pDasherMain) {
1683 // DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(g_pDasherMain);
1685 // if(pPrivate->pEditor) {
1686 // dasher_editor_convert(pPrivate->pEditor);
1687 // }
1688 // }
1691 extern "C" void
1692 protect_cb(GtkDasherControl *pDasherControl, gpointer pUserData) {
1693 // if(g_pDasherMain) {
1694 // DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(g_pDasherMain);
1696 // if(pPrivate->pEditor) {
1697 // dasher_editor_protect(pPrivate->pEditor);
1698 // }
1699 // }