diff --git a/moo.kdevelop b/moo.kdevelop index 51184224..3054b47b 100644 --- a/moo.kdevelop +++ b/moo.kdevelop @@ -24,7 +24,7 @@ . false - + C @@ -46,7 +46,7 @@ - --enable-debug=full --enable-all-gcc-warnings=fatal --disable-moo-module + --enable-debug=full --enable-all-gcc-warnings=fatal --disable-moo-module --without-python --without-mooterm build/debug kdevgccoptions kdevgppoptions @@ -54,13 +54,13 @@ -O0 -g3 -pg -O0 -g3 -pg - - - - - - - + + + + + + + --enable-debug=full --enable-all-gcc-warnings=fatal --enable-developer-mode --disable-moo-module --without-python --without-mooterm --without-mooapp @@ -200,10 +200,10 @@ libtool --g-fatal-warnings - - - - + + + + true false true @@ -268,16 +268,16 @@ - + A new empty GAP source file - + A new empty C++ file. - + A new empty header file for C/C++. - + A new empty C file. @@ -304,7 +304,7 @@ - + set m_,_ theValue diff --git a/moo/mooapp/mooapp.c b/moo/mooapp/mooapp.c index 635ea6ef..8ba17807 100644 --- a/moo/mooapp/mooapp.c +++ b/moo/mooapp/mooapp.c @@ -766,7 +766,7 @@ static gboolean moo_app_init_real (MooApp *app) { G_GNUC_UNUSED const char *app_dir; const char *rc_file; - MooLangTable *lang_table; + MooLangMgr *lang_mgr; MooUIXML *ui_xml; GError *error = NULL; @@ -831,13 +831,13 @@ static gboolean moo_app_init_real (MooApp *app) moo_editor_set_app_name (app->priv->editor, app->priv->info->short_name); - lang_table = moo_editor_get_lang_table (app->priv->editor); - moo_lang_table_add_dir (lang_table, lang_dir); + lang_mgr = moo_editor_get_lang_mgr (app->priv->editor); + moo_lang_mgr_add_dir (lang_mgr, lang_dir); if (user_lang_dir) - moo_lang_table_add_dir (lang_table, user_lang_dir); + moo_lang_mgr_add_dir (lang_mgr, user_lang_dir); - moo_lang_table_read_dirs (lang_table); + moo_lang_mgr_read_dirs (lang_mgr); g_signal_connect_swapped (app->priv->editor, "all-windows-closed", diff --git a/moo/mooapp/mooappdialogs.c b/moo/mooapp/mooappdialogs.c index 6e68b869..568f6fa1 100644 --- a/moo/mooapp/mooappdialogs.c +++ b/moo/mooapp/mooappdialogs.c @@ -54,8 +54,8 @@ GtkWidget *_moo_app_create_prefs_dialog (MooApp *app) #endif #ifdef MOO_BUILD_EDIT - moo_prefs_dialog_append_page (dialog, moo_edit_prefs_page_new (moo_app_get_editor (app))); -// moo_prefs_dialog_append_page (dialog, moo_edit_colors_prefs_page_new (moo_app_get_editor (app))); +// moo_prefs_dialog_append_page (dialog, moo_edit_prefs_page_new (moo_app_get_editor (app))); + moo_prefs_dialog_append_page (dialog, moo_edit_colors_prefs_page_new (moo_app_get_editor (app))); _moo_plugin_attach_prefs (GTK_WIDGET (dialog)); #endif diff --git a/moo/mooedit/Makefile.am b/moo/mooedit/Makefile.am index 8bf933b1..071fdaef 100644 --- a/moo/mooedit/Makefile.am +++ b/moo/mooedit/Makefile.am @@ -24,77 +24,70 @@ mooeditinclude_HEADERS = \ mooeditwindow.h \ mooindenter.h \ moolang.h \ + moolangmgr.h \ moolineview.h \ - mooplugin.h \ mooplugin-macro.h \ + mooplugin.h \ mootextbuffer.h \ mootextiter.h \ mootextstyle.h \ + mootextstylescheme.h \ mootextview.h +noinst_HEADERS = \ + gtksourceiter.h \ + mooedit-private.h \ + mooeditcolorsprefs-glade.h \ + mooeditdialogs.h \ + mooeditfileops.h \ + mooeditfind-glade.h \ + mooeditgotoline-glade.h \ + mooeditprefs-glade.h \ + moohighlighter.h \ + moolang-aux.h \ + moolang-parser.h \ + moolang-rules.h \ + moolang-strings.h \ + moolinebuffer.h \ + moopluginprefs-glade.h \ + mootextbtree.h \ + mootextview-private.h + if !MOO_OS_MINGW -unix_sources = \ - moocmdview.c \ - moocmdview.h +unix_sources = moocmdview.c mooeditinclude_HEADERS += moocmdview.h endif libmooedit_la_SOURCES = \ $(unix_sources) \ $(mooeditinclude_HEADERS) \ + $(noinst_HEADERS) \ gtksourceiter.c \ - gtksourceiter.h \ mooedit.c \ - mooedit-private.h \ mooeditdialogs.c \ - mooeditdialogs.h \ mooeditfileops.c \ - mooeditfileops.h \ mooeditfind.c \ mooeditinput.c \ mooeditor.c \ mooeditprefs.c \ - mooeditprefs.h \ mooeditprefspage.c \ mooeditsearch.c \ - mooeditsearch.h \ mooeditwindow.c \ - mooeditwindow.h \ moohighlighter.c \ - moohighlighter.h \ mooindenter.c \ - mooindenter.h \ moolang.c \ - moolang.h \ + moolangmgr.c \ moolang-parser.c \ - moolang-parser.h \ moolang-rules.c \ - moolang-rules.h \ - moolang-aux.h \ - moolang-strings.h \ moolinebuffer.c \ - moolinebuffer.h \ moolineview.c \ - moolineview.h \ mooplugin.c \ - mooplugin.h \ - mooplugin-macro.h \ mootextbtree.c \ - mootextbtree.h \ mootextbuffer.c \ - mootextbuffer.h \ - mootextiter.h \ mootextstyle.c \ - mootextstyle.h \ - mootextview.c \ - mootextview.h \ - mootextview-private.h \ - mooeditgotoline-glade.h \ - mooeditfind-glade.h \ - moopluginprefs-glade.h \ - mooeditprefs-glade.h \ - mooeditcolorsprefs-glade.h + mootextstylescheme.c \ + mootextview.c libmooedit_la_LIBADD = \ plugins/libplugins.la diff --git a/moo/mooedit/glade/mooeditcolorsprefs.glade b/moo/mooedit/glade/mooeditcolorsprefs.glade index 9eebd9cc..cc1451a3 100644 --- a/moo/mooedit/glade/mooeditcolorsprefs.glade +++ b/moo/mooedit/glade/mooeditcolorsprefs.glade @@ -24,92 +24,136 @@ 0 - + True - True - True - True - GTK_POS_TOP - False - False + False + 0 - + True - False - 0 + True + True + True + GTK_POS_TOP + False + False - - - - - - - - - - - - - False - True - - - - - - True - Colors - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - - - tab - - - - - - True - 0 - 0.5 - GTK_SHADOW_NONE - - - + True 0.5 0.5 1 1 - 0 - 0 + 6 + 6 12 - 0 + 12 - + True - abcdefghijk ABCDEFGHIJK + 3 + 2 + False + 0 + 0 + + + + True + Font: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Color scheme: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + + + 1 + 2 + 1 + 2 + fill + + + + + + True + True + True + True + False + False + True + + + 1 + 2 + 0 + 1 + + + + + False + True + - + True - <b>frame1</b> + Font and Scheme False - True + False GTK_JUSTIFY_LEFT False False @@ -119,133 +163,476 @@ 0 - label_item + tab - - - False - True - - - - - - True - Font - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - - - tab - - - - - - True - False - 0 - + True - True - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - GTK_SHADOW_IN - GTK_CORNER_TOP_LEFT + False + 0 - + True - True - True - False - False - False + 6 + 2 + False + 0 + 0 + + + + True + Text color: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + True + False + True + + + 1 + 2 + 0 + 1 + + + + + + + True + Text background: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + True + False + True + + + 1 + 2 + 1 + 2 + fill + + + + + + + True + Selected text: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 0 + 1 + 2 + 3 + fill + + + + + + + True + True + False + True + + + 1 + 2 + 2 + 3 + fill + + + + + + + True + Selection: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 0 + 1 + 3 + 4 + fill + + + + + + + True + True + False + True + + + 1 + 2 + 3 + 4 + fill + + + + + + + True + Current line: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 0 + 1 + 4 + 5 + fill + + + + + + + True + True + False + True + + + 1 + 2 + 4 + 5 + fill + + + + + 0 + True + True + - 0 - True - True + False + True + + + + + + True + Colors + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + tab + + + + + + True + False + 0 + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + False + + + + + 0 + True + True + + + + + + + + + False + True + + + + + + True + Default styles + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + tab + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + + + + + 0 + True + True + + + + + + + + + 0 + True + True + + + + + False + True + + + + + + True + Highlighting styles + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + tab - False - True + 0 + True + True + + + 0 + True + True + + + + + + True + False + 0 - + True - Default text styles - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 + 0 0.5 - 0 - 0 + 0.15000000596 + 1 + 0 + 0 + 0 + 0 + + + + True + + - tab + 0 + False + False - + True - False - 0 + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_ETCHED_IN + GTK_CORNER_TOP_LEFT - - - - - - - - - + + True + True + True + False + True + GTK_JUSTIFY_LEFT + GTK_WRAP_WORD + True + 0 + 0 + 0 + 0 + 0 + 0 + Choose language in the menu above. + - False - True - - - - - - True - Highlighting text styles - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - - - tab + 0 + True + True diff --git a/moo/mooedit/glade/mooeditprefs.glade b/moo/mooedit/glade/mooeditprefs.glade index b19e806e..a9f64169 100644 --- a/moo/mooedit/glade/mooeditprefs.glade +++ b/moo/mooedit/glade/mooeditprefs.glade @@ -682,26 +682,6 @@ True - - - - True - True - Highlight matching brackets - True - GTK_RELIEF_NORMAL - False - False - False - True - - - - 0 - False - False - - @@ -757,977 +737,6 @@ tab - - - - True - False - 0 - - - - 3 - True - 0 - 0.5 - GTK_SHADOW_ETCHED_IN - - - - True - 0.5 - 0.5 - 1 - 1 - 0 - 3 - 3 - 3 - - - - True - False - 0 - - - - True - True - Use default theme font - True - GTK_RELIEF_NORMAL - False - False - False - True - - - - 0 - False - False - - - - - - True - False - 0 - - - - - True - Editor font: - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - font - - - 0 - False - False - - - - - - True - True - True - True - True - True - False - - - - 0 - True - True - - - - - 0 - True - True - - - - - - - - - - True - Font - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - - - label_item - - - - - 0 - False - False - - - - - - 3 - True - 0 - 0.5 - GTK_SHADOW_ETCHED_IN - - - - True - 0.5 - 0.5 - 1 - 1 - 0 - 3 - 3 - 3 - - - - True - False - 0 - - - - True - True - Use default theme colors - True - GTK_RELIEF_NORMAL - False - False - False - True - - - - 0 - False - False - - - - - - True - 4 - 2 - False - 0 - 0 - - - - - True - Text color: - True - False - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - text_color - - - 0 - 1 - 0 - 1 - fill - - - - - - - True - Background color: - True - False - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - text_background_color - - - 0 - 1 - 1 - 2 - fill - - - - - - - True - True - False - False - - - - - 1 - 2 - 0 - 1 - - - - - - - True - True - False - False - - - - - 1 - 2 - 1 - 2 - - - - - - - True - Selected text color: - True - False - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - selected_text_color - - - 0 - 1 - 2 - 3 - fill - - - - - - - True - Selection color: - True - False - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - selection_color - - - 0 - 1 - 3 - 4 - fill - - - - - - - True - True - False - False - - - - - 1 - 2 - 2 - 3 - fill - - - - - - - True - True - False - False - - - - - 1 - 2 - 3 - 4 - fill - - - - - - 0 - True - True - - - - - - - - - - True - Colors - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - - - label_item - - - - - 0 - False - False - - - - - - 3 - True - 0 - 0.5 - GTK_SHADOW_ETCHED_IN - - - - True - 0.5 - 0.5 - 1 - 1 - 0 - 3 - 3 - 3 - - - - True - False - 0 - - - - True - True - Highlight current line - True - GTK_RELIEF_NORMAL - False - False - False - True - - - - 0 - False - False - - - - - - True - True - False - False - - - - - 0 - False - False - - - - - - - - - - True - Current Line - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - - - label_item - - - - - 0 - False - False - - - - - False - True - - - - - - True - Font and Colors - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - - - tab - - - - - - 3 - True - 0 - 0.5 - GTK_SHADOW_ETCHED_IN - - - - True - 0.5 - 0.5 - 1 - 1 - 0 - 3 - 3 - 3 - - - - True - False - 0 - - - - - True - False - 0 - - - - True - Highlight mode: - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - language_combo - - - 0 - False - False - - - - - - True - - - - 0 - True - True - - - - - 0 - False - False - - - - - - True - 0 - 0.5 - GTK_SHADOW_NONE - - - - True - 0.5 - 0.5 - 1 - 1 - 6 - 0 - 3 - 3 - - - - True - False - 0 - - - - True - True - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - GTK_SHADOW_IN - GTK_CORNER_TOP_LEFT - - - - True - True - False - False - False - False - - - - - 0 - True - True - - - - - - True - False - 0 - - - - True - 0.5 - 0.5 - 1 - 1 - 12 - 12 - 12 - 6 - - - - True - False - 12 - - - - True - True - GTK_RELIEF_NONE - False - False - False - - - - True - gtk-bold - 4 - 0.5 - 0.5 - 0 - 0 - - - - - 0 - False - False - - - - - - True - True - GTK_RELIEF_NONE - False - False - False - - - - True - gtk-italic - 4 - 0.5 - 0.5 - 0 - 0 - - - - - 0 - False - False - - - - - - True - True - GTK_RELIEF_NONE - False - False - False - - - - True - gtk-underline - 4 - 0.5 - 0.5 - 0 - 0 - - - - - 0 - False - False - - - - - - True - True - GTK_RELIEF_NONE - False - False - False - - - - True - gtk-strikethrough - 4 - 0.5 - 0.5 - 0 - 0 - - - - - 0 - False - False - - - - - - - 0 - False - False - - - - - - True - 0.5 - 0.5 - 1 - 1 - 12 - 12 - 12 - 12 - - - - True - 2 - 2 - False - 0 - 6 - - - - True - True - False - False - - - - 1 - 2 - 0 - 1 - - - - - - - - True - True - False - False - - - - 1 - 2 - 1 - 2 - - - - - - - - True - True - Foreground: - True - GTK_RELIEF_NORMAL - False - False - False - True - - - 0 - 1 - 0 - 1 - fill - - - - - - - True - True - Background: - True - GTK_RELIEF_NORMAL - False - False - False - True - - - 0 - 1 - 1 - 2 - fill - - - - - - - - 0 - False - False - - - - - - - - - 0 - False - True - - - - - - - - - 0 - True - True - - - - - - - - - - True - Highlight syntax with colors in editor - True - Use Highlighting - True - GTK_RELIEF_NORMAL - False - False - False - True - - - - label_item - - - - - False - True - - - - - - True - Syntax Highlighting - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - - - tab - - 0 diff --git a/moo/mooedit/mooedit.c b/moo/mooedit/mooedit.c index 4e8a5a56..6cae61e7 100644 --- a/moo/mooedit/mooedit.c +++ b/moo/mooedit/mooedit.c @@ -520,7 +520,7 @@ moo_edit_set_lang (MooEdit *edit, MooLang *lang) { g_return_if_fail (MOO_IS_EDIT (edit)); - moo_text_buffer_set_lang (get_moo_buffer (edit), lang); + moo_text_view_set_lang (MOO_TEXT_VIEW (edit), lang); } @@ -698,8 +698,8 @@ _moo_edit_choose_lang (MooEdit *edit) if (edit->priv->filename) { - MooLangTable *table = moo_editor_get_lang_table (edit->priv->editor); - lang = moo_lang_table_get_lang_for_file (table, edit->priv->filename); + MooLangMgr *mgr = moo_editor_get_lang_mgr (edit->priv->editor); + lang = moo_lang_mgr_get_lang_for_file (mgr, edit->priv->filename); } moo_edit_set_lang (edit, lang); diff --git a/moo/mooedit/mooeditor.c b/moo/mooedit/mooeditor.c index e6bf5ed3..83306476 100644 --- a/moo/mooedit/mooeditor.c +++ b/moo/mooedit/mooeditor.c @@ -94,7 +94,7 @@ struct _MooEditorPrivate { MooUIXML *ui_xml; MooFilterMgr *filter_mgr; MooHistoryList *history; - MooLangTable *lang_table; + MooLangMgr *lang_mgr; MooFileWatch *file_watch; gboolean open_single; gboolean allow_empty_window; @@ -185,7 +185,7 @@ static void moo_editor_init (MooEditor *editor) { editor->priv = g_new0 (MooEditorPrivate, 1); - editor->priv->lang_table = moo_lang_table_new (); + editor->priv->lang_mgr = moo_lang_mgr_new (); editor->priv->filter_mgr = moo_filter_mgr_new (); editor->priv->history = moo_history_list_new ("Editor"); @@ -274,7 +274,7 @@ static void moo_editor_finalize (GObject *object) g_object_unref (editor->priv->filter_mgr); if (editor->priv->history) g_object_unref (editor->priv->history); - g_object_unref (editor->priv->lang_table); + g_object_unref (editor->priv->lang_mgr); if (editor->priv->file_watch) { @@ -1360,9 +1360,9 @@ moo_editor_get_doc (MooEditor *editor, } -MooLangTable* -moo_editor_get_lang_table (MooEditor *editor) +MooLangMgr* +moo_editor_get_lang_mgr (MooEditor *editor) { g_return_val_if_fail (MOO_IS_EDITOR (editor), NULL); - return editor->priv->lang_table; + return editor->priv->lang_mgr; } diff --git a/moo/mooedit/mooeditor.h b/moo/mooedit/mooeditor.h index 221d74e7..601b9210 100644 --- a/moo/mooedit/mooeditor.h +++ b/moo/mooedit/mooeditor.h @@ -16,6 +16,7 @@ #define __MOO_EDITOR_H__ #include +#include #include #include #include @@ -97,7 +98,7 @@ void moo_editor_set_ui_xml (MooEditor *editor, MooEditor *moo_edit_window_get_editor (MooEditWindow *window); -MooLangTable *moo_editor_get_lang_table (MooEditor *editor); +MooLangMgr *moo_editor_get_lang_mgr (MooEditor *editor); #ifdef MOOEDIT_COMPILATION diff --git a/moo/mooedit/mooeditprefspage.c b/moo/mooedit/mooeditprefspage.c index a4fc266e..006adce8 100644 --- a/moo/mooedit/mooeditprefspage.c +++ b/moo/mooedit/mooeditprefspage.c @@ -15,46 +15,819 @@ #define MOOEDIT_COMPILATION #include "mooedit/mooedit-private.h" #include "mooedit/mooeditprefs.h" -#include "mooedit/mooeditprefs-glade.h" +// #include "mooedit/mooeditprefs-glade.h" #include "mooedit/mooeditcolorsprefs-glade.h" #include "mooutils/mooprefsdialog.h" #include "mooutils/moocompat.h" #include "mooutils/moostock.h" #include "mooutils/mooglade.h" +#include "mooutils/moocellrenderercolor.h" #include -GtkWidget* -moo_edit_prefs_page_new (MooEditor *editor) -{ - GtkWidget *page; +static void color_page_init (MooPrefsDialogPage *page); +static void color_page_apply (MooPrefsDialogPage *page); - g_return_val_if_fail (MOO_IS_EDITOR (editor), NULL); +static void scheme_combo_init (GtkWidget *combo, + MooEditor *editor); +static void scheme_combo_data_func (GtkCellLayout *layout, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter); +static void scheme_combo_set_scheme (GtkComboBox *combo, + MooTextStyleScheme *scheme); +static void scheme_combo_changed (GtkComboBox *combo, + MooPrefsDialogPage *page); - _moo_edit_set_default_settings (); +static void syntax_combo_init (GtkWidget *combo, + MooEditor *editor); +static void syntax_combo_data_func (GtkCellLayout *layout, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter); +static void syntax_combo_set_lang (GtkComboBox *combo, + MooLang *lang); +static void syntax_combo_changed (GtkComboBox *combo, + MooPrefsDialogPage *page); - page = moo_prefs_dialog_page_new_from_xml ("Editor", - GTK_STOCK_EDIT, - MOO_EDIT_PREFS_GLADE_UI, - -1, - "page", - MOO_EDIT_PREFS_PREFIX); - return page; -} +static MooLangMgr *page_get_mgr (MooPrefsDialogPage *page); +static MooEditor *page_get_editor (MooPrefsDialogPage *page); +static void page_set_scheme (MooPrefsDialogPage *page, + MooTextStyleScheme *scheme); +static void page_set_lang (MooPrefsDialogPage *page, + MooLang *lang); +static GtkWidget *page_get_preview (MooPrefsDialogPage *page); +static void preview_set_lang (GtkWidget *preview, + MooLang *lang); +static MooTextStyleScheme *page_get_scheme (MooPrefsDialogPage *page); +static MooLang *page_get_lang (MooPrefsDialogPage *page); + + +static void default_treeview_init (GtkTreeView *treeview, + MooPrefsDialogPage *page); +static void default_treeview_set_scheme (GtkTreeView *treeview, + MooTextStyleScheme *scheme); + +static void lang_treeview_init (GtkTreeView *treeview, + MooPrefsDialogPage *page); + +static void treeview_apply_scheme (GtkWidget *widget, + MooTextStyleScheme *scheme); GtkWidget* moo_edit_colors_prefs_page_new (MooEditor *editor) { - GtkWidget *page; + MooPrefsDialogPage *page; + GtkWidget *scheme_combo, *syntax_combo; + GtkTreeView *default_treeview;//, *lang_treeview; + MooGladeXML *xml; g_return_val_if_fail (MOO_IS_EDITOR (editor), NULL); - page = moo_prefs_dialog_page_new_from_xml ("Editor Colors", - GTK_STOCK_EDIT, - MOO_EDIT_COLORS_PREFS_GLADE_UI, - -1, - "page", - MOO_EDIT_PREFS_PREFIX); - return page; + xml = moo_glade_xml_new_empty (); + moo_glade_xml_map_id (xml, "page", MOO_TYPE_PREFS_DIALOG_PAGE); + moo_glade_xml_map_id (xml, "sample_view", MOO_TYPE_TEXT_VIEW); + moo_glade_xml_parse_memory (xml, MOO_EDIT_COLORS_PREFS_GLADE_UI, -1, "page"); + + page = moo_glade_xml_get_widget (xml, "page"); + page->xml = xml; + + g_object_set (page, + "label", "Font and Colors", + "icon-stock-id", GTK_STOCK_EDIT, + NULL); + + g_object_set_data_full (G_OBJECT (page), "moo-editor", + g_object_ref (editor), g_object_unref); + g_object_set_data_full (G_OBJECT (page), "moo-lang-mgr", + g_object_ref (moo_editor_get_lang_mgr (editor)), + g_object_unref); + + g_signal_connect (page, "init", G_CALLBACK (color_page_init), NULL); +// g_signal_connect (page, "apply", G_CALLBACK (color_page_apply), NULL); + + scheme_combo = moo_glade_xml_get_widget (xml, "scheme_combo"); + scheme_combo_init (scheme_combo, editor); + g_signal_connect (scheme_combo, "changed", + G_CALLBACK (scheme_combo_changed), page); + + syntax_combo = moo_glade_xml_get_widget (xml, "syntax_combo"); + syntax_combo_init (syntax_combo, editor); + g_signal_connect (syntax_combo, "changed", + G_CALLBACK (syntax_combo_changed), page); + + default_treeview = moo_glade_xml_get_widget (xml, "default_treeview"); + default_treeview_init (default_treeview, page); + +// lang_treeview = moo_glade_xml_get_widget (xml, "lang_treeview"); +// lang_treeview_init (lang_treeview, page, editor); + + return GTK_WIDGET (page); +} + + +static void +scheme_combo_init (GtkWidget *combo, + MooEditor *editor) +{ + GtkListStore *store; + MooLangMgr *mgr; + GSList *list, *l; + GtkCellRenderer *cell; + + mgr = moo_editor_get_lang_mgr (editor); + list = moo_lang_mgr_list_schemes (mgr); + g_return_if_fail (list != NULL); + + store = gtk_list_store_new (1, MOO_TYPE_TEXT_STYLE_SCHEME); + + for (l = list; l != NULL; l = l->next) + { + GtkTreeIter iter; + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, 0, l->data, -1); + } + + gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (store)); + + cell = gtk_cell_renderer_text_new (); + gtk_cell_layout_clear (GTK_CELL_LAYOUT (combo)); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE); + gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo), cell, + (GtkCellLayoutDataFunc) scheme_combo_data_func, + NULL, NULL); + + g_object_unref (store); + g_slist_free (list); +} + + +static void +scheme_combo_data_func (G_GNUC_UNUSED GtkCellLayout *layout, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter) +{ + MooTextStyleScheme *scheme = NULL; + gtk_tree_model_get (model, iter, 0, &scheme, -1); + g_return_if_fail (scheme != NULL); + g_object_set (cell, "text", scheme->name, NULL); + g_object_unref (scheme); +} + + +static GtkWidget* +page_get_preview (MooPrefsDialogPage *page) +{ + return moo_glade_xml_get_widget (page->xml, "sample_view"); +} + + +static void +color_page_init (MooPrefsDialogPage *page) +{ + MooEditor *editor; + MooLangMgr *mgr; + MooTextStyleScheme *scheme; + GtkComboBox *scheme_combo, *syntax_combo; + + editor = page_get_editor (page); + mgr = moo_editor_get_lang_mgr (editor); + scheme = moo_lang_mgr_get_active_scheme (mgr); + g_return_if_fail (scheme != NULL); + + scheme_combo = moo_glade_xml_get_widget (page->xml, "scheme_combo"); + scheme_combo_set_scheme (scheme_combo, scheme); + + syntax_combo = moo_glade_xml_get_widget (page->xml, "syntax_combo"); + syntax_combo_set_lang (syntax_combo, NULL); +} + + +static MooEditor* + page_get_editor (MooPrefsDialogPage *page) +{ + return g_object_get_data (G_OBJECT (page), "moo-editor"); +} + + +static MooLangMgr* +page_get_mgr (MooPrefsDialogPage *page) +{ + return g_object_get_data (G_OBJECT (page), "moo-lang-mgr"); +} + + +static void +scheme_combo_set_scheme (GtkComboBox *combo, + MooTextStyleScheme *scheme) +{ + GtkTreeModel *model = gtk_combo_box_get_model (combo); + gboolean found = FALSE; + GtkTreeIter iter; + + gtk_tree_model_get_iter_first (model, &iter); + do { + MooTextStyleScheme *s; + gtk_tree_model_get (model, &iter, 0, &s, -1); + g_object_unref (s); + if (scheme == s) + { + found = TRUE; + break; + } + } + while (gtk_tree_model_iter_next (model, &iter)); + + g_return_if_fail (found); + + gtk_combo_box_set_active_iter (combo, &iter); +} + + +static void +scheme_combo_changed (GtkComboBox *combo, + MooPrefsDialogPage *page) +{ + GtkTreeModel *model; + GtkTreeIter iter; + MooTextStyleScheme *scheme = NULL; + + if (!gtk_combo_box_get_active_iter (combo, &iter)) + g_return_if_reached (); + + model = gtk_combo_box_get_model (combo); + gtk_tree_model_get (model, &iter, 0, &scheme, -1); + g_return_if_fail (scheme != NULL); + + page_set_scheme (page, scheme); + g_object_unref (scheme); +} + + +static void +page_set_scheme (MooPrefsDialogPage *page, + MooTextStyleScheme *scheme) +{ + GtkColorButton *fg, *bg, *sel_fg, *sel_bg, *cur_line; + GdkColor color; + GdkScreen *screen; + + g_return_if_fail (scheme != NULL); + + g_object_set_data (G_OBJECT (page), "moo-text-style-scheme", scheme); + + if (gtk_widget_has_screen (GTK_WIDGET (page))) + screen = gtk_widget_get_screen (GTK_WIDGET (page)); + else + screen = gdk_screen_get_default (); + + fg = moo_glade_xml_get_widget (page->xml, "foreground"); + bg = moo_glade_xml_get_widget (page->xml, "background"); + sel_fg = moo_glade_xml_get_widget (page->xml, "selected_foreground"); + sel_bg = moo_glade_xml_get_widget (page->xml, "selected_background"); + cur_line = moo_glade_xml_get_widget (page->xml, "current_line"); + + _moo_text_style_scheme_get_color (scheme, MOO_TEXT_COLOR_FG, &color, screen); + gtk_color_button_set_color (fg, &color); + _moo_text_style_scheme_get_color (scheme, MOO_TEXT_COLOR_BG, &color, screen); + gtk_color_button_set_color (bg, &color); + _moo_text_style_scheme_get_color (scheme, MOO_TEXT_COLOR_SEL_FG, &color, screen); + gtk_color_button_set_color (sel_fg, &color); + _moo_text_style_scheme_get_color (scheme, MOO_TEXT_COLOR_SEL_BG, &color, screen); + gtk_color_button_set_color (sel_bg, &color); + _moo_text_style_scheme_get_color (scheme, MOO_TEXT_COLOR_CUR_LINE, &color, screen); + gtk_color_button_set_color (cur_line, &color); + + moo_text_view_apply_scheme (MOO_TEXT_VIEW (page_get_preview (page)), scheme); + default_treeview_set_scheme (moo_glade_xml_get_widget (page->xml, "default_treeview"), scheme); +} + + +static int +cmp_langs (MooLang *lang1, + MooLang *lang2) +{ + int result; + + if (!lang1 || !lang2) + return lang1 < lang2 ? -1 : (lang1 > lang2 ? 1 : 0); + + result = strcmp (lang1->section, lang2->section); + if (!result) + result = strcmp (lang1->name, lang2->name); + + return result; +} + + +static void +syntax_combo_init (GtkWidget *combo, + MooEditor *editor) +{ + GtkListStore *store; + MooLangMgr *mgr; + GSList *list, *l; + GtkCellRenderer *cell; + + mgr = moo_editor_get_lang_mgr (editor); + + list = moo_lang_mgr_get_available_langs (mgr); + list = g_slist_prepend (list, NULL); + list = g_slist_sort (list, (GCompareFunc) cmp_langs); + + store = gtk_list_store_new (1, MOO_TYPE_LANG); + + for (l = list; l != NULL; l = l->next) + { + GtkTreeIter iter; + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, 0, l->data, -1); + } + + gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (store)); + + cell = gtk_cell_renderer_text_new (); + gtk_cell_layout_clear (GTK_CELL_LAYOUT (combo)); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE); + gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo), cell, + (GtkCellLayoutDataFunc) syntax_combo_data_func, + NULL, NULL); + + g_object_unref (store); + g_slist_free (list); +} + + +static void +syntax_combo_data_func (G_GNUC_UNUSED GtkCellLayout *layout, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter) +{ + MooLang *lang = NULL; + + gtk_tree_model_get (model, iter, 0, &lang, -1); + + if (lang) + { + char *text = g_strdup_printf ("%s/%s", lang->section, lang->name); + g_object_set (cell, "text", text, NULL); + g_free (text); + moo_lang_unref (lang); + } + else + { + g_object_set (cell, "text", "None", NULL); + } +} + + +static void +syntax_combo_changed (GtkComboBox *combo, + MooPrefsDialogPage *page) +{ + GtkTreeModel *model; + GtkTreeIter iter; + MooLang *lang = NULL; + + if (!gtk_combo_box_get_active_iter (combo, &iter)) + g_return_if_reached (); + + model = gtk_combo_box_get_model (combo); + gtk_tree_model_get (model, &iter, 0, &lang, -1); + + page_set_lang (page, lang); + + if (lang) + moo_lang_unref (lang); +} + + +static void +syntax_combo_set_lang (GtkComboBox *combo, + MooLang *lang) +{ + GtkTreeModel *model = gtk_combo_box_get_model (combo); + gboolean found = FALSE; + GtkTreeIter iter; + + gtk_tree_model_get_iter_first (model, &iter); + + do { + MooLang *l; + + gtk_tree_model_get (model, &iter, 0, &l, -1); + + if (l) + moo_lang_unref (l); + + if (lang == l) + { + found = TRUE; + break; + } + } + while (gtk_tree_model_iter_next (model, &iter)); + + g_return_if_fail (found); + + gtk_combo_box_set_active_iter (combo, &iter); +} + + +static void +preview_set_lang (GtkWidget *preview, + MooLang *lang) +{ + if (lang && lang->sample) + { + GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (preview)); + gtk_text_buffer_set_text (buf, lang->sample, -1); + } + + moo_text_view_set_lang (MOO_TEXT_VIEW (preview), lang); +} + + +static void +page_set_lang (MooPrefsDialogPage *page, + MooLang *lang) +{ + g_object_set_data (G_OBJECT (page), "moo-lang", lang); + preview_set_lang (page_get_preview (page), lang); +} + + +static MooTextStyleScheme* +page_get_scheme (MooPrefsDialogPage *page) +{ + return g_object_get_data (G_OBJECT (page), "moo-text-style-scheme"); +} + + +static MooLang* +page_get_lang (MooPrefsDialogPage *page) +{ + return g_object_get_data (G_OBJECT (page), "moo-lang"); +} + + +/********************************************************************/ +/* Default styles list + */ + +static void default_treeview_style_func (GtkTreeViewColumn *column, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter, + MooPrefsDialogPage *page); +static void default_treeview_toggle_func (GtkTreeViewColumn *column, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter, + MooPrefsDialogPage *page); +static void default_treeview_color_func (GtkTreeViewColumn *column, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter, + MooPrefsDialogPage *page); + + +static void +default_treeview_create_toggle (GtkTreeView *treeview, + MooPrefsDialogPage *page, + MooTextStyleMask mask, + const char *title) +{ + GtkCellRenderer *cell; + GtkTreeViewColumn *column; + GtkWidget *label; + + cell = gtk_cell_renderer_toggle_new (); + g_object_set (cell, "activatable", TRUE, NULL); + g_object_set_data (G_OBJECT (cell), "moo-text-style-mask", GUINT_TO_POINTER (mask)); + + column = gtk_tree_view_column_new (); + gtk_tree_view_column_pack_start (column, cell, FALSE); + gtk_tree_view_column_set_cell_data_func (column, cell, + (GtkTreeCellDataFunc) default_treeview_toggle_func, + page, NULL); + gtk_tree_view_column_set_expand (column, FALSE); + gtk_tree_view_append_column (treeview, column); + + label = gtk_label_new (title); + gtk_widget_show (label); + gtk_label_set_use_markup (GTK_LABEL (label), TRUE); + gtk_tree_view_column_set_widget (column, label); +} + +static void +default_treeview_create_color (GtkTreeView *treeview, + MooPrefsDialogPage *page, + MooTextStyleMask mask, + const char *title) +{ + GtkCellRenderer *cell; + GtkTreeViewColumn *column; + + cell = moo_cell_renderer_color_new (); + g_object_set (cell, "activatable", TRUE, NULL); + g_object_set_data (G_OBJECT (cell), "moo-text-style-mask", GUINT_TO_POINTER (mask)); + + column = gtk_tree_view_column_new (); + gtk_tree_view_column_set_title (column, title); + gtk_tree_view_column_pack_start (column, cell, TRUE); + gtk_tree_view_column_set_cell_data_func (column, cell, + (GtkTreeCellDataFunc) default_treeview_color_func, + page, NULL); + gtk_tree_view_column_set_expand (column, FALSE); + gtk_tree_view_append_column (treeview, column); +} + +static void +default_treeview_init (GtkTreeView *treeview, + MooPrefsDialogPage *page) +{ + GtkCellRenderer *cell; + GtkListStore *store; + GtkTreeViewColumn *column; + + gtk_tree_selection_set_mode (gtk_tree_view_get_selection (treeview), + GTK_SELECTION_NONE); + + store = gtk_list_store_new (1, G_TYPE_STRING); + gtk_tree_view_set_model (treeview, GTK_TREE_MODEL (store)); + g_object_unref (store); + + cell = gtk_cell_renderer_text_new (); + gtk_tree_view_insert_column_with_data_func (treeview, -1, "Style", cell, + (GtkTreeCellDataFunc) default_treeview_style_func, page, NULL); + column = gtk_tree_view_get_column (treeview, 0); + + default_treeview_create_color (treeview, page, MOO_TEXT_STYLE_FOREGROUND, "Foreground"); + default_treeview_create_color (treeview, page, MOO_TEXT_STYLE_BACKGROUND, "Background"); + + default_treeview_create_toggle (treeview, page, MOO_TEXT_STYLE_BOLD, "B"); + default_treeview_create_toggle (treeview, page, MOO_TEXT_STYLE_ITALIC, "I"); + default_treeview_create_toggle (treeview, page, MOO_TEXT_STYLE_UNDERLINE, "U"); + default_treeview_create_toggle (treeview, page, MOO_TEXT_STYLE_STRIKETHROUGH, "S"); +} + + +static void +text_cell_set_props_from_style (GtkCellRenderer *cell, + MooTextStyle *style) +{ + g_return_if_fail (style != NULL); + + if ((style->mask & MOO_TEXT_STYLE_BOLD) && style->bold) + g_object_set (cell, "weight", PANGO_WEIGHT_BOLD, NULL); + else + g_object_set (cell, "weight-set", FALSE, NULL); + + if ((style->mask & MOO_TEXT_STYLE_ITALIC) && style->italic) + g_object_set (cell, "style", PANGO_STYLE_ITALIC, NULL); + else + g_object_set (cell, "style-set", FALSE, NULL); + + if ((style->mask & MOO_TEXT_STYLE_UNDERLINE) && style->underline) + g_object_set (cell, "underline", PANGO_UNDERLINE_SINGLE, NULL); + else + g_object_set (cell, "underline", PANGO_UNDERLINE_NONE, NULL); + + if ((style->mask & MOO_TEXT_STYLE_STRIKETHROUGH) && style->strikethrough) + g_object_set (cell, "strikethrough", TRUE, NULL); + else + g_object_set (cell, "strikethrough", FALSE, NULL); + + if (style->mask & MOO_TEXT_STYLE_FOREGROUND) + g_object_set (cell, "foreground-gdk", &style->foreground, NULL); + else + g_object_set (cell, "foreground-set", FALSE, NULL); + + if (style->mask & MOO_TEXT_STYLE_BACKGROUND) + g_object_set (cell, "background-gdk", &style->background, NULL); + else + g_object_set (cell, "background-set", FALSE, NULL); +} + + +static void +default_treeview_style_func (G_GNUC_UNUSED GtkTreeViewColumn *column, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter, + G_GNUC_UNUSED MooPrefsDialogPage *page) +{ + char *style_name; + MooTextStyle *style; + + gtk_tree_model_get (model, iter, 0, &style_name, -1); + g_return_if_fail (style_name != NULL); + + style = moo_lang_mgr_get_style (page_get_mgr (page), + NULL, style_name, + page_get_scheme (page)); + g_return_if_fail (style != NULL); + + text_cell_set_props_from_style (cell, style); + g_object_set (cell, "text", style_name, NULL); + + moo_text_style_free (style); + g_free (style_name); +} + + +static void +default_treeview_toggle_func (G_GNUC_UNUSED GtkTreeViewColumn *column, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter, + MooPrefsDialogPage *page) +{ + char *style_name; + MooTextStyle *style; + MooTextStyleMask mask; + gboolean active = FALSE; + + gtk_tree_model_get (model, iter, 0, &style_name, -1); + g_return_if_fail (style_name != NULL); + + style = moo_lang_mgr_get_style (page_get_mgr (page), + NULL, style_name, + page_get_scheme (page)); + g_return_if_fail (style != NULL); + + mask = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (cell), "moo-text-style-mask")); + + /* XXX */ + if (mask & style->mask) + { + switch (mask) + { + case MOO_TEXT_STYLE_BOLD: + active = style->bold ? TRUE : FALSE; + break; + case MOO_TEXT_STYLE_ITALIC: + active = style->italic ? TRUE : FALSE; + break; + case MOO_TEXT_STYLE_UNDERLINE: + active = style->underline ? TRUE : FALSE; + break; + case MOO_TEXT_STYLE_STRIKETHROUGH: + active = style->strikethrough ? TRUE : FALSE; + break; + default: + g_return_if_reached (); + } + } + + g_object_set (cell, "active", active, NULL); + moo_text_style_free (style); + g_free (style_name); +} + + +static void +default_treeview_color_func (G_GNUC_UNUSED GtkTreeViewColumn *column, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter, + MooPrefsDialogPage *page) +{ + char *style_name; + MooTextStyle *style; + MooTextStyleScheme *scheme; + MooTextStyleMask mask; + GdkScreen *screen; + + if (!gtk_widget_has_screen (GTK_WIDGET (page))) + return; + + screen = gtk_widget_get_screen (GTK_WIDGET (page)); + + gtk_tree_model_get (model, iter, 0, &style_name, -1); + g_return_if_fail (style_name != NULL); + + scheme = page_get_scheme (page); + style = moo_lang_mgr_get_style (page_get_mgr (page), + NULL, style_name, + scheme); + g_return_if_fail (style != NULL); + + mask = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (cell), "moo-text-style-mask")); + + switch (mask) + { + case MOO_TEXT_STYLE_FOREGROUND: + if (style->mask & MOO_TEXT_STYLE_FOREGROUND) + g_object_set (cell, "color", &style->foreground, NULL); + else + g_object_set (cell, "color-set", FALSE, NULL); + break; + case MOO_TEXT_STYLE_BACKGROUND: + if (style->mask & MOO_TEXT_STYLE_BACKGROUND) + g_object_set (cell, "color", &style->background, NULL); + else + g_object_set (cell, "color-set", FALSE, NULL); + break; + default: + g_return_if_reached (); + } + + moo_text_style_free (style); + g_free (style_name); +} + + +static void +default_treeview_set_scheme (GtkTreeView *treeview, + MooTextStyleScheme *scheme) +{ + GtkListStore *store; + GtkTreeModel *model; + GSList *styles, *l; + GtkTreeIter iter; + + treeview_apply_scheme (GTK_WIDGET (treeview), scheme); + + model = gtk_tree_view_get_model (treeview); + store = GTK_LIST_STORE (model); + gtk_list_store_clear (store); + + styles = moo_text_style_scheme_list_default (scheme); + + for (l = styles; l != NULL; l = l->next) + { + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, 0, l->data, -1); + } + + g_slist_foreach (styles, (GFunc) g_free, NULL); + g_slist_free (styles); +} + + +static void +treeview_apply_scheme (GtkWidget *widget, + MooTextStyleScheme *scheme) +{ + GdkColor color; + GdkColor *color_ptr; + + g_return_if_fail (scheme != NULL); + + gtk_widget_ensure_style (widget); + + color_ptr = NULL; + if (scheme->text_colors[MOO_TEXT_COLOR_FG]) + { + if (gdk_color_parse (scheme->text_colors[MOO_TEXT_COLOR_FG], &color)) + color_ptr = &color; + else + g_warning ("%s: could not parse color '%s'", G_STRLOC, + scheme->text_colors[MOO_TEXT_COLOR_FG]); + } + gtk_widget_modify_text (widget, GTK_STATE_NORMAL, color_ptr); + gtk_widget_modify_text (widget, GTK_STATE_ACTIVE, color_ptr); + gtk_widget_modify_text (widget, GTK_STATE_PRELIGHT, color_ptr); + gtk_widget_modify_text (widget, GTK_STATE_INSENSITIVE, color_ptr); + + color_ptr = NULL; + if (scheme->text_colors[MOO_TEXT_COLOR_BG]) + { + if (gdk_color_parse (scheme->text_colors[MOO_TEXT_COLOR_BG], &color)) + color_ptr = &color; + else + g_warning ("%s: could not parse color '%s'", G_STRLOC, + scheme->text_colors[MOO_TEXT_COLOR_BG]); + } + gtk_widget_modify_base (widget, GTK_STATE_NORMAL, color_ptr); + gtk_widget_modify_base (widget, GTK_STATE_ACTIVE, color_ptr); + gtk_widget_modify_base (widget, GTK_STATE_PRELIGHT, color_ptr); + gtk_widget_modify_base (widget, GTK_STATE_INSENSITIVE, color_ptr); + + color_ptr = NULL; + if (scheme->text_colors[MOO_TEXT_COLOR_SEL_FG]) + { + if (gdk_color_parse (scheme->text_colors[MOO_TEXT_COLOR_SEL_FG], &color)) + color_ptr = &color; + else + g_warning ("%s: could not parse color '%s'", G_STRLOC, + scheme->text_colors[MOO_TEXT_COLOR_SEL_FG]); + } + gtk_widget_modify_text (widget, GTK_STATE_SELECTED, color_ptr); + + color_ptr = NULL; + if (scheme->text_colors[MOO_TEXT_COLOR_SEL_BG]) + { + if (gdk_color_parse (scheme->text_colors[MOO_TEXT_COLOR_SEL_BG], &color)) + color_ptr = &color; + else + g_warning ("%s: could not parse color '%s'", G_STRLOC, + scheme->text_colors[MOO_TEXT_COLOR_SEL_BG]); + } + gtk_widget_modify_base (widget, GTK_STATE_SELECTED, color_ptr); } diff --git a/moo/mooedit/mooeditwindow.c b/moo/mooedit/mooeditwindow.c index f86f2222..077e1fd5 100644 --- a/moo/mooedit/mooeditwindow.c +++ b/moo/mooedit/mooeditwindow.c @@ -695,14 +695,14 @@ static void apply_styles (MooEditWindow *window, MooEdit *edit) { - MooLangTable *table; + MooLangMgr *mgr; MooTextStyleScheme *scheme; - table = moo_editor_get_lang_table (window->priv->editor); - scheme = moo_lang_table_get_active_scheme (table); + mgr = moo_editor_get_lang_mgr (window->priv->editor); + scheme = moo_lang_mgr_get_active_scheme (mgr); g_return_if_fail (scheme != NULL); - _moo_text_style_scheme_apply (scheme, edit); + moo_text_view_apply_scheme (MOO_TEXT_VIEW (edit), scheme); } @@ -1637,18 +1637,18 @@ static void lang_item_activated (MooEditWindow *window, const char *lang_name) { - MooLangTable *table; + MooLangMgr *mgr; MooLang *lang = NULL; MooEdit *doc = ACTIVE_DOC (window); g_return_if_fail (doc != NULL); g_return_if_fail (MOO_IS_EDIT_WINDOW (window)); - table = moo_editor_get_lang_table (window->priv->editor); + mgr = moo_editor_get_lang_mgr (window->priv->editor); if (lang_name) { - lang = moo_lang_table_get_lang (table, lang_name); + lang = moo_lang_mgr_get_lang (mgr, lang_name); g_return_if_fail (lang != NULL); } @@ -1661,16 +1661,16 @@ create_lang_action (MooEditWindow *window) { MooAction *action; MooMenuMgr *menu_mgr; - MooLangTable *table; + MooLangMgr *lang_mgr; GSList *langs, *sections, *l; - table = moo_editor_get_lang_table (window->priv->editor); + lang_mgr = moo_editor_get_lang_mgr (window->priv->editor); /* TODO display names, etc. */ - sections = moo_lang_table_get_sections (table); + sections = moo_lang_mgr_get_sections (lang_mgr); sections = g_slist_sort (sections, (GCompareFunc) strcmp); - langs = moo_lang_table_get_available_langs (table); + langs = moo_lang_mgr_get_available_langs (lang_mgr); langs = g_slist_sort (langs, (GCompareFunc) cmp_langs); action = moo_menu_action_new (LANG_ACTION_ID); diff --git a/moo/mooedit/moohighlighter.c b/moo/mooedit/moohighlighter.c index cffa461d..510fd405 100644 --- a/moo/mooedit/moohighlighter.c +++ b/moo/mooedit/moohighlighter.c @@ -277,7 +277,7 @@ create_tag (MooHighlighter *hl, _moo_lang_set_tag_style (rule ? rule->context->lang : ctx_node->ctx->lang, tag, rule ? rule->context : ctx_node->ctx, - rule); + rule, NULL); ctx_node->child_tags = g_slist_prepend (ctx_node->child_tags, tag); return tag; @@ -750,3 +750,35 @@ moo_highlighter_apply_tags (MooHighlighter *hl, LINE_SET_TAGS_APPLIED (line); } } + + +static void +tag_set_scheme (G_GNUC_UNUSED gpointer whatever, + MooSyntaxTag *tag, + MooTextStyleScheme *scheme) +{ + if (tag) + { + _moo_lang_erase_tag_style (GTK_TEXT_TAG (tag)); + _moo_lang_set_tag_style (tag->rule ? tag->rule->context->lang : tag->ctx_node->ctx->lang, + GTK_TEXT_TAG (tag), + tag->rule ? tag->rule->context : tag->ctx_node->ctx, + tag->rule, scheme); + } +} + +static void +ctx_node_set_scheme (CtxNode *node, + MooTextStyleScheme *scheme) +{ + g_hash_table_foreach (node->match_tags, (GHFunc) tag_set_scheme, scheme); + tag_set_scheme (NULL, MOO_SYNTAX_TAG (node->context_tag), scheme); +} + +void +moo_highlighter_apply_scheme (MooHighlighter *hl, + MooTextStyleScheme *scheme) +{ + g_return_if_fail (hl != NULL && scheme != NULL); + g_slist_foreach (hl->nodes, (GFunc) ctx_node_set_scheme, scheme); +} diff --git a/moo/mooedit/moohighlighter.h b/moo/mooedit/moohighlighter.h index 58921068..69a15c5b 100644 --- a/moo/mooedit/moohighlighter.h +++ b/moo/mooedit/moohighlighter.h @@ -87,6 +87,8 @@ void moo_highlighter_apply_tags (MooHighlighter *highlight, int first_line, int last_line); +void moo_highlighter_apply_scheme (MooHighlighter *highlight, + MooTextStyleScheme *scheme); G_END_DECLS diff --git a/moo/mooedit/moolang-parser.c b/moo/mooedit/moolang-parser.c index 32d71201..5b8652fb 100644 --- a/moo/mooedit/moolang-parser.c +++ b/moo/mooedit/moolang-parser.c @@ -15,6 +15,7 @@ #define MOOEDIT_COMPILATION #include "mooedit/moolang-parser.h" #include "mooedit/moolang-strings.h" +#include "mooedit/moolangmgr.h" #include #include #include @@ -162,6 +163,7 @@ inline static void STRING_FREE (xmlChar *s) #define IS_DEFAULT_STYLE_NODE(node_) (IS_ELEMENT_NODE(node_) && NODE_NAME_IS_(node_, DEFAULT_STYLE_ELM)) #define IS_BRACKET_MATCH_NODE(node_) (IS_ELEMENT_NODE(node_) && NODE_NAME_IS_(node_, BRACKET_MATCH_ELM)) #define IS_BRACKET_MISMATCH_NODE(node_) (IS_ELEMENT_NODE(node_) && NODE_NAME_IS_(node_, BRACKET_MISMATCH_ELM)) +#define IS_SAMPLE_CODE_NODE(node_) (IS_ELEMENT_NODE(node_) && NODE_NAME_IS_(node_, SAMPLE_CODE_ELM)) #if VERBOSE @@ -449,6 +451,21 @@ lang_xml_parse (xmlNode *node) if (!xml->general) goto error; } + else if (IS_SAMPLE_CODE_NODE (child)) + { + xmlChar *content; + + if (xml->sample) + { + g_warning ("%s: duplicated '" SAMPLE_CODE_ELM "' element", G_STRLOC); + goto error; + } + + content = xmlNodeGetContent (child); + xml->sample = STRDUP (content); + + STRING_FREE (content); + } else { g_warning ("%s: unknown tag '%s'", G_STRLOC, child->name); @@ -499,6 +516,7 @@ moo_lang_xml_free (LangXML *xml) g_free (xml->mimetypes); g_free (xml->extensions); g_free (xml->author); + g_free (xml->sample); general_xml_free (xml->general); syntax_xml_free (xml->syntax); style_list_xml_free (xml->style_list); @@ -1480,9 +1498,9 @@ moo_rule_new_from_xml (RuleXML *xml, break; case MOO_CONTEXT_SWITCH: if (xml->end_switch_info.ref.lang) - switch_to = moo_lang_table_get_context (lang->table, - xml->end_switch_info.ref.lang, - xml->end_switch_info.ref.name); + switch_to = moo_lang_mgr_get_context (lang->mgr, + xml->end_switch_info.ref.lang, + xml->end_switch_info.ref.name); else switch_to = moo_lang_get_context (lang, xml->end_switch_info.ref.name); @@ -1884,7 +1902,7 @@ rule_include_xml_create_rule (RuleIncludeXML *xml, MooContext *ctx; if (xml->from_lang) - ctx = moo_lang_table_get_context (lang->table, xml->from_lang, xml->from_context); + ctx = moo_lang_mgr_get_context (lang->mgr, xml->from_lang, xml->from_context); else ctx = moo_lang_get_context (lang, xml->from_context); @@ -2059,10 +2077,11 @@ error: static MooTextStyleScheme* -style_scheme_xml_parse (xmlNode *node) +style_scheme_xml_parse (xmlNode *node, + char **base_scheme) { MooTextStyleScheme *scheme; - xmlChar *name = NULL, *foreground = NULL, *background = NULL; + xmlChar *name = NULL, *foreground = NULL, *background = NULL, *base = NULL; xmlChar *selected_foreground = NULL, *selected_background = NULL, *current_line = NULL; g_return_val_if_fail (IS_SCHEME_NODE (node), NULL); @@ -2073,6 +2092,7 @@ style_scheme_xml_parse (xmlNode *node) selected_foreground = GET_PROP (node, SCHEME_SEL_FOREGROUND_PROP); selected_background = GET_PROP (node, SCHEME_SEL_BACKGROUND_PROP); current_line = GET_PROP (node, SCHEME_CURRENT_LINE_PROP); + base = GET_PROP (node, SCHEME_BASE_SCHEME_PROP); if (!name || !name[0]) { @@ -2080,13 +2100,13 @@ style_scheme_xml_parse (xmlNode *node) goto error; } - scheme = moo_text_style_scheme_new_empty (name); + scheme = moo_text_style_scheme_new_empty (name, NULL); - scheme->foreground = STRDUP (foreground); - scheme->background = STRDUP (background); - scheme->selected_foreground = STRDUP (selected_foreground); - scheme->selected_background = STRDUP (selected_background); - scheme->current_line = STRDUP (current_line); + scheme->text_colors[MOO_TEXT_COLOR_FG] = STRDUP (foreground); + scheme->text_colors[MOO_TEXT_COLOR_BG] = STRDUP (background); + scheme->text_colors[MOO_TEXT_COLOR_SEL_FG] = STRDUP (selected_foreground); + scheme->text_colors[MOO_TEXT_COLOR_SEL_BG] = STRDUP (selected_background); + scheme->text_colors[MOO_TEXT_COLOR_CUR_LINE] = STRDUP (current_line); ELM_FOREACH (node, child) { @@ -2153,12 +2173,16 @@ style_scheme_xml_parse (xmlNode *node) } ELM_FOREACH_END; + if (base_scheme) + *base_scheme = STRDUP (base); + STRING_FREE (name); STRING_FREE (foreground); STRING_FREE (background); STRING_FREE (selected_foreground); STRING_FREE (selected_background); STRING_FREE (current_line); + STRING_FREE (base); return scheme; error: @@ -2168,13 +2192,15 @@ error: STRING_FREE (selected_foreground); STRING_FREE (selected_background); STRING_FREE (current_line); - moo_text_style_scheme_unref (scheme); + STRING_FREE (base); + g_object_unref (scheme); return NULL; } MooTextStyleScheme* -moo_text_style_scheme_parse_file (const char *file) +moo_text_style_scheme_parse_file (const char *file, + char **base_scheme) { xmlDoc *doc; xmlNode *root; @@ -2187,7 +2213,7 @@ moo_text_style_scheme_parse_file (const char *file) g_return_val_if_fail (doc != NULL, NULL); root = xmlDocGetRootElement (doc); - scheme = style_scheme_xml_parse (root); + scheme = style_scheme_xml_parse (root, base_scheme); xmlFreeDoc (doc); xmlCleanupParser (); @@ -2198,7 +2224,8 @@ moo_text_style_scheme_parse_file (const char *file) MooTextStyleScheme* moo_text_style_scheme_parse_memory (const char *buffer, - int size) + int size, + char **base_scheme) { xmlDoc *doc; xmlNode *root; @@ -2214,7 +2241,7 @@ moo_text_style_scheme_parse_memory (const char *buffer, g_return_val_if_fail (doc != NULL, NULL); root = xmlDocGetRootElement (doc); - scheme = style_scheme_xml_parse (root); + scheme = style_scheme_xml_parse (root, base_scheme); xmlFreeDoc (doc); xmlCleanupParser (); diff --git a/moo/mooedit/moolang-parser.h b/moo/mooedit/moolang-parser.h index fed3b410..eb975281 100644 --- a/moo/mooedit/moolang-parser.h +++ b/moo/mooedit/moolang-parser.h @@ -61,6 +61,7 @@ struct _LangXML { char *mimetypes; char *extensions; char *author; + char *sample; guint hidden : 1; GeneralXML *general; SyntaxXML *syntax; @@ -185,9 +186,11 @@ LangXML *moo_lang_parse_memory (const char *buffer, int size); void moo_lang_xml_free (LangXML *xml); -MooTextStyleScheme *moo_text_style_scheme_parse_file (const char *file); +MooTextStyleScheme *moo_text_style_scheme_parse_file (const char *file, + char **base_scheme); MooTextStyleScheme *moo_text_style_scheme_parse_memory (const char *buffer, - int size); + int size, + char **base_scheme); MooRule *moo_rule_new_from_xml (RuleXML *xml, LangXML *lang_xml, diff --git a/moo/mooedit/moolang-strings.h b/moo/mooedit/moolang-strings.h index 062097b5..ac0cc738 100644 --- a/moo/mooedit/moolang-strings.h +++ b/moo/mooedit/moolang-strings.h @@ -41,7 +41,7 @@ #define DEFAULT_STYLE_ELM "default-style" #define SCHEME_NAME_PROP "name" #define DEFAULT_SCHEME_PROP "default-scheme" -#define SCHEME_USE_SCHEME_PROP "use-scheme" +#define SCHEME_BASE_SCHEME_PROP "base" #define SCHEME_FOREGROUND_PROP "foreground" #define SCHEME_BACKGROUND_PROP "background" #define SCHEME_SEL_FOREGROUND_PROP "selected-foreground" @@ -62,6 +62,7 @@ #define COMMENTS_ELM "comments" #define SINGLE_LINE_ELM "single-line" #define MULTI_LINE_ELM "multi-line" +#define SAMPLE_CODE_ELM "sample-code" #define LANG_NAME_PROP "name" #define LANG_VERSION_PROP "version" diff --git a/moo/mooedit/moolang.c b/moo/mooedit/moolang.c index 170b0e65..54f5ea57 100644 --- a/moo/mooedit/moolang.c +++ b/moo/mooedit/moolang.c @@ -17,7 +17,7 @@ #endif #define MOOEDIT_COMPILATION -#include "mooedit/moolang.h" +#include "mooedit/moolangmgr.h" #include "mooedit/moolang-rules.h" #include "mooedit/moolang-parser.h" #include "mooedit/moolang-strings.h" @@ -124,8 +124,99 @@ moo_context_set_line_end_switch (MooContext *ctx, /* MooLang */ +static void lang_connect_scheme (MooLang *lang, + MooTextStyleScheme *scheme); +static void lang_disconnect_scheme (MooLang *lang, + MooTextStyleScheme *scheme); + +static void +style_cache_create (MooLang *lang) +{ + g_return_if_fail (lang->style_cache == NULL); + lang->style_cache = g_hash_table_new_full (g_direct_hash, g_direct_equal, + NULL, (GDestroyNotify) g_hash_table_destroy); +} + +static void +scheme_destroyed (MooLang *lang, + MooTextStyleScheme *scheme) +{ + g_hash_table_remove (lang->style_cache, scheme); +} + +static void +scheme_changed (MooTextStyleScheme *scheme, + MooLang *lang) +{ + g_hash_table_remove (lang->style_cache, scheme); + lang_disconnect_scheme (lang, scheme); +} + +static void +disconnect_scheme (MooTextStyleScheme *scheme, + G_GNUC_UNUSED GHashTable *scheme_cache, + MooLang *lang) +{ + lang_disconnect_scheme (lang, scheme); +} + +static void +style_cache_destroy (MooLang *lang) +{ + g_hash_table_foreach (lang->style_cache, (GHFunc) disconnect_scheme, lang); + g_hash_table_destroy (lang->style_cache); + lang->style_cache = NULL; +} + +static MooTextStyle* +style_cache_lookup (MooLang *lang, + const char *style_name, + MooTextStyleScheme *scheme) +{ + GHashTable *scheme_cache = g_hash_table_lookup (lang->style_cache, scheme); + return scheme_cache ? g_hash_table_lookup (scheme_cache, style_name) : NULL; +} + +static void +style_cache_insert (MooLang *lang, + const char *style_name, + MooTextStyleScheme *scheme, + MooTextStyle *style) +{ + GHashTable *scheme_cache = g_hash_table_lookup (lang->style_cache, scheme); + + if (!scheme_cache) + { + lang_connect_scheme (lang, scheme); + scheme_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, + (GDestroyNotify) moo_text_style_free); + g_hash_table_insert (lang->style_cache, scheme, scheme_cache); + } + + g_hash_table_insert (scheme_cache, g_strdup (style_name), style); +} + +static void +lang_disconnect_scheme (MooLang *lang, + MooTextStyleScheme *scheme) +{ + g_signal_handlers_disconnect_by_func (scheme, + (gpointer) scheme_changed, + lang); + g_object_weak_unref (G_OBJECT (scheme), (GWeakNotify) scheme_destroyed, lang); +} + +static void +lang_connect_scheme (MooLang *lang, + MooTextStyleScheme *scheme) +{ + g_signal_connect (scheme, "changed", G_CALLBACK (scheme_changed), lang); + g_object_weak_ref (G_OBJECT (scheme), (GWeakNotify) scheme_destroyed, lang); +} + + MooLang* -moo_lang_new (MooLangTable *table, +moo_lang_new (MooLangMgr *mgr, const char *name, const char *section, const char *version, @@ -133,28 +224,26 @@ moo_lang_new (MooLangTable *table, { MooLang *lang; - g_return_val_if_fail (table != NULL && name != NULL && name[0] != 0, NULL); - g_return_val_if_fail (!g_hash_table_lookup (table->lang_names, name), NULL); + g_return_val_if_fail (MOO_IS_LANG_MGR (mgr) && name != NULL && name[0] != 0, NULL); + g_return_val_if_fail (!g_hash_table_lookup (mgr->lang_names, name), NULL); lang = g_new0 (MooLang, 1); - lang->table = table; + lang->mgr = mgr; lang->context_names = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); lang->contexts = (MooContextArray*) g_ptr_array_new (); lang->style_names = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); lang->styles = (MooTextStyleArray*) g_ptr_array_new (); - lang->style_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, - (GDestroyNotify) moo_text_style_free); + style_cache_create (lang); lang->name = g_strdup (name); lang->section = section ? g_strdup (section) : g_strdup ("Others"); lang->version = version ? g_strdup (version) : g_strdup (""); lang->author = author ? g_strdup (author) : g_strdup (""); - table->langs = g_slist_append (table->langs, lang); - g_hash_table_insert (table->lang_names, g_strdup (name), lang); + _moo_lang_mgr_add_lang (mgr, lang); return lang; } @@ -184,8 +273,8 @@ moo_lang_add_style (MooLang *lang, MooLang* moo_lang_ref (MooLang *lang) { - g_return_val_if_fail (lang != NULL && lang->table != NULL, NULL); - g_object_ref (lang->table); + g_return_val_if_fail (lang != NULL && lang->mgr != NULL, NULL); + g_object_ref (lang->mgr); return lang; } @@ -193,8 +282,8 @@ moo_lang_ref (MooLang *lang) void moo_lang_unref (MooLang *lang) { - g_return_if_fail (lang != NULL && lang->table != NULL); - g_object_unref (lang->table); + g_return_if_fail (lang != NULL && lang->mgr != NULL); + g_object_unref (lang->mgr); } @@ -236,8 +325,8 @@ moo_lang_get_default_context (MooLang *lang) } -static void -moo_lang_free (MooLang *lang) +void +_moo_lang_free (MooLang *lang) { if (lang) { @@ -250,7 +339,7 @@ moo_lang_free (MooLang *lang) g_ptr_array_free ((GPtrArray*) lang->contexts, TRUE); g_hash_table_destroy (lang->style_names); - g_hash_table_destroy (lang->style_cache); + style_cache_destroy (lang); for (i = 0; i < lang->styles->len; ++i) moo_text_style_free (lang->styles->data[i]); @@ -260,6 +349,7 @@ moo_lang_free (MooLang *lang) g_free (lang->section); g_free (lang->version); g_free (lang->author); + g_free (lang->sample); g_free (lang->brackets); @@ -273,48 +363,6 @@ moo_lang_free (MooLang *lang) } -static void -moo_lang_parse_mime_types (MooLang *lang, - const char *mimetypes) -{ - char **pieces, **p; - - g_return_if_fail (lang != NULL && mimetypes != NULL); - - pieces = g_strsplit (mimetypes, EXTENSION_SEPARATOR, 0); - - if (!pieces) - return; - - for (p = pieces; *p; p++) - if (**p) - lang->mime_types = g_slist_prepend (lang->mime_types, g_strdup (*p)); - - g_strfreev (pieces); -} - - -static void -moo_lang_parse_extensions (MooLang *lang, - const char *extensions) -{ - char **pieces, **p; - - g_return_if_fail (lang != NULL && extensions != NULL); - - pieces = g_strsplit (extensions, EXTENSION_SEPARATOR, 0); - - if (!pieces) - return; - - for (p = pieces; *p; p++) - if (**p) - lang->extensions = g_slist_prepend (lang->extensions, g_strdup (*p)); - - g_strfreev (pieces); -} - - GType moo_lang_get_type (void) { @@ -333,27 +381,32 @@ moo_lang_get_type (void) static void set_tag_style (MooLang *lang, GtkTextTag *tag, - const char *style_name) + const char *style_name, + MooTextStyleScheme *scheme) { - MooTextStyle *style; + MooTextStyle *style = NULL; g_return_if_fail (lang != NULL && tag != NULL); if (!style_name) return; - style = g_hash_table_lookup (lang->style_cache, style_name); + if (!scheme) + scheme = moo_lang_mgr_get_active_scheme (lang->mgr); + g_return_if_fail (MOO_IS_TEXT_STYLE_SCHEME (scheme)); + + style = style_cache_lookup (lang, style_name, scheme); if (!style) { - style = moo_lang_table_get_style (lang->table, lang->name, style_name); + style = moo_lang_mgr_get_style (lang->mgr, lang->name, style_name, scheme); g_return_if_fail (style != NULL); if (style->default_style) { MooTextStyle *def_style; - def_style = moo_lang_table_get_style (lang->table, NULL, style->default_style); + def_style = moo_lang_mgr_get_style (lang->mgr, NULL, style->default_style, scheme); if (!def_style) { @@ -368,7 +421,7 @@ set_tag_style (MooLang *lang, } } - g_hash_table_insert (lang->style_cache, g_strdup (style_name), style); + style_cache_insert (lang, style_name, scheme, style); } if (style->mask & MOO_TEXT_STYLE_FOREGROUND) @@ -390,99 +443,17 @@ void _moo_lang_set_tag_style (MooLang *lang, GtkTextTag *tag, MooContext *ctx, - MooRule *rule) + MooRule *rule, + MooTextStyleScheme *scheme) { g_return_if_fail (lang != NULL && GTK_IS_TEXT_TAG (tag)); g_return_if_fail (ctx != NULL && ctx->lang == lang); g_return_if_fail (!rule || rule->context == ctx); - set_tag_style (lang, tag, ctx->style); + set_tag_style (lang, tag, ctx->style, scheme); if (rule) - set_tag_style (lang, tag, rule->style); -} - - -static MooTextStyle* -moo_lang_get_style (MooLang *lang, - const char *style_name) -{ - MooTextStyle *style; - g_return_val_if_fail (lang != NULL && style_name != NULL, NULL); - style = g_hash_table_lookup (lang->style_names, style_name); - return moo_text_style_copy (style); -} - - -static gboolean -parse_bool (const char *string, - gboolean *val) -{ - g_return_val_if_fail (string != NULL && val != NULL, FALSE); - if (!g_ascii_strcasecmp (string, "true") || - !g_ascii_strcasecmp (string, "yes") || - !strcmp (string, "1")) - { - *val = TRUE; - return TRUE; - } - else if (!g_ascii_strcasecmp (string, "false") || - !g_ascii_strcasecmp (string, "no") || - !strcmp (string, "0")) - { - *val = FALSE; - return TRUE; - } - else - { - g_warning ("%s: could not get boolean value from '%s'", - G_STRLOC, string); - return FALSE; - } -} - - -static gboolean -parse_color (const char *string, - GdkColor *val) -{ - g_return_val_if_fail (string != NULL && val != NULL, FALSE); - - if (gdk_color_parse (string, val)) - return TRUE; - - g_warning ("%s: could not get color value from '%s'", - G_STRLOC, string); - return FALSE; -} - - -static MooTextStyle* -style_new_from_xml (StyleXML *xml) -{ - GdkColor foreground, background; - gboolean bold, italic, underline, strikethrough; - MooTextStyleMask mask = 0; - - g_return_val_if_fail (xml != NULL, NULL); - - if (xml->bold && parse_bool (xml->bold, &bold)) - mask |= MOO_TEXT_STYLE_BOLD; - if (xml->italic && parse_bool (xml->italic, &italic)) - mask |= MOO_TEXT_STYLE_ITALIC; - if (xml->underline && parse_bool (xml->underline, &underline)) - mask |= MOO_TEXT_STYLE_UNDERLINE; - if (xml->strikethrough && parse_bool (xml->strikethrough, &strikethrough)) - mask |= MOO_TEXT_STYLE_STRIKETHROUGH; - if (xml->foreground && parse_color (xml->foreground, &foreground)) - mask |= MOO_TEXT_STYLE_FOREGROUND; - if (xml->background && parse_color (xml->background, &background)) - mask |= MOO_TEXT_STYLE_BACKGROUND; - - return moo_text_style_new (xml->default_style, - &foreground, &background, - bold, italic, underline, - strikethrough, mask, FALSE); + set_tag_style (lang, tag, rule->style, scheme); } @@ -525,839 +496,17 @@ _moo_style_set_tag_style (const MooTextStyle *style, } -/*****************************************************************************/ -/* MooLangTable - */ - -static void moo_lang_table_finalize (GObject *object); - - -/* MOO_TYPE_LANG_TABLE */ -G_DEFINE_TYPE (MooLangTable, moo_lang_table, G_TYPE_OBJECT) - -enum { - LANG_ADDED, - LANG_REMOVED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL]; - -static void -moo_lang_table_class_init (MooLangTableClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->finalize = moo_lang_table_finalize; - - signals[LANG_ADDED] = - g_signal_new ("lang-added", - G_OBJECT_CLASS_TYPE (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (MooLangTableClass, lang_added), - NULL, NULL, - _moo_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE); - - signals[LANG_REMOVED] = - g_signal_new ("lang-removed", - G_OBJECT_CLASS_TYPE (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (MooLangTableClass, lang_removed), - NULL, NULL, - _moo_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE); -} - - -static void -moo_lang_table_init (MooLangTable *table) -{ - table->lang_names = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - table->schemes = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, - (GDestroyNotify) moo_text_style_scheme_unref); - table->active_scheme = moo_text_style_scheme_new_default (); - g_hash_table_insert (table->schemes, g_strdup (table->active_scheme->name), - table->active_scheme); - table->langs = NULL; - table->dirs_read = FALSE; -} - - -MooLangTable* -moo_lang_table_new (void) -{ - return g_object_new (MOO_TYPE_LANG_TABLE, NULL); -} - - -static void -moo_lang_table_finalize (GObject *object) -{ - MooLangTable *table = MOO_LANG_TABLE (object); - - g_slist_foreach (table->lang_dirs, (GFunc) g_free, NULL); - g_slist_free (table->lang_dirs); - - g_slist_foreach (table->langs, (GFunc) moo_lang_free, NULL); - g_slist_free (table->langs); - - g_hash_table_destroy (table->lang_names); - g_hash_table_destroy (table->schemes); - table->active_scheme = NULL; - - G_OBJECT_CLASS(moo_lang_table_parent_class)->finalize (object); -} - - void -moo_lang_table_add_dir (MooLangTable *table, - const char *dir) +_moo_lang_erase_tag_style (GtkTextTag *tag) { - g_return_if_fail (MOO_IS_LANG_TABLE (table)); - g_return_if_fail (dir != NULL); - g_return_if_fail (!table->dirs_read); - table->lang_dirs = g_slist_append (table->lang_dirs, g_strdup (dir)); -} - - -static MooTextStyle* -style_new_from_markup (MooMarkupNode *node, - gboolean modified) -{ - GdkColor foreground, background; - gboolean bold, italic, underline, strikethrough; - const char *fg_prop, *bg_prop, *bold_prop, *italic_prop; - const char *underline_prop, *strikethrough_prop; - MooTextStyleMask mask = 0; - - g_return_val_if_fail (node != NULL, NULL); - - fg_prop = moo_markup_get_prop (node, STYLE_FOREGROUND_PROP); - bg_prop = moo_markup_get_prop (node, STYLE_BACKGROUND_PROP); - bold_prop = moo_markup_get_prop (node, STYLE_BOLD_PROP); - italic_prop = moo_markup_get_prop (node, STYLE_ITALIC_PROP); - underline_prop = moo_markup_get_prop (node, STYLE_UNDERLINE_PROP); - strikethrough_prop = moo_markup_get_prop (node, STYLE_STRIKETHROUGH_PROP); - - if (bold_prop && parse_bool (bold_prop, &bold)) - mask |= MOO_TEXT_STYLE_BOLD; - if (italic_prop && parse_bool (italic_prop, &italic)) - mask |= MOO_TEXT_STYLE_ITALIC; - if (underline_prop && parse_bool (underline_prop, &underline)) - mask |= MOO_TEXT_STYLE_UNDERLINE; - if (strikethrough_prop && parse_bool (strikethrough_prop, &strikethrough)) - mask |= MOO_TEXT_STYLE_STRIKETHROUGH; - if (fg_prop && parse_color (fg_prop, &foreground)) - mask |= MOO_TEXT_STYLE_FOREGROUND; - if (bg_prop && parse_color (bg_prop, &background)) - mask |= MOO_TEXT_STYLE_BACKGROUND; - - return moo_text_style_new (NULL, - &foreground, &background, - bold, italic, underline, - strikethrough, mask, modified); -} - - -static void -load_language_node (MooTextStyleScheme *scheme, - MooMarkupNode *node) -{ - MooMarkupNode *child; - const char *lang_name; - - g_return_if_fail (node != NULL && node->name != NULL && !strcmp (node->name, LANGUAGE_ELM)); - g_return_if_fail (scheme != NULL); - - lang_name = moo_markup_get_prop (node, LANG_NAME_PROP); - g_return_if_fail (lang_name && lang_name[0]); - - for (child = node->children; child != NULL; child = child->next) - { - MooTextStyle *style; - const char *style_name; - - if (!MOO_MARKUP_IS_ELEMENT (child)) - continue; - - if (strcmp (child->name, STYLE_ELM)) - { - g_warning ("%s: invalid element '%s'", G_STRLOC, child->name); - continue; - } - - style_name = moo_markup_get_prop (child, STYLE_NAME_PROP); - - if (!style_name || !style_name[0]) - { - g_warning ("%s: style name absent", G_STRLOC); - continue; - } - - style = style_new_from_markup (child, TRUE); - - if (!style) - { - g_critical ("%s: could not parse style node", G_STRLOC); - continue; - } - - moo_text_style_scheme_compose (scheme, lang_name, style_name, style); - moo_text_style_free (style); - } -} - - -static void -moo_lang_table_choose_scheme (MooLangTable *table, - MooMarkupNode *node) -{ - const char *name = moo_markup_get_prop (node, DEFAULT_SCHEME_PROP); - MooTextStyleScheme *scheme; - - if (!name) - name = SCHEME_DEFAULT; - - scheme = g_hash_table_lookup (table->schemes, name); - - if (!scheme) - scheme = g_hash_table_lookup (table->schemes, SCHEME_DEFAULT); - - g_return_if_fail (scheme != NULL); - table->active_scheme = scheme; -} - - -static void -moo_lang_table_load_styles (MooLangTable *table) -{ - MooMarkupDoc *xml; - MooMarkupNode *root, *child; - - xml = moo_prefs_get_markup (); - g_return_if_fail (xml != NULL); - - root = moo_markup_get_element (MOO_MARKUP_NODE (xml), - MOO_STYLES_PREFS_PREFIX); - - if (!root) - return; - - moo_lang_table_choose_scheme (table, root); - - for (child = root->children; child != NULL; child = child->next) - { - MooMarkupNode *grand_child; - MooTextStyleScheme *scheme; - const char *scheme_name; - - if (!MOO_MARKUP_IS_ELEMENT (child)) - continue; - - if (strcmp (child->name, SCHEME_ELM)) - { - g_warning ("%s: invalid element '%s'", G_STRLOC, child->name); - continue; - } - - scheme_name = moo_markup_get_prop (child, SCHEME_NAME_PROP); - - if (!scheme_name || !scheme_name[0]) - { - g_warning ("%s: scheme name missing", G_STRLOC); - continue; - } - - scheme = g_hash_table_lookup (table->schemes, scheme_name); - - if (!scheme) - continue; - - for (grand_child = child->children; grand_child != NULL; grand_child = grand_child->next) - { - if (!MOO_MARKUP_IS_ELEMENT (grand_child)) - continue; - - if (!strcmp (grand_child->name, LANGUAGE_ELM)) - { - load_language_node (scheme, grand_child); - } - else if (!strcmp (grand_child->name, DEFAULT_STYLE_ELM)) - { - const char *name; - MooTextStyle *style; - - name = moo_markup_get_prop (grand_child, STYLE_NAME_PROP); - - if (!name || !name[0]) - { - g_warning ("%s: style name absent", G_STRLOC); - continue; - } - - style = style_new_from_markup (grand_child, TRUE); - - if (!style) - { - g_critical ("%s: could not parse style node", G_STRLOC); - continue; - } - - moo_text_style_scheme_compose (scheme, NULL, name, style); - moo_text_style_free (style); - } - else - { - g_warning ("%s: invalid element '%s'", G_STRLOC, grand_child->name); - } - } - } -} - - -static GSList* -read_files (MooLangTable *table, - GHashTable *lang_xml_names) -{ - GSList *l; - GSList *lang_xml_list = NULL; - - g_return_val_if_fail (table != NULL, NULL); - g_return_val_if_fail (lang_xml_names != NULL, NULL); - - if (!table->lang_dirs) - return NULL; - - for (l = table->lang_dirs; l != NULL; l = l->next) - { - const char *dirname = l->data, *entry; - GDir *dir; - - dir = g_dir_open (dirname, 0, NULL); - - if (!dir) - continue; - - while ((entry = g_dir_read_name (dir))) - { - guint entry_len = strlen (entry); - - if (entry_len > LANG_FILE_SUFFIX_LEN && - !strcmp (entry + (entry_len - LANG_FILE_SUFFIX_LEN), LANG_FILE_SUFFIX)) - { - char *filename; - LangXML *lang, *old_lang; - - filename = g_build_filename (dirname, entry, NULL); - lang = moo_lang_parse_file (filename); - g_free (filename); - - if (!lang) - continue; - - old_lang = g_hash_table_lookup (lang_xml_names, lang->name); - - if (old_lang) - { - g_message ("%s: loading another instance of lang '%s'", - G_STRLOC, lang->name); - lang_xml_list = g_slist_remove (lang_xml_list, old_lang); - moo_lang_xml_free (old_lang); - } - - lang_xml_list = g_slist_append (lang_xml_list, lang); - g_hash_table_insert (lang_xml_names, g_strdup (lang->name), lang); - } - else if (entry_len > STYLES_FILE_SUFFIX_LEN && - !strcmp (entry + (entry_len - STYLES_FILE_SUFFIX_LEN), STYLES_FILE_SUFFIX)) - { - char *filename; - MooTextStyleScheme *scheme; - - filename = g_build_filename (dirname, entry, NULL); - scheme = moo_text_style_scheme_parse_file (filename); - g_free (filename); - - if (!scheme) - continue; - - if (g_hash_table_lookup (table->schemes, scheme->name)) - { - g_message ("%s: loading another instance of scheme '%s'", - G_STRLOC, scheme->name); - if (!strcmp (table->active_scheme->name, scheme->name)) - table->active_scheme = scheme; - } - - g_hash_table_insert (table->schemes, g_strdup (scheme->name), scheme); - } - } - - g_dir_close (dir); - } - - return lang_xml_list; -} - - -static GSList* -check_external_refs (GSList *lang_xml_list, - GHashTable *lang_xml_names) -{ - gboolean again = TRUE; - - while (again) - { - GSList *l; - - again = FALSE; - - for (l = lang_xml_list; l != NULL; l = l->next) - { - GSList *ref_link; - LangXML *xml = l->data; - gboolean valid = TRUE; - - for (ref_link = xml->external_refs; ref_link != NULL; ref_link = ref_link->next) - { - CrossRef *ref = ref_link->data; - LangXML *ref_lang; - - g_assert (ref->lang != NULL); - - ref_lang = g_hash_table_lookup (lang_xml_names, ref->lang); - - if (!ref_lang) - { - g_warning ("%s: invalid reference to lang '%s' in lang '%s'", - G_STRLOC, ref->lang, xml->name); - g_hash_table_remove (lang_xml_names, xml->name); - lang_xml_list = g_slist_remove (lang_xml_list, xml); - moo_lang_xml_free (xml); - valid = FALSE; - break; - } - - if (!g_hash_table_lookup (ref_lang->context_names, ref->name)) - { - g_warning ("%s: lang '%s' does not contain context '%s', referenced from lang '%s'", - G_STRLOC, ref->lang, ref->name, xml->name); - g_hash_table_remove (lang_xml_names, xml->name); - lang_xml_list = g_slist_remove (lang_xml_list, xml); - moo_lang_xml_free (xml); - valid = FALSE; - break; - } - } - - if (!valid) - { - again = TRUE; - break; - } - } - } - - return lang_xml_list; -} - - -static void -moo_lang_build_contexts (MooLang *lang, - LangXML *xml) -{ - GSList *l; - - g_assert (!strcmp (lang->name, xml->name)); - - for (l = xml->syntax->contexts; l != NULL; l = l->next) - { - ContextXML *ctx_xml = l->data; - MooContext *ctx = moo_lang_add_context (lang, ctx_xml->name, ctx_xml->style); - g_assert (ctx != NULL); - } -} - - -static void -moo_lang_finish_build (MooLang *lang, - LangXML *xml) -{ - GSList *l; - - g_assert (!strcmp (lang->name, xml->name)); - - if (xml->style_list) - { - for (l = xml->style_list->styles; l != NULL; l = l->next) - { - StyleXML *style_xml = l->data; - MooTextStyle *style = style_new_from_xml (style_xml); - moo_lang_add_style (lang, style_xml->name, style); - moo_text_style_free (style); - } - } - - if (xml->mimetypes) - moo_lang_parse_mime_types (lang, xml->mimetypes); - - if (xml->extensions) - moo_lang_parse_extensions (lang, xml->extensions); - - if (xml->general) - lang->brackets = g_strdup (xml->general->brackets); - - for (l = xml->syntax->contexts; l != NULL; l = l->next) - { - GSList *rule_link; - ContextXML *ctx_xml; - MooContext *ctx, *switch_to; - - ctx_xml = l->data; - ctx = moo_lang_get_context (lang, ctx_xml->name); - g_assert (ctx != NULL); - - for (rule_link = ctx_xml->rules; rule_link != NULL; rule_link = rule_link->next) - { - RuleXML *rule_xml = rule_link->data; - MooRule *rule = moo_rule_new_from_xml (rule_xml, xml, lang); - if (rule) - moo_context_add_rule (ctx, rule); - } - - switch (ctx_xml->eol_switch_info.type) - { - case MOO_CONTEXT_STAY: - moo_context_set_line_end_stay (ctx); - break; - case MOO_CONTEXT_POP: - moo_context_set_line_end_pop (ctx, ctx_xml->eol_switch_info.num); - break; - case MOO_CONTEXT_SWITCH: - if (ctx_xml->eol_switch_info.ref.lang) - switch_to = moo_lang_table_get_context (lang->table, - ctx_xml->eol_switch_info.ref.lang, - ctx_xml->eol_switch_info.ref.name); - else - switch_to = moo_lang_get_context (lang, ctx_xml->eol_switch_info.ref.name); - - if (!switch_to) - g_critical ("%s: oops", G_STRLOC); - else - moo_context_set_line_end_switch (ctx, switch_to); - - break; - } - } -} - - -void -moo_lang_table_read_dirs (MooLangTable *table) -{ - GHashTable *lang_xml_names; - GSList *lang_xml_list, *l; - - g_return_if_fail (MOO_IS_LANG_TABLE (table)); - g_return_if_fail (!table->dirs_read); - - if (!table->lang_dirs) - return; - - lang_xml_names = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - - lang_xml_list = read_files (table, lang_xml_names); - - if (!lang_xml_list) - goto out; - - lang_xml_list = check_external_refs (lang_xml_list, lang_xml_names); - - if (!lang_xml_list) - goto out; - - table->dirs_read = TRUE; - - for (l = lang_xml_list; l != NULL; l = l->next) - { - LangXML *xml = l->data; - MooLang *lang = moo_lang_new (table, xml->name, - xml->section, xml->version, - xml->author); - lang->hidden = xml->hidden; - moo_lang_build_contexts (lang, xml); - } - - for (l = lang_xml_list; l != NULL; l = l->next) - { - LangXML *xml = l->data; - MooLang *lang = moo_lang_table_get_lang (table, xml->name); - g_assert (lang != NULL); - moo_lang_finish_build (lang, xml); - } - -out: - g_hash_table_destroy (lang_xml_names); - g_slist_foreach (lang_xml_list, (GFunc) moo_lang_xml_free, NULL); - g_slist_free (lang_xml_list); - - moo_lang_table_load_styles (table); -} - - -MooContext* -moo_lang_table_get_context (MooLangTable *table, - const char *lang_name, - const char *ctx_name) -{ - MooLang *lang; - g_return_val_if_fail (MOO_IS_LANG_TABLE (table), NULL); - g_return_val_if_fail (lang_name && ctx_name, NULL); - lang = moo_lang_table_get_lang (table, lang_name); - g_return_val_if_fail (lang != NULL, NULL); - return moo_lang_get_context (lang, ctx_name); -} - - -MooLang* -moo_lang_table_get_lang (MooLangTable *table, - const char *name) -{ - g_return_val_if_fail (MOO_IS_LANG_TABLE (table), NULL); - g_return_val_if_fail (name != NULL, NULL); - return g_hash_table_lookup (table->lang_names, name); -} - - -GSList* -moo_lang_table_get_available_langs (MooLangTable *table) -{ - g_return_val_if_fail (MOO_IS_LANG_TABLE (table), NULL); - return g_slist_copy (table->langs); -} - - -static void -maybe_add_section (MooLang *lang, - GSList **list) -{ - if (!g_slist_find_custom (*list, lang->section, (GCompareFunc) strcmp)) - *list = g_slist_prepend (*list, g_strdup (lang->section)); -} - -GSList* -moo_lang_table_get_sections (MooLangTable *table) -{ - GSList *list = NULL; - g_return_val_if_fail (MOO_IS_LANG_TABLE (table), NULL); - g_slist_foreach (table->langs, (GFunc) maybe_add_section, &list); - return list; -} - - -MooLang* -moo_lang_table_get_lang_for_file (MooLangTable *table, - const char *filename) -{ - MooLang *lang = NULL; - char *basename, *utf8_basename; - GSList *l; - gboolean found = FALSE; - - g_return_val_if_fail (MOO_IS_LANG_TABLE (table), NULL); - g_return_val_if_fail (filename != NULL, NULL); - - /* TODO: is this right? */ - basename = g_path_get_basename (filename); - g_return_val_if_fail (basename != NULL, NULL); - utf8_basename = g_filename_display_name (basename); - g_return_val_if_fail (utf8_basename != NULL, NULL); - - for (l = table->langs; !found && l != NULL; l = l->next) - { - GSList *g; - lang = l->data; - - for (g = lang->extensions; !found && g != NULL; g = g->next) - { - if (g_pattern_match_simple ((char*) g->data, utf8_basename)) - { - found = TRUE; - break; - } - } - } - - if (!found) - lang = NULL; - -#ifdef MOO_USE_XDGMIME - /* XXX: xdgmime wants utf8-encoded filename here. is it a problem? */ - - if (!lang) - { - const char *mime_type = xdg_mime_get_mime_type_for_file (filename); - if (!xdg_mime_mime_type_equal (mime_type, XDG_MIME_TYPE_UNKNOWN)) - lang = moo_lang_table_get_lang_for_mime_type (table, mime_type); - } -#endif /* MOO_USE_XDGMIME */ - - if (!lang) - lang = moo_lang_table_get_lang_for_filename (table, filename); - - g_free (utf8_basename); - g_free (basename); - return lang; -} - - -MooLang* -moo_lang_table_get_lang_for_filename (MooLangTable *table, - const char *filename) -{ - MooLang *lang = NULL; - char *basename, *utf8_basename; - GSList *l; - gboolean found = FALSE; - - g_return_val_if_fail (MOO_IS_LANG_TABLE (table), NULL); - g_return_val_if_fail (filename != NULL, NULL); - - basename = g_path_get_basename (filename); - g_return_val_if_fail (basename != NULL, NULL); - utf8_basename = g_filename_display_name (basename); - g_return_val_if_fail (utf8_basename != NULL, NULL); - - for (l = table->langs; l != NULL && !found; l = l->next) - { - GSList *g; - - lang = l->data; - - for (g = lang->extensions; !found && g != NULL; g = g->next) - if (g_pattern_match_simple (g->data, utf8_basename)) - found = TRUE; - } - - if (!found) - lang = NULL; - -#ifdef MOO_USE_XDGMIME - /* XXX: xdgmime wants utf8-encoded filename here. is it a problem? */ - if (!lang) - { - const char *mime_type = xdg_mime_get_mime_type_from_file_name (filename); - if (!xdg_mime_mime_type_equal (mime_type, XDG_MIME_TYPE_UNKNOWN)) - lang = moo_lang_table_get_lang_for_mime_type (table, mime_type); - } -#endif /* MOO_USE_XDGMIME */ - - /* check if it's backup file */ - if (!lang) - { - char *base = NULL; - int len = strlen (utf8_basename); - guint i; - - static const char *bak_globs[] = {"*~", "*.bak", "*.in"}; - - /* XXX this is broken - it passes utf8 filename to get_lang_for_filename */ - - for (i = 0; i < G_N_ELEMENTS (bak_globs); ++i) - { - int ext_len = strlen (bak_globs[i]) - 1; - - if (len > ext_len && g_pattern_match_simple (bak_globs[i], utf8_basename)) - { - base = g_strndup (utf8_basename, len - ext_len); - break; - } - } - - if (base) - { - lang = moo_lang_table_get_lang_for_filename (table, base); - g_free (base); - } - } - - return lang; -} - - -MooLang* -moo_lang_table_get_lang_for_mime_type (MooLangTable *table, - const char *mime_type) -{ - GSList *l; - MooLang *lang = NULL; - gboolean found = FALSE; - - g_return_val_if_fail (MOO_IS_LANG_TABLE (table), NULL); - g_return_val_if_fail (mime_type != NULL, NULL); - - for (l = table->langs; !found && l != NULL; l = l->next) - { - lang = l->data; - - if (g_slist_find_custom (lang->mime_types, mime_type, (GCompareFunc) strcmp)) - { - found = TRUE; - break; - } - } - - return found ? lang : NULL; -} - - -MooTextStyle* -moo_lang_table_get_style (MooLangTable *table, - const char *lang_name, - const char *style_name) -{ - const MooTextStyle *scheme_style = NULL; - MooTextStyle *lang_style = NULL; - - g_return_val_if_fail (MOO_IS_LANG_TABLE (table), NULL); - g_return_val_if_fail (style_name != NULL, NULL); - g_return_val_if_fail (table->active_scheme != NULL, NULL); - - if (lang_name) - { - MooLang *lang = moo_lang_table_get_lang (table, lang_name); - g_return_val_if_fail (lang != NULL, NULL); - lang_style = moo_lang_get_style (lang, style_name); - } - - scheme_style = moo_text_style_scheme_get (table->active_scheme, - lang_name, style_name); - - if (lang_style) - { - if (scheme_style) - moo_text_style_compose (lang_style, scheme_style); - return lang_style; - } - else if (scheme_style) - { - return moo_text_style_copy (scheme_style); - } - else - { - return NULL; - } -} - - -MooTextStyleScheme* -moo_lang_table_get_active_scheme (MooLangTable *table) -{ - g_return_val_if_fail (MOO_IS_LANG_TABLE (table), NULL); - g_return_val_if_fail (table->active_scheme != NULL, NULL); - return table->active_scheme; + g_return_if_fail (GTK_IS_TEXT_TAG (tag)); + + g_object_set (tag, + "background-set", FALSE, + "foreground-set", FALSE, + "weight-set", FALSE, + "style-set", FALSE, + "underline-set", FALSE, + "strikethrough-set", FALSE, + NULL); } diff --git a/moo/mooedit/moolang.h b/moo/mooedit/moolang.h index de7b0901..5c005305 100644 --- a/moo/mooedit/moolang.h +++ b/moo/mooedit/moolang.h @@ -16,7 +16,7 @@ #define __MOO_LANG_H__ #include -#include +#include G_BEGIN_DECLS @@ -25,18 +25,9 @@ G_BEGIN_DECLS #define MOO_STYLES_PREFS_PREFIX MOO_EDIT_PREFS_PREFIX "/styles" #define MOO_TYPE_LANG (moo_lang_get_type ()) -#define MOO_TYPE_LANG_TABLE (moo_lang_table_get_type ()) - -#define MOO_LANG_TABLE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MOO_TYPE_LANG_TABLE, MooLangTable)) -#define MOO_LANG_TABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOO_TYPE_LANG_TABLE, MooLangTableClass)) -#define MOO_IS_LANG_TABLE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MOO_TYPE_LANG_TABLE)) -#define MOO_IS_LANG_TABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOO_TYPE_LANG_TABLE)) -#define MOO_LANG_TABLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOO_TYPE_LANG_TABLE, MooLangTableClass)) typedef struct _MooLang MooLang; -typedef struct _MooLangTable MooLangTable; -typedef struct _MooLangTableClass MooLangTableClass; typedef struct _MooContext MooContext; typedef struct _MooContextArray MooContextArray; typedef struct _MooCtxSwitch MooCtxSwitch; @@ -44,14 +35,14 @@ typedef struct _MooRule MooRule; typedef struct _MooRuleArray MooRuleArray; struct _MooLang { - MooLangTable *table; + struct _MooLangMgr *mgr; GHashTable *context_names; /* char* -> MooContext* */ MooContextArray *contexts; GHashTable *style_names; /* char* -> MooStyle* */ MooTextStyleArray *styles; - GHashTable *style_cache; /* char* -> MooStyle* */ + GHashTable *style_cache; char *name; /* not NULL */ char *section; /* not NULL; "Others" by default */ @@ -65,33 +56,12 @@ struct _MooLang { char *multi_line_comment_start; char *multi_line_comment_end; + char *sample; + guint hidden : 1; }; -struct _MooLangTable { - GObject base; - - GSList *lang_dirs; - GSList *langs; - GHashTable *lang_names; - GHashTable *schemes; - MooTextStyleScheme *active_scheme; - guint dirs_read : 1; -}; - -struct _MooLangTableClass -{ - GObjectClass base_class; - - void (*lang_added) (MooLangTable *table, - const char *lang_name); - void (*lang_removed) (MooLangTable *table, - const char *lang_name); -}; - - - typedef enum { MOO_CONTEXT_STAY = 0, MOO_CONTEXT_POP, @@ -201,7 +171,6 @@ struct _MooRule GType moo_lang_get_type (void) G_GNUC_CONST; -GType moo_lang_table_get_type (void) G_GNUC_CONST; /*****************************************************************************/ @@ -221,7 +190,7 @@ void moo_context_set_line_end_switch (MooContext *ctx, /* MooLang */ -MooLang *moo_lang_new (MooLangTable *table, +MooLang *moo_lang_new (struct _MooLangMgr *mgr, const char *name, const char *section, const char *version, @@ -244,51 +213,22 @@ void moo_lang_add_style (MooLang *lang, const MooTextStyle *style); -/*****************************************************************************/ -/* MooLangTable - */ - -MooLangTable *moo_lang_table_new (void); - -GSList *moo_lang_table_get_available_langs (MooLangTable *table); -GSList *moo_lang_table_get_sections (MooLangTable *table); - -MooLang *moo_lang_table_get_lang_for_file (MooLangTable *table, - const char *filename); -MooLang *moo_lang_table_get_lang_for_filename (MooLangTable *table, - const char *filename); -MooLang *moo_lang_table_get_lang_for_mime_type (MooLangTable *table, - const char *mime_type); -MooLang *moo_lang_table_get_lang (MooLangTable *table, - const char *name); -MooContext *moo_lang_table_get_context (MooLangTable *table, - const char *lang_name, - const char *ctx_name); - -void moo_lang_table_add_dir (MooLangTable *table, - const char *dir); -void moo_lang_table_read_dirs (MooLangTable *table); - -MooTextStyle *moo_lang_table_get_style (MooLangTable *table, - const char *lang_name, /* default style if NULL */ - const char *style_name); -void moo_lang_table_set_style (MooLangTable *table, - const char *lang_name, /* default style if NULL */ - const char *style_name, - const MooTextStyle *style); -MooTextStyleScheme *moo_lang_table_get_active_scheme (MooLangTable *table); - - /*****************************************************************************/ /* Auxiliary private methods */ +void _moo_lang_free (MooLang *lang); + +void _moo_lang_scheme_changed (MooLang *lang); void _moo_lang_set_tag_style (MooLang *lang, GtkTextTag *tag, MooContext *ctx, - MooRule *rule); + MooRule *rule, + MooTextStyleScheme *scheme); void _moo_style_set_tag_style (const MooTextStyle *style, GtkTextTag *tag); +void _moo_lang_erase_tag_style (GtkTextTag *tag); + /* implemented in moohighlighter.c */ MooContext *_moo_text_iter_get_context (const GtkTextIter *iter); diff --git a/moo/mooedit/moolangmgr.c b/moo/mooedit/moolangmgr.c new file mode 100644 index 00000000..51a3433b --- /dev/null +++ b/moo/mooedit/moolangmgr.c @@ -0,0 +1,1027 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4; coding: utf-8 -*- + * + * moolangmgr.c + * + * Copyright (C) 2004-2005 by Yevgen Muntyan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * See COPYING file that comes with this distribution. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#define MOOEDIT_COMPILATION +#include "mooedit/moolangmgr.h" +#include "mooedit/moolang-strings.h" +#include "mooedit/moolang-parser.h" +#include "mooedit/mooeditprefs.h" +#include "mooutils/xdgmime/xdgmime.h" +#include "mooutils/mooprefs.h" +#include "mooutils/moomarshals.h" +#include + + +#define LANG_FILE_SUFFIX ".lang" +#define LANG_FILE_SUFFIX_LEN 5 +#define STYLES_FILE_SUFFIX ".styles" +#define STYLES_FILE_SUFFIX_LEN 7 +#define EXTENSION_SEPARATOR ";" + + +static void moo_lang_mgr_finalize (GObject *object); + + +/* MOO_TYPE_LANG_MGR */ +G_DEFINE_TYPE (MooLangMgr, moo_lang_mgr, G_TYPE_OBJECT) + +enum { + LANG_ADDED, + LANG_REMOVED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +static void +moo_lang_mgr_class_init (MooLangMgrClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = moo_lang_mgr_finalize; + + signals[LANG_ADDED] = + g_signal_new ("lang-added", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MooLangMgrClass, lang_added), + NULL, NULL, + _moo_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE); + + signals[LANG_REMOVED] = + g_signal_new ("lang-removed", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MooLangMgrClass, lang_removed), + NULL, NULL, + _moo_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE); +} + + +static void +moo_lang_mgr_init (MooLangMgr *mgr) +{ + mgr->lang_names = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + mgr->schemes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + mgr->active_scheme = moo_text_style_scheme_new_default (); + g_hash_table_insert (mgr->schemes, g_strdup (mgr->active_scheme->name), + mgr->active_scheme); + mgr->langs = NULL; + mgr->dirs_read = FALSE; +} + + +MooLangMgr* +moo_lang_mgr_new (void) +{ + return g_object_new (MOO_TYPE_LANG_MGR, NULL); +} + + +static void +moo_lang_mgr_finalize (GObject *object) +{ + MooLangMgr *mgr = MOO_LANG_MGR (object); + + g_slist_foreach (mgr->lang_dirs, (GFunc) g_free, NULL); + g_slist_free (mgr->lang_dirs); + + g_slist_foreach (mgr->langs, (GFunc) _moo_lang_free, NULL); + g_slist_free (mgr->langs); + + g_hash_table_destroy (mgr->lang_names); + g_hash_table_destroy (mgr->schemes); + mgr->active_scheme = NULL; + + G_OBJECT_CLASS(moo_lang_mgr_parent_class)->finalize (object); +} + + +void +moo_lang_mgr_add_dir (MooLangMgr *mgr, + const char *dir) +{ + g_return_if_fail (MOO_IS_LANG_MGR (mgr)); + g_return_if_fail (dir != NULL); + g_return_if_fail (!mgr->dirs_read); + mgr->lang_dirs = g_slist_append (mgr->lang_dirs, g_strdup (dir)); +} + + +static gboolean +parse_bool (const char *string, + gboolean *val) +{ + g_return_val_if_fail (string != NULL && val != NULL, FALSE); + if (!g_ascii_strcasecmp (string, "true") || + !g_ascii_strcasecmp (string, "yes") || + !strcmp (string, "1")) + { + *val = TRUE; + return TRUE; + } + else if (!g_ascii_strcasecmp (string, "false") || + !g_ascii_strcasecmp (string, "no") || + !strcmp (string, "0")) + { + *val = FALSE; + return TRUE; + } + else + { + g_warning ("%s: could not get boolean value from '%s'", + G_STRLOC, string); + return FALSE; + } +} + + +static gboolean +parse_color (const char *string, + GdkColor *val) +{ + g_return_val_if_fail (string != NULL && val != NULL, FALSE); + + if (gdk_color_parse (string, val)) + return TRUE; + + g_warning ("%s: could not get color value from '%s'", + G_STRLOC, string); + return FALSE; +} + + +static MooTextStyle* +style_new_from_markup (MooMarkupNode *node, + gboolean modified) +{ + GdkColor foreground, background; + gboolean bold, italic, underline, strikethrough; + const char *fg_prop, *bg_prop, *bold_prop, *italic_prop; + const char *underline_prop, *strikethrough_prop; + MooTextStyleMask mask = 0; + + g_return_val_if_fail (node != NULL, NULL); + + fg_prop = moo_markup_get_prop (node, STYLE_FOREGROUND_PROP); + bg_prop = moo_markup_get_prop (node, STYLE_BACKGROUND_PROP); + bold_prop = moo_markup_get_prop (node, STYLE_BOLD_PROP); + italic_prop = moo_markup_get_prop (node, STYLE_ITALIC_PROP); + underline_prop = moo_markup_get_prop (node, STYLE_UNDERLINE_PROP); + strikethrough_prop = moo_markup_get_prop (node, STYLE_STRIKETHROUGH_PROP); + + if (bold_prop && parse_bool (bold_prop, &bold)) + mask |= MOO_TEXT_STYLE_BOLD; + if (italic_prop && parse_bool (italic_prop, &italic)) + mask |= MOO_TEXT_STYLE_ITALIC; + if (underline_prop && parse_bool (underline_prop, &underline)) + mask |= MOO_TEXT_STYLE_UNDERLINE; + if (strikethrough_prop && parse_bool (strikethrough_prop, &strikethrough)) + mask |= MOO_TEXT_STYLE_STRIKETHROUGH; + if (fg_prop && parse_color (fg_prop, &foreground)) + mask |= MOO_TEXT_STYLE_FOREGROUND; + if (bg_prop && parse_color (bg_prop, &background)) + mask |= MOO_TEXT_STYLE_BACKGROUND; + + return moo_text_style_new (NULL, + &foreground, &background, + bold, italic, underline, + strikethrough, mask, modified); +} + + +static void +load_language_node (MooTextStyleScheme *scheme, + MooMarkupNode *node) +{ + MooMarkupNode *child; + const char *lang_name; + + g_return_if_fail (node != NULL && node->name != NULL && !strcmp (node->name, LANGUAGE_ELM)); + g_return_if_fail (scheme != NULL); + + lang_name = moo_markup_get_prop (node, LANG_NAME_PROP); + g_return_if_fail (lang_name && lang_name[0]); + + for (child = node->children; child != NULL; child = child->next) + { + MooTextStyle *style; + const char *style_name; + + if (!MOO_MARKUP_IS_ELEMENT (child)) + continue; + + if (strcmp (child->name, STYLE_ELM)) + { + g_warning ("%s: invalid element '%s'", G_STRLOC, child->name); + continue; + } + + style_name = moo_markup_get_prop (child, STYLE_NAME_PROP); + + if (!style_name || !style_name[0]) + { + g_warning ("%s: style name absent", G_STRLOC); + continue; + } + + style = style_new_from_markup (child, TRUE); + + if (!style) + { + g_critical ("%s: could not parse style node", G_STRLOC); + continue; + } + + moo_text_style_scheme_compose (scheme, lang_name, style_name, style); + moo_text_style_free (style); + } +} + + +static void +moo_lang_mgr_choose_scheme (MooLangMgr *mgr, + MooMarkupNode *node) +{ + const char *name = moo_markup_get_prop (node, DEFAULT_SCHEME_PROP); + MooTextStyleScheme *scheme; + + if (!name) + name = SCHEME_DEFAULT; + + scheme = g_hash_table_lookup (mgr->schemes, name); + + if (!scheme) + scheme = g_hash_table_lookup (mgr->schemes, SCHEME_DEFAULT); + + g_return_if_fail (scheme != NULL); + mgr->active_scheme = scheme; +} + + +static void +moo_lang_mgr_load_styles (MooLangMgr *mgr) +{ + MooMarkupDoc *xml; + MooMarkupNode *root, *child; + + xml = moo_prefs_get_markup (); + g_return_if_fail (xml != NULL); + + root = moo_markup_get_element (MOO_MARKUP_NODE (xml), + MOO_STYLES_PREFS_PREFIX); + + if (!root) + return; + + moo_lang_mgr_choose_scheme (mgr, root); + + for (child = root->children; child != NULL; child = child->next) + { + MooMarkupNode *grand_child; + MooTextStyleScheme *scheme; + const char *scheme_name; + + if (!MOO_MARKUP_IS_ELEMENT (child)) + continue; + + if (strcmp (child->name, SCHEME_ELM)) + { + g_warning ("%s: invalid element '%s'", G_STRLOC, child->name); + continue; + } + + scheme_name = moo_markup_get_prop (child, SCHEME_NAME_PROP); + + if (!scheme_name || !scheme_name[0]) + { + g_warning ("%s: scheme name missing", G_STRLOC); + continue; + } + + scheme = g_hash_table_lookup (mgr->schemes, scheme_name); + + if (!scheme) + continue; + + for (grand_child = child->children; grand_child != NULL; grand_child = grand_child->next) + { + if (!MOO_MARKUP_IS_ELEMENT (grand_child)) + continue; + + if (!strcmp (grand_child->name, LANGUAGE_ELM)) + { + load_language_node (scheme, grand_child); + } + else if (!strcmp (grand_child->name, DEFAULT_STYLE_ELM)) + { + const char *name; + MooTextStyle *style; + + name = moo_markup_get_prop (grand_child, STYLE_NAME_PROP); + + if (!name || !name[0]) + { + g_warning ("%s: style name absent", G_STRLOC); + continue; + } + + style = style_new_from_markup (grand_child, TRUE); + + if (!style) + { + g_critical ("%s: could not parse style node", G_STRLOC); + continue; + } + + moo_text_style_scheme_compose (scheme, NULL, name, style); + moo_text_style_free (style); + } + else + { + g_warning ("%s: invalid element '%s'", G_STRLOC, grand_child->name); + } + } + } +} + + +static GSList* +read_files (MooLangMgr *mgr, + GHashTable *lang_xml_names) +{ + GSList *l; + GSList *lang_xml_list = NULL; + + g_return_val_if_fail (mgr != NULL, NULL); + g_return_val_if_fail (lang_xml_names != NULL, NULL); + + if (!mgr->lang_dirs) + return NULL; + + for (l = mgr->lang_dirs; l != NULL; l = l->next) + { + const char *dirname = l->data, *entry; + GDir *dir; + + dir = g_dir_open (dirname, 0, NULL); + + if (!dir) + continue; + + while ((entry = g_dir_read_name (dir))) + { + guint entry_len = strlen (entry); + + if (entry_len > LANG_FILE_SUFFIX_LEN && + !strcmp (entry + (entry_len - LANG_FILE_SUFFIX_LEN), LANG_FILE_SUFFIX)) + { + char *filename; + LangXML *lang, *old_lang; + + filename = g_build_filename (dirname, entry, NULL); + lang = moo_lang_parse_file (filename); + g_free (filename); + + if (!lang) + continue; + + old_lang = g_hash_table_lookup (lang_xml_names, lang->name); + + if (old_lang) + { + g_message ("%s: loading another instance of lang '%s'", + G_STRLOC, lang->name); + lang_xml_list = g_slist_remove (lang_xml_list, old_lang); + moo_lang_xml_free (old_lang); + } + + lang_xml_list = g_slist_append (lang_xml_list, lang); + g_hash_table_insert (lang_xml_names, g_strdup (lang->name), lang); + } + else if (entry_len > STYLES_FILE_SUFFIX_LEN && + !strcmp (entry + (entry_len - STYLES_FILE_SUFFIX_LEN), STYLES_FILE_SUFFIX)) + { + char *filename; + MooTextStyleScheme *scheme; + + filename = g_build_filename (dirname, entry, NULL); + scheme = moo_text_style_scheme_parse_file (filename, NULL); /* XXX */ + g_free (filename); + + if (!scheme) + continue; + + if (g_hash_table_lookup (mgr->schemes, scheme->name)) + { + g_message ("%s: loading another instance of scheme '%s'", + G_STRLOC, scheme->name); + if (!strcmp (mgr->active_scheme->name, scheme->name)) + mgr->active_scheme = scheme; + } + + /* XXX base scheme */ + + g_hash_table_insert (mgr->schemes, g_strdup (scheme->name), scheme); + } + } + + g_dir_close (dir); + } + + return lang_xml_list; +} + + +static GSList* +check_external_refs (GSList *lang_xml_list, + GHashTable *lang_xml_names) +{ + gboolean again = TRUE; + + while (again) + { + GSList *l; + + again = FALSE; + + for (l = lang_xml_list; l != NULL; l = l->next) + { + GSList *ref_link; + LangXML *xml = l->data; + gboolean valid = TRUE; + + for (ref_link = xml->external_refs; ref_link != NULL; ref_link = ref_link->next) + { + CrossRef *ref = ref_link->data; + LangXML *ref_lang; + + g_assert (ref->lang != NULL); + + ref_lang = g_hash_table_lookup (lang_xml_names, ref->lang); + + if (!ref_lang) + { + g_warning ("%s: invalid reference to lang '%s' in lang '%s'", + G_STRLOC, ref->lang, xml->name); + g_hash_table_remove (lang_xml_names, xml->name); + lang_xml_list = g_slist_remove (lang_xml_list, xml); + moo_lang_xml_free (xml); + valid = FALSE; + break; + } + + if (!g_hash_table_lookup (ref_lang->context_names, ref->name)) + { + g_warning ("%s: lang '%s' does not contain context '%s', referenced from lang '%s'", + G_STRLOC, ref->lang, ref->name, xml->name); + g_hash_table_remove (lang_xml_names, xml->name); + lang_xml_list = g_slist_remove (lang_xml_list, xml); + moo_lang_xml_free (xml); + valid = FALSE; + break; + } + } + + if (!valid) + { + again = TRUE; + break; + } + } + } + + return lang_xml_list; +} + + +static void +moo_lang_build_contexts (MooLang *lang, + LangXML *xml) +{ + GSList *l; + + g_assert (!strcmp (lang->name, xml->name)); + + for (l = xml->syntax->contexts; l != NULL; l = l->next) + { + ContextXML *ctx_xml = l->data; + MooContext *ctx = moo_lang_add_context (lang, ctx_xml->name, ctx_xml->style); + g_assert (ctx != NULL); + } +} + + +static MooTextStyle* +style_new_from_xml (StyleXML *xml) +{ + GdkColor foreground, background; + gboolean bold, italic, underline, strikethrough; + MooTextStyleMask mask = 0; + + g_return_val_if_fail (xml != NULL, NULL); + + if (xml->bold && parse_bool (xml->bold, &bold)) + mask |= MOO_TEXT_STYLE_BOLD; + if (xml->italic && parse_bool (xml->italic, &italic)) + mask |= MOO_TEXT_STYLE_ITALIC; + if (xml->underline && parse_bool (xml->underline, &underline)) + mask |= MOO_TEXT_STYLE_UNDERLINE; + if (xml->strikethrough && parse_bool (xml->strikethrough, &strikethrough)) + mask |= MOO_TEXT_STYLE_STRIKETHROUGH; + if (xml->foreground && parse_color (xml->foreground, &foreground)) + mask |= MOO_TEXT_STYLE_FOREGROUND; + if (xml->background && parse_color (xml->background, &background)) + mask |= MOO_TEXT_STYLE_BACKGROUND; + + return moo_text_style_new (xml->default_style, + &foreground, &background, + bold, italic, underline, + strikethrough, mask, FALSE); +} + + +static void +moo_lang_parse_mime_types (MooLang *lang, + const char *mimetypes) +{ + char **pieces, **p; + + g_return_if_fail (lang != NULL && mimetypes != NULL); + + pieces = g_strsplit (mimetypes, EXTENSION_SEPARATOR, 0); + + if (!pieces) + return; + + for (p = pieces; *p; p++) + if (**p)/*XXX*/ + lang->mime_types = g_slist_prepend (lang->mime_types, g_strdup (*p)); + + g_strfreev (pieces); +} + + +static void +moo_lang_parse_extensions (MooLang *lang, + const char *extensions) +{ + char **pieces, **p; + + g_return_if_fail (lang != NULL && extensions != NULL); + + pieces = g_strsplit (extensions, EXTENSION_SEPARATOR, 0); + + if (!pieces) + return; + + for (p = pieces; *p; p++) + if (**p) + lang->extensions = g_slist_prepend (lang->extensions, g_strdup (*p)); + + g_strfreev (pieces); +} + + +static void +moo_lang_finish_build (MooLang *lang, + LangXML *xml) +{ + GSList *l; + + g_assert (!strcmp (lang->name, xml->name)); + + if (xml->style_list) + { + for (l = xml->style_list->styles; l != NULL; l = l->next) + { + StyleXML *style_xml = l->data; + MooTextStyle *style = style_new_from_xml (style_xml); + moo_lang_add_style (lang, style_xml->name, style); + moo_text_style_free (style); + } + } + + if (xml->mimetypes) + moo_lang_parse_mime_types (lang, xml->mimetypes); + if (xml->extensions) + moo_lang_parse_extensions (lang, xml->extensions); + if (xml->general) + lang->brackets = g_strdup (xml->general->brackets); + lang->sample = g_strdup (xml->sample); + + for (l = xml->syntax->contexts; l != NULL; l = l->next) + { + GSList *rule_link; + ContextXML *ctx_xml; + MooContext *ctx, *switch_to; + + ctx_xml = l->data; + ctx = moo_lang_get_context (lang, ctx_xml->name); + g_assert (ctx != NULL); + + for (rule_link = ctx_xml->rules; rule_link != NULL; rule_link = rule_link->next) + { + RuleXML *rule_xml = rule_link->data; + MooRule *rule = moo_rule_new_from_xml (rule_xml, xml, lang); + if (rule) + moo_context_add_rule (ctx, rule); + } + + switch (ctx_xml->eol_switch_info.type) + { + case MOO_CONTEXT_STAY: + moo_context_set_line_end_stay (ctx); + break; + case MOO_CONTEXT_POP: + moo_context_set_line_end_pop (ctx, ctx_xml->eol_switch_info.num); + break; + case MOO_CONTEXT_SWITCH: + if (ctx_xml->eol_switch_info.ref.lang) + switch_to = moo_lang_mgr_get_context (lang->mgr, + ctx_xml->eol_switch_info.ref.lang, + ctx_xml->eol_switch_info.ref.name); + else + switch_to = moo_lang_get_context (lang, ctx_xml->eol_switch_info.ref.name); + + if (!switch_to) + g_critical ("%s: oops", G_STRLOC); + else + moo_context_set_line_end_switch (ctx, switch_to); + + break; + } + } +} + + +void +moo_lang_mgr_read_dirs (MooLangMgr *mgr) +{ + GHashTable *lang_xml_names; + GSList *lang_xml_list, *l; + + g_return_if_fail (MOO_IS_LANG_MGR (mgr)); + g_return_if_fail (!mgr->dirs_read); + + if (!mgr->lang_dirs) + return; + + lang_xml_names = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + lang_xml_list = read_files (mgr, lang_xml_names); + + if (!lang_xml_list) + goto out; + + lang_xml_list = check_external_refs (lang_xml_list, lang_xml_names); + + if (!lang_xml_list) + goto out; + + mgr->dirs_read = TRUE; + + for (l = lang_xml_list; l != NULL; l = l->next) + { + LangXML *xml = l->data; + MooLang *lang = moo_lang_new (mgr, xml->name, + xml->section, xml->version, + xml->author); + lang->hidden = xml->hidden; + moo_lang_build_contexts (lang, xml); + } + + for (l = lang_xml_list; l != NULL; l = l->next) + { + LangXML *xml = l->data; + MooLang *lang = moo_lang_mgr_get_lang (mgr, xml->name); + g_assert (lang != NULL); + moo_lang_finish_build (lang, xml); + } + +out: + g_hash_table_destroy (lang_xml_names); + g_slist_foreach (lang_xml_list, (GFunc) moo_lang_xml_free, NULL); + g_slist_free (lang_xml_list); + + moo_lang_mgr_load_styles (mgr); +} + + +MooContext* +moo_lang_mgr_get_context (MooLangMgr *mgr, + const char *lang_name, + const char *ctx_name) +{ + MooLang *lang; + g_return_val_if_fail (MOO_IS_LANG_MGR (mgr), NULL); + g_return_val_if_fail (lang_name && ctx_name, NULL); + lang = moo_lang_mgr_get_lang (mgr, lang_name); + g_return_val_if_fail (lang != NULL, NULL); + return moo_lang_get_context (lang, ctx_name); +} + + +MooLang* +moo_lang_mgr_get_lang (MooLangMgr *mgr, + const char *name) +{ + g_return_val_if_fail (MOO_IS_LANG_MGR (mgr), NULL); + g_return_val_if_fail (name != NULL, NULL); + return g_hash_table_lookup (mgr->lang_names, name); +} + + +GSList* +moo_lang_mgr_get_available_langs (MooLangMgr *mgr) +{ + g_return_val_if_fail (MOO_IS_LANG_MGR (mgr), NULL); + return g_slist_copy (mgr->langs); +} + + +static void +maybe_add_section (MooLang *lang, + GSList **list) +{ + if (!g_slist_find_custom (*list, lang->section, (GCompareFunc) strcmp)) + *list = g_slist_prepend (*list, g_strdup (lang->section)); +} + +GSList* +moo_lang_mgr_get_sections (MooLangMgr *mgr) +{ + GSList *list = NULL; + g_return_val_if_fail (MOO_IS_LANG_MGR (mgr), NULL); + g_slist_foreach (mgr->langs, (GFunc) maybe_add_section, &list); + return list; +} + + +MooLang* +moo_lang_mgr_get_lang_for_file (MooLangMgr *mgr, + const char *filename) +{ + MooLang *lang = NULL; + char *basename, *utf8_basename; + GSList *l; + gboolean found = FALSE; + + g_return_val_if_fail (MOO_IS_LANG_MGR (mgr), NULL); + g_return_val_if_fail (filename != NULL, NULL); + + /* TODO: is this right? */ + basename = g_path_get_basename (filename); + g_return_val_if_fail (basename != NULL, NULL); + utf8_basename = g_filename_display_name (basename); + g_return_val_if_fail (utf8_basename != NULL, NULL); + + for (l = mgr->langs; !found && l != NULL; l = l->next) + { + GSList *g; + lang = l->data; + + for (g = lang->extensions; !found && g != NULL; g = g->next) + { + if (g_pattern_match_simple ((char*) g->data, utf8_basename)) + { + found = TRUE; + break; + } + } + } + + if (!found) + lang = NULL; + +#ifdef MOO_USE_XDGMIME + /* XXX: xdgmime wants utf8-encoded filename here. is it a problem? */ + + if (!lang) + { + const char *mime_type = xdg_mime_get_mime_type_for_file (filename); + if (!xdg_mime_mime_type_equal (mime_type, XDG_MIME_TYPE_UNKNOWN)) + lang = moo_lang_mgr_get_lang_for_mime_type (mgr, mime_type); + } +#endif /* MOO_USE_XDGMIME */ + + if (!lang) + lang = moo_lang_mgr_get_lang_for_filename (mgr, filename); + + g_free (utf8_basename); + g_free (basename); + return lang; +} + + +MooLang* +moo_lang_mgr_get_lang_for_filename (MooLangMgr *mgr, + const char *filename) +{ + MooLang *lang = NULL; + char *basename, *utf8_basename; + GSList *l; + gboolean found = FALSE; + + g_return_val_if_fail (MOO_IS_LANG_MGR (mgr), NULL); + g_return_val_if_fail (filename != NULL, NULL); + + basename = g_path_get_basename (filename); + g_return_val_if_fail (basename != NULL, NULL); + utf8_basename = g_filename_display_name (basename); + g_return_val_if_fail (utf8_basename != NULL, NULL); + + for (l = mgr->langs; l != NULL && !found; l = l->next) + { + GSList *g; + + lang = l->data; + + for (g = lang->extensions; !found && g != NULL; g = g->next) + if (g_pattern_match_simple (g->data, utf8_basename)) + found = TRUE; + } + + if (!found) + lang = NULL; + +#ifdef MOO_USE_XDGMIME + /* XXX: xdgmime wants utf8-encoded filename here. is it a problem? */ + if (!lang) + { + const char *mime_type = xdg_mime_get_mime_type_from_file_name (filename); + if (!xdg_mime_mime_type_equal (mime_type, XDG_MIME_TYPE_UNKNOWN)) + lang = moo_lang_mgr_get_lang_for_mime_type (mgr, mime_type); + } +#endif /* MOO_USE_XDGMIME */ + + /* check if it's backup file */ + if (!lang) + { + char *base = NULL; + int len = strlen (utf8_basename); + guint i; + + static const char *bak_globs[] = {"*~", "*.bak", "*.in"}; + + /* XXX this is broken - it passes utf8 filename to get_lang_for_filename */ + + for (i = 0; i < G_N_ELEMENTS (bak_globs); ++i) + { + int ext_len = strlen (bak_globs[i]) - 1; + + if (len > ext_len && g_pattern_match_simple (bak_globs[i], utf8_basename)) + { + base = g_strndup (utf8_basename, len - ext_len); + break; + } + } + + if (base) + { + lang = moo_lang_mgr_get_lang_for_filename (mgr, base); + g_free (base); + } + } + + return lang; +} + + +MooLang* +moo_lang_mgr_get_lang_for_mime_type (MooLangMgr *mgr, + const char *mime_type) +{ + GSList *l; + MooLang *lang = NULL; + gboolean found = FALSE; + + g_return_val_if_fail (MOO_IS_LANG_MGR (mgr), NULL); + g_return_val_if_fail (mime_type != NULL, NULL); + + for (l = mgr->langs; !found && l != NULL; l = l->next) + { + lang = l->data; + + if (g_slist_find_custom (lang->mime_types, mime_type, (GCompareFunc) strcmp)) + { + found = TRUE; + break; + } + } + + return found ? lang : NULL; +} + + +static MooTextStyle* +moo_lang_get_style (MooLang *lang, + const char *style_name) +{ + MooTextStyle *style; + g_return_val_if_fail (lang != NULL && style_name != NULL, NULL); + style = g_hash_table_lookup (lang->style_names, style_name); + return moo_text_style_copy (style); +} + + +MooTextStyle* +moo_lang_mgr_get_style (MooLangMgr *mgr, + const char *lang_name, + const char *style_name, + MooTextStyleScheme *scheme) +{ + const MooTextStyle *scheme_style = NULL; + MooTextStyle *lang_style = NULL; + + g_return_val_if_fail (MOO_IS_LANG_MGR (mgr), NULL); + g_return_val_if_fail (style_name != NULL, NULL); + g_return_val_if_fail (mgr->active_scheme != NULL, NULL); + + if (!scheme) + scheme = mgr->active_scheme; + + if (lang_name) + { + MooLang *lang = moo_lang_mgr_get_lang (mgr, lang_name); + g_return_val_if_fail (lang != NULL, NULL); + lang_style = moo_lang_get_style (lang, style_name); + } + + scheme_style = moo_text_style_scheme_get (scheme, lang_name, style_name); + + if (lang_style) + { + if (scheme_style) + moo_text_style_compose (lang_style, scheme_style); + return lang_style; + } + else if (scheme_style) + { + return moo_text_style_copy (scheme_style); + } + else + { + return NULL; + } +} + + +MooTextStyleScheme* +moo_lang_mgr_get_active_scheme (MooLangMgr *mgr) +{ + g_return_val_if_fail (MOO_IS_LANG_MGR (mgr), NULL); + g_return_val_if_fail (mgr->active_scheme != NULL, NULL); + return mgr->active_scheme; +} + + +void +_moo_lang_mgr_add_lang (MooLangMgr *mgr, + MooLang *lang) +{ + g_return_if_fail (MOO_IS_LANG_MGR (mgr)); + g_return_if_fail (lang != NULL); + g_return_if_fail (lang->name != NULL); + g_return_if_fail (!g_hash_table_lookup (mgr->lang_names, lang->name)); + + mgr->langs = g_slist_append (mgr->langs, lang); + g_hash_table_insert (mgr->lang_names, g_strdup (lang->name), lang); +} + + +static void +prepend_scheme (G_GNUC_UNUSED const char *scheme_name, + gpointer scheme, + GSList **list) +{ + *list = g_slist_prepend (*list, scheme); +} + +GSList* +moo_lang_mgr_list_schemes (MooLangMgr *mgr) +{ + GSList *list = NULL; + g_return_val_if_fail (MOO_IS_LANG_MGR (mgr), NULL); + g_hash_table_foreach (mgr->schemes, (GHFunc) prepend_scheme, &list); + return list; +} diff --git a/moo/mooedit/moolangmgr.h b/moo/mooedit/moolangmgr.h new file mode 100644 index 00000000..0a14c528 --- /dev/null +++ b/moo/mooedit/moolangmgr.h @@ -0,0 +1,96 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4; coding: utf-8 -*- + * + * moolangmgr.h + * + * Copyright (C) 2004-2005 by Yevgen Muntyan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * See COPYING file that comes with this distribution. + */ + +#ifndef __MOO_LANG_MGR_H__ +#define __MOO_LANG_MGR_H__ + +#include + +G_BEGIN_DECLS + + +#define MOO_LANG_DIR_BASENAME "syntax" +#define MOO_STYLES_PREFS_PREFIX MOO_EDIT_PREFS_PREFIX "/styles" + +#define MOO_TYPE_LANG_MGR (moo_lang_mgr_get_type ()) +#define MOO_LANG_MGR(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MOO_TYPE_LANG_MGR, MooLangMgr)) +#define MOO_LANG_MGR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOO_TYPE_LANG_MGR, MooLangMgrClass)) +#define MOO_IS_LANG_MGR(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MOO_TYPE_LANG_MGR)) +#define MOO_IS_LANG_MGR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOO_TYPE_LANG_MGR)) +#define MOO_LANG_MGR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOO_TYPE_LANG_MGR, MooLangMgrClass)) + + +typedef struct _MooLangMgr MooLangMgr; +typedef struct _MooLangMgrClass MooLangMgrClass; + +struct _MooLangMgr { + GObject base; + + GSList *lang_dirs; + GSList *langs; + GHashTable *lang_names; + GHashTable *schemes; + MooTextStyleScheme *active_scheme; + guint dirs_read : 1; +}; + +struct _MooLangMgrClass +{ + GObjectClass base_class; + + void (*lang_added) (MooLangMgr *mgr, + const char *lang_name); + void (*lang_removed) (MooLangMgr *mgr, + const char *lang_name); +}; + + +GType moo_lang_mgr_get_type (void) G_GNUC_CONST; + +MooLangMgr *moo_lang_mgr_new (void); + +GSList *moo_lang_mgr_get_available_langs (MooLangMgr *mgr); +GSList *moo_lang_mgr_get_sections (MooLangMgr *mgr); + +MooLang *moo_lang_mgr_get_lang_for_file (MooLangMgr *mgr, + const char *filename); +MooLang *moo_lang_mgr_get_lang_for_filename (MooLangMgr *mgr, + const char *filename); +MooLang *moo_lang_mgr_get_lang_for_mime_type (MooLangMgr *mgr, + const char *mime_type); +MooLang *moo_lang_mgr_get_lang (MooLangMgr *mgr, + const char *name); +MooContext *moo_lang_mgr_get_context (MooLangMgr *mgr, + const char *lang_name, + const char *ctx_name); + +GSList *moo_lang_mgr_list_schemes (MooLangMgr *mgr); + +void moo_lang_mgr_add_dir (MooLangMgr *mgr, + const char *dir); +void moo_lang_mgr_read_dirs (MooLangMgr *mgr); + +MooTextStyle *moo_lang_mgr_get_style (MooLangMgr *mgr, + const char *lang_name, /* default style if NULL */ + const char *style_name, + MooTextStyleScheme *scheme); +MooTextStyleScheme *moo_lang_mgr_get_active_scheme (MooLangMgr *mgr); + +void _moo_lang_mgr_add_lang (MooLangMgr *mgr, + MooLang *lang); + + +G_END_DECLS + +#endif /* __MOO_LANG_MGR_H__ */ diff --git a/moo/mooedit/mootextbuffer.c b/moo/mooedit/mootextbuffer.c index 0cc73f88..d573abf1 100644 --- a/moo/mooedit/mootextbuffer.c +++ b/moo/mooedit/mootextbuffer.c @@ -538,6 +538,19 @@ _moo_text_buffer_apply_syntax_tag (MooTextBuffer *buffer, } +void +moo_text_buffer_apply_scheme (MooTextBuffer *buffer, + MooTextStyleScheme *scheme) +{ + g_return_if_fail (scheme != NULL); + g_return_if_fail (MOO_IS_TEXT_BUFFER (buffer)); + + moo_text_buffer_set_bracket_match_style (buffer, scheme->bracket_match); + moo_text_buffer_set_bracket_mismatch_style (buffer, scheme->bracket_mismatch); + moo_highlighter_apply_scheme (buffer->priv->hl, scheme); +} + + /*****************************************************************************/ /* Matching brackets */ diff --git a/moo/mooedit/mootextbuffer.h b/moo/mooedit/mootextbuffer.h index ef58b85f..c1ab3b9e 100644 --- a/moo/mooedit/mootextbuffer.h +++ b/moo/mooedit/mootextbuffer.h @@ -73,6 +73,8 @@ void moo_text_buffer_set_check_brackets (MooTextBuffer *buf gboolean moo_text_buffer_has_text (MooTextBuffer *buffer); gboolean moo_text_buffer_has_selection (MooTextBuffer *buffer); +void moo_text_buffer_apply_scheme (MooTextBuffer *buffer, + MooTextStyleScheme *scheme); void _moo_text_buffer_ensure_highlight (MooTextBuffer *buffer, int first_line, diff --git a/moo/mooedit/mootextstyle.c b/moo/mooedit/mootextstyle.c index e6f00abc..a80e9e6c 100644 --- a/moo/mooedit/mootextstyle.c +++ b/moo/mooedit/mootextstyle.c @@ -187,393 +187,3 @@ moo_text_style_mask_get_type (void) return type; } - - -/****************************************************************************/ -/* Style schemes - */ - -static void fill_in_default_scheme (MooTextStyleScheme *scheme); - - -GType -moo_text_style_scheme_get_type (void) -{ - static GType type = 0; - - if (!type) - type = g_boxed_type_register_static ("MooTextStyleScheme", - (GBoxedCopyFunc) moo_text_style_scheme_ref, - (GBoxedFreeFunc) moo_text_style_scheme_unref); - - return type; -} - - -MooTextStyleScheme* -moo_text_style_scheme_new_empty (const char *name) -{ - MooTextStyleScheme *scheme; - - g_return_val_if_fail (name && name[0], NULL); - - scheme = g_new0 (MooTextStyleScheme, 1); - - scheme->name = g_strdup (name); - scheme->styles = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, - (GDestroyNotify) moo_text_style_free); - scheme->ref_count = 1; - scheme->use_theme_colors = TRUE; - - return scheme; -} - - -MooTextStyleScheme* -moo_text_style_scheme_new_default (void) -{ - MooTextStyleScheme *scheme; - scheme = moo_text_style_scheme_new_empty (SCHEME_DEFAULT); - fill_in_default_scheme (scheme); - return scheme; -} - - -static void -copy_style (const char *style_name, - const MooTextStyle *style, - GHashTable *dest) -{ - g_hash_table_insert (dest, g_strdup (style_name), - moo_text_style_copy (style)); -} - -MooTextStyleScheme* -moo_text_style_scheme_copy (MooTextStyleScheme *scheme) -{ - MooTextStyleScheme *copy; - - g_return_val_if_fail (scheme != NULL, NULL); - - copy = moo_text_style_scheme_new_empty (scheme->name); - - copy->foreground = g_strdup (scheme->foreground); - copy->background = g_strdup (scheme->background); - copy->selected_foreground = g_strdup (scheme->selected_foreground); - copy->selected_background = g_strdup (scheme->selected_background); - copy->current_line = g_strdup (scheme->current_line); - copy->use_theme_colors = scheme->use_theme_colors; - copy->bracket_match = moo_text_style_copy (scheme->bracket_match); - copy->bracket_mismatch = moo_text_style_copy (scheme->bracket_mismatch); - - g_hash_table_foreach (scheme->styles, (GHFunc) copy_style, scheme->styles); - - return copy; -} - - -void -moo_text_style_scheme_compose (MooTextStyleScheme *scheme, - const char *language_name, - const char *style_name, - const MooTextStyle *style) -{ - const char *key; - char *freeme = NULL; - MooTextStyle *old_style; - - g_return_if_fail (scheme != NULL); - g_return_if_fail (style_name != NULL && style != NULL); - - if (language_name) - { - freeme = g_strdup_printf ("%s::%s", language_name, style_name); - key = freeme; - } - else - { - key = style_name; - } - - old_style = g_hash_table_lookup (scheme->styles, key); - - if (old_style) - moo_text_style_compose (old_style, style); - else - g_hash_table_insert (scheme->styles, g_strdup (key), - moo_text_style_copy (style)); - - g_free (freeme); -} - - -void -moo_text_style_scheme_set (MooTextStyleScheme *scheme, - const char *language_name, - const char *style_name, - const MooTextStyle *style) -{ - const char *key; - char *freeme = NULL; - - g_return_if_fail (scheme != NULL); - g_return_if_fail (style_name != NULL && style != NULL); - - if (language_name) - { - freeme = g_strdup_printf ("%s::%s", language_name, style_name); - key = freeme; - } - else - { - key = style_name; - } - - g_hash_table_insert (scheme->styles, g_strdup (key), - moo_text_style_copy (style)); - - g_free (freeme); -} - - -const MooTextStyle* -moo_text_style_scheme_get (MooTextStyleScheme *scheme, - const char *language_name, - const char *style_name) -{ - const MooTextStyle *style; - const char *key; - char *freeme = NULL; - - g_return_val_if_fail (scheme != NULL, NULL); - g_return_val_if_fail (style_name != NULL, NULL); - - if (language_name) - { - freeme = g_strdup_printf ("%s::%s", language_name, style_name); - key = freeme; - } - else - { - key = style_name; - } - - style = g_hash_table_lookup (scheme->styles, key); - - g_free (freeme); - return style; -} - - -MooTextStyleScheme* -moo_text_style_scheme_ref (MooTextStyleScheme *scheme) -{ - g_return_val_if_fail (scheme != NULL, NULL); - scheme->ref_count++; - return scheme; -} - - -void -moo_text_style_scheme_unref (MooTextStyleScheme *scheme) -{ - if (scheme && !(--scheme->ref_count)) - { - g_free (scheme->name); - g_free (scheme->foreground); - g_free (scheme->background); - g_free (scheme->selected_foreground); - g_free (scheme->selected_background); - g_free (scheme->current_line); - g_hash_table_destroy (scheme->styles); - moo_text_style_free (scheme->bracket_match); - moo_text_style_free (scheme->bracket_mismatch); - g_free (scheme); - } -} - - -static MooTextStyle* -new_style (const char *fg, - const char *bg, - gboolean italic, - gboolean bold, - gboolean underline, - gboolean strikethrough, - MooTextStyleMask mask) -{ - GdkColor foreground, background; - - if (mask & MOO_TEXT_STYLE_FOREGROUND) - { - if (!gdk_color_parse (fg, &foreground)) - { - g_warning ("could not parse color %s", fg); - mask = mask & ~MOO_TEXT_STYLE_FOREGROUND; - } - } - - if (mask & MOO_TEXT_STYLE_BACKGROUND) - { - if (!gdk_color_parse (bg, &background)) - { - g_warning ("could not parse color %s", bg); - mask = mask & ~MOO_TEXT_STYLE_BACKGROUND; - } - } - - return moo_text_style_new (NULL, &foreground, &background, - bold, italic, underline, strikethrough, - mask, FALSE); -} - - -#define INSERT(name_,fg_,bg_,italic_,bold_,underline_,strikethrough_,mask_) \ - g_hash_table_insert (scheme->styles, g_strdup (name_), \ - new_style (fg_, bg_, italic_, bold_, \ - underline_, strikethrough_, mask_)) - -static void -fill_in_default_scheme (MooTextStyleScheme *scheme) -{ - scheme->current_line = g_strdup ("#EEF6FF"); - scheme->bracket_match = new_style (NULL, "#FFFF99", FALSE, - FALSE, FALSE, FALSE, - MOO_TEXT_STYLE_BACKGROUND); - - INSERT (DEF_STYLE_NORMAL, - NULL, NULL, FALSE, FALSE, FALSE, FALSE, 0); - - INSERT (DEF_STYLE_PREPROCESSOR, - "#008000", NULL, FALSE, FALSE, FALSE, FALSE, - MOO_TEXT_STYLE_FOREGROUND); - - INSERT (DEF_STYLE_STRING, - "#DD0000", NULL, FALSE, FALSE, FALSE, FALSE, - MOO_TEXT_STYLE_FOREGROUND); - - INSERT (DEF_STYLE_COMMENT, - "#808080", NULL, TRUE, FALSE, FALSE, FALSE, - MOO_TEXT_STYLE_FOREGROUND | MOO_TEXT_STYLE_ITALIC); - - INSERT (DEF_STYLE_BASE_N, - "#008080", NULL, FALSE, FALSE, FALSE, FALSE, - MOO_TEXT_STYLE_FOREGROUND); - - INSERT (DEF_STYLE_KEYWORD, - NULL, NULL, FALSE, TRUE, FALSE, FALSE, - MOO_TEXT_STYLE_BOLD); - - INSERT (DEF_STYLE_DATA_TYPE, - "#800000", NULL, FALSE, FALSE, FALSE, FALSE, - MOO_TEXT_STYLE_FOREGROUND); - - INSERT (DEF_STYLE_DECIMAL, - "#0000FF", NULL, FALSE, FALSE, FALSE, FALSE, - MOO_TEXT_STYLE_FOREGROUND); - - INSERT (DEF_STYLE_FLOAT, - "#800080", NULL, FALSE, FALSE, FALSE, FALSE, - MOO_TEXT_STYLE_FOREGROUND); - - INSERT (DEF_STYLE_CHAR, - "#FF00FF", NULL, FALSE, FALSE, FALSE, FALSE, - MOO_TEXT_STYLE_FOREGROUND); - - INSERT (DEF_STYLE_ALERT, - "#FFFFFF", "#FFCCCC", FALSE, TRUE, FALSE, FALSE, - MOO_TEXT_STYLE_FOREGROUND | MOO_TEXT_STYLE_BACKGROUND | - MOO_TEXT_STYLE_BOLD | MOO_TEXT_STYLE_ITALIC); - - INSERT (DEF_STYLE_FUNCTION, - "#000080", NULL, FALSE, FALSE, FALSE, FALSE, - MOO_TEXT_STYLE_FOREGROUND); - - INSERT (DEF_STYLE_ERROR, - "#FF0000", NULL, FALSE, FALSE, TRUE, FALSE, - MOO_TEXT_STYLE_FOREGROUND | MOO_TEXT_STYLE_UNDERLINE); - - INSERT (DEF_STYLE_OTHERS, - "#008000", NULL, FALSE, FALSE, FALSE, FALSE, - MOO_TEXT_STYLE_FOREGROUND); -} -#undef INSERT - - -void -_moo_text_style_scheme_apply (MooTextStyleScheme *scheme, - gpointer view) -{ - GdkColor color; - GdkColor *color_ptr; - MooTextBuffer *buffer; - - g_return_if_fail (scheme != NULL); - g_return_if_fail (MOO_IS_TEXT_VIEW (view)); - - buffer = MOO_TEXT_BUFFER (gtk_text_view_get_buffer (view)); - - gtk_widget_ensure_style (view); - - color_ptr = NULL; - if (scheme->foreground) - { - if (gdk_color_parse (scheme->foreground, &color)) - color_ptr = &color; - else - g_warning ("%s: could not parse color '%s'", G_STRLOC, scheme->foreground); - } - gtk_widget_modify_text (view, GTK_STATE_NORMAL, color_ptr); - gtk_widget_modify_text (view, GTK_STATE_ACTIVE, color_ptr); - gtk_widget_modify_text (view, GTK_STATE_PRELIGHT, color_ptr); - gtk_widget_modify_text (view, GTK_STATE_INSENSITIVE, color_ptr); - moo_text_view_set_cursor_color (view, color_ptr); - - color_ptr = NULL; - if (scheme->background) - { - if (gdk_color_parse (scheme->background, &color)) - color_ptr = &color; - else - g_warning ("%s: could not parse color '%s'", G_STRLOC, scheme->background); - } - gtk_widget_modify_base (view, GTK_STATE_NORMAL, color_ptr); - gtk_widget_modify_base (view, GTK_STATE_ACTIVE, color_ptr); - gtk_widget_modify_base (view, GTK_STATE_PRELIGHT, color_ptr); - gtk_widget_modify_base (view, GTK_STATE_INSENSITIVE, color_ptr); - - color_ptr = NULL; - if (scheme->selected_foreground) - { - if (gdk_color_parse (scheme->selected_foreground, &color)) - color_ptr = &color; - else - g_warning ("%s: could not parse color '%s'", G_STRLOC, scheme->selected_foreground); - } - gtk_widget_modify_text (view, GTK_STATE_SELECTED, color_ptr); - - color_ptr = NULL; - if (scheme->selected_background) - { - if (gdk_color_parse (scheme->selected_background, &color)) - color_ptr = &color; - else - g_warning ("%s: could not parse color '%s'", G_STRLOC, scheme->selected_background); - } - gtk_widget_modify_base (view, GTK_STATE_SELECTED, color_ptr); - - color_ptr = NULL; - if (scheme->current_line) - { - if (gdk_color_parse (scheme->current_line, &color)) - color_ptr = &color; - else - g_warning ("%s: could not parse color '%s'", G_STRLOC, scheme->current_line); - } - moo_text_view_set_current_line_color (view, color_ptr); - moo_text_view_set_highlight_current_line (view, color_ptr != NULL); - - moo_text_buffer_set_bracket_match_style (buffer, scheme->bracket_match); - moo_text_buffer_set_bracket_mismatch_style (buffer, scheme->bracket_mismatch); -} diff --git a/moo/mooedit/mootextstyle.h b/moo/mooedit/mootextstyle.h index 820ad58b..d8e21d7d 100644 --- a/moo/mooedit/mootextstyle.h +++ b/moo/mooedit/mootextstyle.h @@ -21,11 +21,9 @@ G_BEGIN_DECLS #define MOO_TYPE_TEXT_STYLE (moo_text_style_get_type ()) #define MOO_TYPE_TEXT_STYLE_MASK (moo_text_style_mask_get_type ()) -#define MOO_TYPE_TEXT_STYLE_SCHEME (moo_text_style_scheme_get_type ()) typedef struct _MooTextStyle MooTextStyle; typedef struct _MooTextStyleArray MooTextStyleArray; -typedef struct _MooTextStyleScheme MooTextStyleScheme; typedef enum { MOO_TEXT_STYLE_FOREGROUND = 1 << 0, @@ -53,24 +51,9 @@ struct _MooTextStyleArray { guint len; }; -struct _MooTextStyleScheme { - char *name; - char *foreground; - char *background; - char *selected_foreground; - char *selected_background; - char *current_line; - MooTextStyle *bracket_match; - MooTextStyle *bracket_mismatch; - GHashTable *styles; /* char* -> MooTextStyle* */ - guint ref_count; - guint use_theme_colors : 1; -}; - GType moo_text_style_get_type (void) G_GNUC_CONST; GType moo_text_style_mask_get_type (void) G_GNUC_CONST; -GType moo_text_style_scheme_get_type (void) G_GNUC_CONST; MooTextStyle *moo_text_style_new (const char *default_style, const GdkColor *foreground, @@ -88,27 +71,6 @@ void moo_text_style_compose (MooTextStyle *dest, const MooTextStyle *src); void moo_text_style_free (MooTextStyle *style); -MooTextStyleScheme *moo_text_style_scheme_new_empty (const char *name); -MooTextStyleScheme *moo_text_style_scheme_new_default (void); -MooTextStyleScheme *moo_text_style_scheme_copy (MooTextStyleScheme *scheme); -MooTextStyleScheme *moo_text_style_scheme_ref (MooTextStyleScheme *scheme); -void moo_text_style_scheme_unref (MooTextStyleScheme *scheme); - -void moo_text_style_scheme_compose (MooTextStyleScheme *scheme, - const char *language_name, - const char *style_name, - const MooTextStyle *style); -void moo_text_style_scheme_set (MooTextStyleScheme *scheme, - const char *language_name, - const char *style_name, - const MooTextStyle *style); -const MooTextStyle *moo_text_style_scheme_get (MooTextStyleScheme *scheme, - const char *language_name, - const char *style_name); - -void _moo_text_style_scheme_apply (MooTextStyleScheme *scheme, - gpointer view); - G_END_DECLS diff --git a/moo/mooedit/mootextstylescheme.c b/moo/mooedit/mootextstylescheme.c new file mode 100644 index 00000000..0c42b0e1 --- /dev/null +++ b/moo/mooedit/mootextstylescheme.c @@ -0,0 +1,424 @@ +/* + * mootextstylescheme.c + * + * Copyright (C) 2004-2005 by Yevgen Muntyan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * See COPYING file that comes with this distribution. + */ + +#define MOOEDIT_COMPILATION +#include "mooedit/mootextstylescheme.h" +#include "mooedit/moolang-strings.h" +#include "mooedit/mootextview.h" +#include "mooedit/mootextbuffer.h" +#include "mooutils/moomarshals.h" +#include + + +static void moo_text_style_scheme_finalize (GObject *object); +static void fill_in_default_scheme (MooTextStyleScheme *scheme); + + +/* MOO_TYPE_TEXT_STYLE_SCHEME */ +G_DEFINE_TYPE (MooTextStyleScheme, moo_text_style_scheme, G_TYPE_OBJECT) + +enum { + CHANGED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +static void +moo_text_style_scheme_class_init (MooTextStyleSchemeClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = moo_text_style_scheme_finalize; + + signals[CHANGED] = + g_signal_new ("changed", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MooTextStyleSchemeClass, changed), + NULL, NULL, + _moo_marshal_VOID__VOID, + G_TYPE_NONE,0); +} + + +static void +moo_text_style_scheme_init (MooTextStyleScheme *scheme) +{ + scheme->base_scheme = NULL; + scheme->name = NULL; + memset (scheme->text_colors, 0, MOO_TEXT_NUM_COLORS * sizeof(char*)); + scheme->bracket_match = NULL; + scheme->bracket_mismatch = NULL; + scheme->styles = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, + (GDestroyNotify) moo_text_style_free); +} + + +static void +moo_text_style_scheme_finalize (GObject *object) +{ + guint i; + MooTextStyleScheme *scheme = MOO_TEXT_STYLE_SCHEME (object); + + if (scheme->base_scheme) + g_object_unref (scheme->base_scheme); + + g_free (scheme->name); + + for (i = 0; i < MOO_TEXT_NUM_COLORS; ++i) + g_free (scheme->text_colors[i]); + + g_hash_table_destroy (scheme->styles); + moo_text_style_free (scheme->bracket_match); + moo_text_style_free (scheme->bracket_mismatch); + + G_OBJECT_CLASS(moo_text_style_scheme_parent_class)->finalize (object); +} + + +MooTextStyleScheme* +moo_text_style_scheme_new_empty (const char *name, + MooTextStyleScheme *base) +{ + MooTextStyleScheme *scheme; + + g_return_val_if_fail (name && name[0], NULL); + + scheme = g_object_new (MOO_TYPE_TEXT_STYLE_SCHEME, NULL); + + scheme->base_scheme = base ? g_object_ref (base) : NULL; + scheme->name = g_strdup (name); + + return scheme; +} + + +MooTextStyleScheme* +moo_text_style_scheme_new_default (void) +{ + MooTextStyleScheme *scheme; + scheme = moo_text_style_scheme_new_empty (SCHEME_DEFAULT, NULL); + fill_in_default_scheme (scheme); + return scheme; +} + + +static void +copy_style (const char *style_name, + const MooTextStyle *style, + GHashTable *dest) +{ + g_hash_table_insert (dest, g_strdup (style_name), + moo_text_style_copy (style)); +} + +MooTextStyleScheme* +moo_text_style_scheme_copy (MooTextStyleScheme *scheme) +{ + MooTextStyleScheme *copy; + guint i; + + g_return_val_if_fail (scheme != NULL, NULL); + + copy = moo_text_style_scheme_new_empty (scheme->name, scheme->base_scheme); + + for (i = 0; i < MOO_TEXT_NUM_COLORS; ++i) + copy->text_colors[i] = g_strdup (scheme->text_colors[i]); + + copy->bracket_match = moo_text_style_copy (scheme->bracket_match); + copy->bracket_mismatch = moo_text_style_copy (scheme->bracket_mismatch); + + g_hash_table_foreach (scheme->styles, (GHFunc) copy_style, scheme->styles); + + return copy; +} + + +void +moo_text_style_scheme_compose (MooTextStyleScheme *scheme, + const char *language_name, + const char *style_name, + const MooTextStyle *style) +{ + const char *key; + char *freeme = NULL; + MooTextStyle *old_style; + + g_return_if_fail (scheme != NULL); + g_return_if_fail (style_name != NULL && style != NULL); + + if (language_name) + { + freeme = g_strdup_printf ("%s::%s", language_name, style_name); + key = freeme; + } + else + { + key = style_name; + } + + old_style = g_hash_table_lookup (scheme->styles, key); + + if (old_style) + moo_text_style_compose (old_style, style); + else + g_hash_table_insert (scheme->styles, g_strdup (key), + moo_text_style_copy (style)); + + g_free (freeme); +} + + +void +moo_text_style_scheme_set (MooTextStyleScheme *scheme, + const char *language_name, + const char *style_name, + const MooTextStyle *style) +{ + const char *key; + char *freeme = NULL; + + g_return_if_fail (scheme != NULL); + g_return_if_fail (style_name != NULL && style != NULL); + + if (language_name) + { + freeme = g_strdup_printf ("%s::%s", language_name, style_name); + key = freeme; + } + else + { + key = style_name; + } + + g_hash_table_insert (scheme->styles, g_strdup (key), + moo_text_style_copy (style)); + + g_free (freeme); +} + + +const MooTextStyle* +moo_text_style_scheme_get (MooTextStyleScheme *scheme, + const char *language_name, + const char *style_name) +{ + const MooTextStyle *style; + const char *key; + char *freeme = NULL; + + g_return_val_if_fail (scheme != NULL, NULL); + g_return_val_if_fail (style_name != NULL, NULL); + + if (language_name) + { + freeme = g_strdup_printf ("%s::%s", language_name, style_name); + key = freeme; + } + else + { + key = style_name; + } + + style = g_hash_table_lookup (scheme->styles, key); + + g_free (freeme); + return style; +} + + +static MooTextStyle* +new_style (const char *fg, + const char *bg, + gboolean italic, + gboolean bold, + gboolean underline, + gboolean strikethrough, + MooTextStyleMask mask) +{ + GdkColor foreground, background; + + if (mask & MOO_TEXT_STYLE_FOREGROUND) + { + if (!gdk_color_parse (fg, &foreground)) + { + g_warning ("could not parse color %s", fg); + mask = mask & ~MOO_TEXT_STYLE_FOREGROUND; + } + } + + if (mask & MOO_TEXT_STYLE_BACKGROUND) + { + if (!gdk_color_parse (bg, &background)) + { + g_warning ("could not parse color %s", bg); + mask = mask & ~MOO_TEXT_STYLE_BACKGROUND; + } + } + + return moo_text_style_new (NULL, &foreground, &background, + bold, italic, underline, strikethrough, + mask, FALSE); +} + + +#define INSERT(name_,fg_,bg_,italic_,bold_,underline_,strikethrough_,mask_) \ + g_hash_table_insert (scheme->styles, g_strdup (name_), \ + new_style (fg_, bg_, italic_, bold_, \ + underline_, strikethrough_, mask_)) + +static void +fill_in_default_scheme (MooTextStyleScheme *scheme) +{ + scheme->text_colors[MOO_TEXT_COLOR_CUR_LINE] = g_strdup ("#EEF6FF"); + scheme->bracket_match = new_style (NULL, "#FFFF99", FALSE, + FALSE, FALSE, FALSE, + MOO_TEXT_STYLE_BACKGROUND); + + INSERT (DEF_STYLE_NORMAL, + NULL, NULL, FALSE, FALSE, FALSE, FALSE, 0); + + INSERT (DEF_STYLE_PREPROCESSOR, + "#008000", NULL, FALSE, FALSE, FALSE, FALSE, + MOO_TEXT_STYLE_FOREGROUND); + + INSERT (DEF_STYLE_STRING, + "#DD0000", NULL, FALSE, FALSE, FALSE, FALSE, + MOO_TEXT_STYLE_FOREGROUND); + + INSERT (DEF_STYLE_COMMENT, + "#808080", NULL, TRUE, FALSE, FALSE, FALSE, + MOO_TEXT_STYLE_FOREGROUND | MOO_TEXT_STYLE_ITALIC); + + INSERT (DEF_STYLE_BASE_N, + "#008080", NULL, FALSE, FALSE, FALSE, FALSE, + MOO_TEXT_STYLE_FOREGROUND); + + INSERT (DEF_STYLE_KEYWORD, + NULL, NULL, FALSE, TRUE, FALSE, FALSE, + MOO_TEXT_STYLE_BOLD); + + INSERT (DEF_STYLE_DATA_TYPE, + "#800000", NULL, FALSE, FALSE, FALSE, FALSE, + MOO_TEXT_STYLE_FOREGROUND); + + INSERT (DEF_STYLE_DECIMAL, + "#0000FF", NULL, FALSE, FALSE, FALSE, FALSE, + MOO_TEXT_STYLE_FOREGROUND); + + INSERT (DEF_STYLE_FLOAT, + "#800080", NULL, FALSE, FALSE, FALSE, FALSE, + MOO_TEXT_STYLE_FOREGROUND); + + INSERT (DEF_STYLE_CHAR, + "#FF00FF", NULL, FALSE, FALSE, FALSE, FALSE, + MOO_TEXT_STYLE_FOREGROUND); + + INSERT (DEF_STYLE_ALERT, + "#FFFFFF", "#FFCCCC", FALSE, TRUE, FALSE, FALSE, + MOO_TEXT_STYLE_FOREGROUND | MOO_TEXT_STYLE_BACKGROUND | + MOO_TEXT_STYLE_BOLD | MOO_TEXT_STYLE_ITALIC); + + INSERT (DEF_STYLE_FUNCTION, + "#000080", NULL, FALSE, FALSE, FALSE, FALSE, + MOO_TEXT_STYLE_FOREGROUND); + + INSERT (DEF_STYLE_ERROR, + "#FF0000", NULL, FALSE, FALSE, TRUE, FALSE, + MOO_TEXT_STYLE_FOREGROUND | MOO_TEXT_STYLE_UNDERLINE); + + INSERT (DEF_STYLE_OTHERS, + "#008000", NULL, FALSE, FALSE, FALSE, FALSE, + MOO_TEXT_STYLE_FOREGROUND); +} +#undef INSERT + + +void +_moo_text_style_scheme_get_color (MooTextStyleScheme *scheme, + MooTextColor color, + GdkColor *dest, + GdkScreen *screen) +{ + GtkSettings *settings; + GtkStyle *style; + + g_return_if_fail (scheme != NULL); + g_return_if_fail (dest != NULL); + g_return_if_fail (GDK_IS_SCREEN (screen)); + g_return_if_fail (color < MOO_TEXT_NUM_COLORS); + + if (scheme->text_colors[color]) + { + if (gdk_color_parse (scheme->text_colors[color], dest)) + return; + else + g_warning ("%s: could not parse color '%s'", G_STRLOC, + scheme->text_colors[color]); + } + + settings = gtk_settings_get_for_screen (screen); + + style = gtk_rc_get_style_by_paths (settings, NULL, NULL, MOO_TYPE_TEXT_VIEW); + + if (!style) + style = gtk_style_new (); + else + g_object_ref (style); + + switch (color) + { + case MOO_TEXT_COLOR_FG: + *dest = style->text[GTK_STATE_NORMAL]; + break; + + case MOO_TEXT_COLOR_BG: + case MOO_TEXT_COLOR_CUR_LINE: + *dest = style->base[GTK_STATE_NORMAL]; + break; + + case MOO_TEXT_COLOR_SEL_FG: + *dest = style->text[GTK_STATE_SELECTED]; + break; + + case MOO_TEXT_COLOR_SEL_BG: + *dest = style->base[GTK_STATE_SELECTED]; + break; + + case MOO_TEXT_NUM_COLORS: + g_assert_not_reached (); + } + + g_object_unref (style); +} + + +static void +prepend_default_style (const char *style_name, + G_GNUC_UNUSED gpointer whatever, + GSList **list) +{ + if (!strstr (style_name, "::")) + *list = g_slist_prepend (*list, g_strdup (style_name)); +} + +GSList* +moo_text_style_scheme_list_default (MooTextStyleScheme *scheme) +{ + GSList *list = NULL; + g_return_val_if_fail (MOO_IS_TEXT_STYLE_SCHEME (scheme), NULL); + g_hash_table_foreach (scheme->styles, (GHFunc) prepend_default_style, &list); + return g_slist_reverse (list); +} diff --git a/moo/mooedit/mootextstylescheme.h b/moo/mooedit/mootextstylescheme.h new file mode 100644 index 00000000..3a6f08da --- /dev/null +++ b/moo/mooedit/mootextstylescheme.h @@ -0,0 +1,92 @@ +/* + * mootextstylescheme.h + * + * Copyright (C) 2004-2005 by Yevgen Muntyan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * See COPYING file that comes with this distribution. + */ + +#ifndef __MOO_TEXT_STYLE_SCHEME_H__ +#define __MOO_TEXT_STYLE_SCHEME_H__ + +#include + +G_BEGIN_DECLS + + +#define MOO_TYPE_TEXT_STYLE_SCHEME (moo_text_style_scheme_get_type ()) +#define MOO_TEXT_STYLE_SCHEME(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MOO_TYPE_TEXT_STYLE_SCHEME, MooTextStyleScheme)) +#define MOO_TEXT_STYLE_SCHEME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOO_TYPE_TEXT_STYLE_SCHEME, MooTextStyleSchemeClass)) +#define MOO_IS_TEXT_STYLE_SCHEME(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MOO_TYPE_TEXT_STYLE_SCHEME)) +#define MOO_IS_TEXT_STYLE_SCHEME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOO_TYPE_TEXT_STYLE_SCHEME)) +#define MOO_TEXT_STYLE_SCHEME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOO_TYPE_TEXT_STYLE_SCHEME, MooTextStyleSchemeClass)) + +typedef struct _MooTextStyleScheme MooTextStyleScheme; +typedef struct _MooTextStyleSchemeClass MooTextStyleSchemeClass; + +typedef enum { + MOO_TEXT_COLOR_FG = 0, + MOO_TEXT_COLOR_BG, + MOO_TEXT_COLOR_SEL_FG, + MOO_TEXT_COLOR_SEL_BG, + MOO_TEXT_COLOR_CUR_LINE, + MOO_TEXT_NUM_COLORS +} MooTextColor; + + +struct _MooTextStyleScheme +{ + GObject parent; + + MooTextStyleScheme *base_scheme; + char *name; + char *text_colors[MOO_TEXT_NUM_COLORS]; + MooTextStyle *bracket_match; + MooTextStyle *bracket_mismatch; + GHashTable *styles; /* char* -> MooTextStyle* */ +}; + +struct _MooTextStyleSchemeClass +{ + GObjectClass parent_class; + + void (*changed) (MooTextStyleScheme *scheme); +}; + + +GType moo_text_style_scheme_get_type (void) G_GNUC_CONST; + +MooTextStyleScheme *moo_text_style_scheme_new_empty (const char *name, + MooTextStyleScheme *base); +MooTextStyleScheme *moo_text_style_scheme_new_default (void); + +MooTextStyleScheme *moo_text_style_scheme_copy (MooTextStyleScheme *scheme); + +GSList *moo_text_style_scheme_list_default (MooTextStyleScheme *scheme); + +void moo_text_style_scheme_compose (MooTextStyleScheme *scheme, + const char *language_name, + const char *style_name, + const MooTextStyle *style); +void moo_text_style_scheme_set (MooTextStyleScheme *scheme, + const char *language_name, + const char *style_name, + const MooTextStyle *style); +const MooTextStyle *moo_text_style_scheme_get (MooTextStyleScheme *scheme, + const char *language_name, + const char *style_name); + +void _moo_text_style_scheme_get_color (MooTextStyleScheme *scheme, + MooTextColor color, + GdkColor *dest, + GdkScreen *screen); + + +G_END_DECLS + +#endif /* __MOO_TEXT_STYLE_SCHEME_H__ */ diff --git a/moo/mooedit/mootextview.c b/moo/mooedit/mootextview.c index 07d544eb..d87ffe69 100644 --- a/moo/mooedit/mootextview.c +++ b/moo/mooedit/mootextview.c @@ -1168,8 +1168,9 @@ moo_text_view_expose (GtkWidget *widget, GtkTextIter start, end; int first_line, last_line; - if (view->priv->highlight_current_line && event->window == text_window) - moo_text_view_draw_current_line (text_view, event); + if (view->priv->highlight_current_line && + event->window == text_window && view->priv->current_line_gc) + moo_text_view_draw_current_line (text_view, event); if (event->window == text_window) { @@ -1268,3 +1269,95 @@ moo_text_view_set_cursor_color (MooTextView *view, g_free (rc_string); } + + +void +moo_text_view_set_lang (MooTextView *view, + MooLang *lang) +{ + g_return_if_fail (MOO_IS_TEXT_VIEW (view)); + moo_text_buffer_set_lang (get_moo_buffer (view), lang); +} + + +void +moo_text_view_apply_scheme (MooTextView *view, + MooTextStyleScheme *scheme) +{ + GdkColor color; + GdkColor *color_ptr; + MooTextBuffer *buffer; + GtkWidget *widget; + + g_return_if_fail (scheme != NULL); + g_return_if_fail (MOO_IS_TEXT_VIEW (view)); + + widget = GTK_WIDGET (view); + buffer = get_moo_buffer (view); + gtk_widget_ensure_style (widget); + + color_ptr = NULL; + if (scheme->text_colors[MOO_TEXT_COLOR_FG]) + { + if (gdk_color_parse (scheme->text_colors[MOO_TEXT_COLOR_FG], &color)) + color_ptr = &color; + else + g_warning ("%s: could not parse color '%s'", G_STRLOC, + scheme->text_colors[MOO_TEXT_COLOR_FG]); + } + gtk_widget_modify_text (widget, GTK_STATE_NORMAL, color_ptr); + gtk_widget_modify_text (widget, GTK_STATE_ACTIVE, color_ptr); + gtk_widget_modify_text (widget, GTK_STATE_PRELIGHT, color_ptr); + gtk_widget_modify_text (widget, GTK_STATE_INSENSITIVE, color_ptr); + moo_text_view_set_cursor_color (view, color_ptr); + + color_ptr = NULL; + if (scheme->text_colors[MOO_TEXT_COLOR_BG]) + { + if (gdk_color_parse (scheme->text_colors[MOO_TEXT_COLOR_BG], &color)) + color_ptr = &color; + else + g_warning ("%s: could not parse color '%s'", G_STRLOC, + scheme->text_colors[MOO_TEXT_COLOR_BG]); + } + gtk_widget_modify_base (widget, GTK_STATE_NORMAL, color_ptr); + gtk_widget_modify_base (widget, GTK_STATE_ACTIVE, color_ptr); + gtk_widget_modify_base (widget, GTK_STATE_PRELIGHT, color_ptr); + gtk_widget_modify_base (widget, GTK_STATE_INSENSITIVE, color_ptr); + + color_ptr = NULL; + if (scheme->text_colors[MOO_TEXT_COLOR_SEL_FG]) + { + if (gdk_color_parse (scheme->text_colors[MOO_TEXT_COLOR_SEL_FG], &color)) + color_ptr = &color; + else + g_warning ("%s: could not parse color '%s'", G_STRLOC, + scheme->text_colors[MOO_TEXT_COLOR_SEL_FG]); + } + gtk_widget_modify_text (widget, GTK_STATE_SELECTED, color_ptr); + + color_ptr = NULL; + if (scheme->text_colors[MOO_TEXT_COLOR_SEL_BG]) + { + if (gdk_color_parse (scheme->text_colors[MOO_TEXT_COLOR_SEL_BG], &color)) + color_ptr = &color; + else + g_warning ("%s: could not parse color '%s'", G_STRLOC, + scheme->text_colors[MOO_TEXT_COLOR_SEL_BG]); + } + gtk_widget_modify_base (widget, GTK_STATE_SELECTED, color_ptr); + + color_ptr = NULL; + if (scheme->text_colors[MOO_TEXT_COLOR_CUR_LINE]) + { + if (gdk_color_parse (scheme->text_colors[MOO_TEXT_COLOR_CUR_LINE], &color)) + color_ptr = &color; + else + g_warning ("%s: could not parse color '%s'", G_STRLOC, + scheme->text_colors[MOO_TEXT_COLOR_CUR_LINE]); + } + moo_text_view_set_current_line_color (view, color_ptr); + moo_text_view_set_highlight_current_line (view, color_ptr != NULL); + + moo_text_buffer_apply_scheme (buffer, scheme); +} diff --git a/moo/mooedit/mootextview.h b/moo/mooedit/mootextview.h index bea46457..53fe267f 100644 --- a/moo/mooedit/mootextview.h +++ b/moo/mooedit/mootextview.h @@ -17,6 +17,7 @@ #include #include +#include G_BEGIN_DECLS @@ -83,55 +84,60 @@ GType moo_text_selection_type_get_type (void) G_GNUC_CONST; MooTextView *moo_text_view_new (void); -void moo_text_view_select_all (MooTextView *view); +void moo_text_view_select_all (MooTextView *view); -gboolean moo_text_view_is_empty (MooTextView *view); +gboolean moo_text_view_is_empty (MooTextView *view); -char *moo_text_view_get_selection (MooTextView *view); -char *moo_text_view_get_text (MooTextView *view); -gboolean moo_text_view_has_selection (MooTextView *view); -gboolean moo_text_view_has_text (MooTextView *view); +char *moo_text_view_get_selection (MooTextView *view); +char *moo_text_view_get_text (MooTextView *view); +gboolean moo_text_view_has_selection (MooTextView *view); +gboolean moo_text_view_has_text (MooTextView *view); -void moo_text_view_delete_selection (MooTextView *view); +void moo_text_view_delete_selection (MooTextView *view); -gboolean moo_text_view_can_redo (MooTextView *view); -gboolean moo_text_view_can_undo (MooTextView *view); -void moo_text_view_redo (MooTextView *view); -void moo_text_view_undo (MooTextView *view); -void moo_text_view_start_not_undoable_action(MooTextView *view); -void moo_text_view_end_not_undoable_action (MooTextView *view); +gboolean moo_text_view_can_redo (MooTextView *view); +gboolean moo_text_view_can_undo (MooTextView *view); +void moo_text_view_redo (MooTextView *view); +void moo_text_view_undo (MooTextView *view); +void moo_text_view_start_not_undoable_action(MooTextView *view); +void moo_text_view_end_not_undoable_action (MooTextView *view); -void moo_text_view_find_interactive (MooTextView *view); -void moo_text_view_replace_interactive (MooTextView *view); -void moo_text_view_find_next_interactive (MooTextView *view); -void moo_text_view_find_prev_interactive (MooTextView *view); -void moo_text_view_goto_line (MooTextView *view, - int line); +void moo_text_view_find_interactive (MooTextView *view); +void moo_text_view_replace_interactive (MooTextView *view); +void moo_text_view_find_next_interactive (MooTextView *view); +void moo_text_view_find_prev_interactive (MooTextView *view); +void moo_text_view_goto_line (MooTextView *view, + int line); -void moo_text_view_set_font_from_string (MooTextView *view, - const char *font); +void moo_text_view_set_font_from_string (MooTextView *view, + const char *font); -MooIndenter *moo_text_view_get_indenter (MooTextView *view); -void moo_text_view_set_indenter (MooTextView *view, - MooIndenter *indenter); +MooIndenter *moo_text_view_get_indenter (MooTextView *view); +void moo_text_view_set_indenter (MooTextView *view, + MooIndenter *indenter); -void moo_text_view_move_cursor (MooTextView *view, - int line, - int character, - gboolean in_idle); +void moo_text_view_move_cursor (MooTextView *view, + int line, + int character, + gboolean in_idle); void moo_text_view_set_highlight_current_line - (MooTextView *view, - gboolean highlight); -void moo_text_view_set_current_line_color (MooTextView *view, - const GdkColor *color); -void moo_text_view_set_cursor_color (MooTextView *view, - const GdkColor *color); -void moo_text_view_set_show_tabs (MooTextView *view, - gboolean show); + (MooTextView *view, + gboolean highlight); +void moo_text_view_set_current_line_color (MooTextView *view, + const GdkColor *color); +void moo_text_view_set_cursor_color (MooTextView *view, + const GdkColor *color); +void moo_text_view_set_show_tabs (MooTextView *view, + gboolean show); +void moo_text_view_apply_scheme (MooTextView *view, + MooTextStyleScheme *scheme); -GtkTextTag *moo_text_view_lookup_tag (MooTextView *view, - const char *name); +GtkTextTag *moo_text_view_lookup_tag (MooTextView *view, + const char *name); + +void moo_text_view_set_lang (MooTextView *view, + MooLang *lang); G_END_DECLS diff --git a/moo/mooedit/syntax/c.lang b/moo/mooedit/syntax/c.lang index 6b4bb5ea..3c2548fb 100644 --- a/moo/mooedit/syntax/c.lang +++ b/moo/mooedit/syntax/c.lang @@ -165,4 +165,17 @@ + + /* This is a comment + * TODO: do something + */ + +#include <stdio.h> + +int main (int argc, char **argv) +{ + printf ("Hello world!"); + return 0; +} + diff --git a/moo/mooedit/syntax/gap.lang b/moo/mooedit/syntax/gap.lang index 686de494..eecd27b5 100644 --- a/moo/mooedit/syntax/gap.lang +++ b/moo/mooedit/syntax/gap.lang @@ -9161,4 +9161,18 @@ + + ## This is a comment +## TODO: do something + +InstallGlobalFunction("func", +func(arg) + local i; + + for i in [1..100] do + Print("Hello world!"); + od; +end); + + diff --git a/moo/mooedit/syntax/language.dtd b/moo/mooedit/syntax/language.dtd index 52dd93a8..8f199a89 100644 --- a/moo/mooedit/syntax/language.dtd +++ b/moo/mooedit/syntax/language.dtd @@ -8,7 +8,7 @@ - + + + + + diff --git a/moo/mooutils/Makefile.am b/moo/mooutils/Makefile.am index 1f22bcf1..be60c4b0 100644 --- a/moo/mooutils/Makefile.am +++ b/moo/mooutils/Makefile.am @@ -39,6 +39,7 @@ utilsinclude_HEADERS = \ eggregex.h \ mooaccelbutton.h \ moobigpaned.h \ + moocellrenderercolor.h \ mooclosure.h \ moocombo.h \ mooentry.h \ @@ -76,6 +77,7 @@ libmooutils_la_SOURCES = \ mooaccelbutton.c \ mooaccelbutton-glade.h \ moobigpaned.c \ + moocellrenderercolor.c \ mooclosure.c \ moocombo.c \ moocompat.c \ diff --git a/moo/mooutils/moocellrenderercolor.c b/moo/mooutils/moocellrenderercolor.c new file mode 100644 index 00000000..a735ec11 --- /dev/null +++ b/moo/mooutils/moocellrenderercolor.c @@ -0,0 +1,326 @@ +/* + * moocellrenderercolor.c + * + * Copyright (C) 2004-2005 by Yevgen Muntyan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * See COPYING file that comes with this distribution. + */ + +#include "mooutils/moocellrenderercolor.h" +#include "mooutils/moomarshals.h" +#include + +#define CELL_MIN_WIDTH 20 +#define CELL_MIN_HEIGHT 12 +#define CELL_BORDER_WIDTH 1 + + +static void moo_cell_renderer_color_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec); +static void moo_cell_renderer_color_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec); +static void moo_cell_renderer_color_get_size (GtkCellRenderer *cell, + GtkWidget *widget, + GdkRectangle *rectangle, + gint *x_offset, + gint *y_offset, + gint *width, + gint *height); +static void moo_cell_renderer_color_render (GtkCellRenderer *cell, + GdkDrawable *window, + GtkWidget *widget, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GdkRectangle *expose_area, + GtkCellRendererState flags); +static gboolean moo_cell_renderer_color_activate (GtkCellRenderer *cell, + GdkEvent *event, + GtkWidget *widget, + const gchar *path, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GtkCellRendererState flags); + + +enum { + PROP_0, + PROP_COLOR, + PROP_COLOR_SET, + PROP_ACTIVATABLE +}; + +enum { + COLOR_SET, + NUM_SIGNALS +}; + +static guint signals[NUM_SIGNALS]; + +G_DEFINE_TYPE (MooCellRendererColor, moo_cell_renderer_color, GTK_TYPE_CELL_RENDERER) + + +static void +moo_cell_renderer_color_class_init (MooCellRendererColorClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass); + + object_class->get_property = moo_cell_renderer_color_get_property; + object_class->set_property = moo_cell_renderer_color_set_property; + + cell_class->get_size = moo_cell_renderer_color_get_size; + cell_class->render = moo_cell_renderer_color_render; + cell_class->activate = moo_cell_renderer_color_activate; + + g_object_class_install_property (object_class, + PROP_COLOR, + g_param_spec_boxed ("color", + "color", + "color", + GDK_TYPE_COLOR, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, + PROP_ACTIVATABLE, + g_param_spec_boolean ("activatable", + "activatable", + "activatable", + FALSE, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, + PROP_COLOR_SET, + g_param_spec_boolean ("color-set", + "color-set", + "color-set", + FALSE, + G_PARAM_READWRITE)); + + signals[COLOR_SET] = + g_signal_new ("color-set", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MooCellRendererColorClass, color_set), + NULL, NULL, + _moo_marshal_VOID__BOXED, + G_TYPE_NONE, 1, + GDK_TYPE_COLOR); +} + + +static void +moo_cell_renderer_color_init (MooCellRendererColor *cell) +{ + cell->color_set = FALSE; + cell->activatable = FALSE; + GTK_CELL_RENDERER(cell)->mode = GTK_CELL_RENDERER_MODE_ACTIVATABLE; + GTK_CELL_RENDERER(cell)->xpad = 2; + GTK_CELL_RENDERER(cell)->ypad = 2; +} + + +static void +moo_cell_renderer_color_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + MooCellRendererColor *cell = MOO_CELL_RENDERER_COLOR (object); + + switch (param_id) + { + case PROP_COLOR: + g_value_set_boxed (value, &cell->color); + break; + + case PROP_COLOR_SET: + g_value_set_boolean (value, cell->color_set ? TRUE : FALSE); + break; + + case PROP_ACTIVATABLE: + g_value_set_boolean (value, cell->activatable ? TRUE : FALSE); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + + +static void +moo_cell_renderer_color_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + GdkColor *color; + MooCellRendererColor *cell = MOO_CELL_RENDERER_COLOR (object); + + switch (param_id) + { + case PROP_COLOR: + color = g_value_get_boxed (value); + if (color) + { + cell->color = *color; + cell->color_set = TRUE; + } + else + { + cell->color_set = FALSE; + } + break; + + case PROP_COLOR_SET: + cell->color_set = g_value_get_boolean (value) ? TRUE : FALSE; + break; + + case PROP_ACTIVATABLE: + cell->activatable = g_value_get_boolean (value) ? TRUE : FALSE; + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + + +GtkCellRenderer * +moo_cell_renderer_color_new (void) +{ + return g_object_new (MOO_TYPE_CELL_RENDERER_COLOR, NULL); +} + + +static void +moo_cell_renderer_color_get_size (GtkCellRenderer *gtkcell, + GtkWidget *widget, + GdkRectangle *cell_area, + gint *x_offset, + gint *y_offset, + gint *width, + gint *height) +{ + if (x_offset) + *x_offset = 0; + if (y_offset) + *y_offset = 0; + if (width) + *width = 2 * gtkcell->xpad + 2 * CELL_BORDER_WIDTH + CELL_MIN_WIDTH; + if (height) + *height = 2 * gtkcell->ypad + 2 * CELL_BORDER_WIDTH + CELL_MIN_HEIGHT; +} + + +static void +moo_cell_renderer_color_render (GtkCellRenderer *gtkcell, + GdkWindow *window, + GtkWidget *widget, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GdkRectangle *expose_area, + GtkCellRendererState flags) + +{ + MooCellRendererColor *cell = MOO_CELL_RENDERER_COLOR (gtkcell); + GdkRectangle rect; + GdkGC *gc; + GdkColor *color; + + rect = *cell_area; + rect.x += gtkcell->xpad; + rect.y += gtkcell->ypad; + rect.width -= gtkcell->xpad * 2; + rect.height -= gtkcell->ypad * 2; + + if (cell->color_set) + { + static GdkGCValues values; + GdkColormap *colormap; + + colormap = gtk_widget_get_colormap (widget); + g_return_if_fail (colormap != NULL); + gdk_colormap_alloc_color (colormap, &cell->color, TRUE, TRUE); + + values.foreground = cell->color; + + gc = gdk_gc_new_with_values (window, &values, GDK_GC_FOREGROUND); + gdk_draw_rectangle (window, gc, TRUE, rect.x, rect.y, + rect.width, rect.height); + g_object_unref (gc); + } + + if (flags & GTK_CELL_RENDERER_SELECTED) + gc = widget->style->text_gc[GTK_STATE_SELECTED]; + else if (flags & GTK_CELL_RENDERER_INSENSITIVE) + gc = widget->style->text_gc[GTK_STATE_INSENSITIVE]; + else + gc = widget->style->text_gc[GTK_STATE_NORMAL]; + + gdk_draw_rectangle (window, gc, FALSE, rect.x, rect.y, + rect.width - 1, rect.height - 1); + + if (!cell->color_set) + gdk_draw_line (window, gc, + rect.x, + rect.y + rect.height - 1, + rect.x + rect.width - 1, + rect.y); + +} + + +static gboolean +moo_cell_renderer_color_activate (GtkCellRenderer *gtkcell, + GdkEvent *event, + GtkWidget *widget, + const gchar *path, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GtkCellRendererState flags) +{ + MooCellRendererColor *cell = MOO_CELL_RENDERER_COLOR (gtkcell); + + if (cell->activatable) + { + GtkWidget *dialog, *toplevel; + GtkColorSelectionDialog *color_dialog; + GtkColorSelection *colorsel; + GdkColor color; + int response; + + dialog = gtk_color_selection_dialog_new (NULL); + color_dialog = GTK_COLOR_SELECTION_DIALOG (dialog); + colorsel = GTK_COLOR_SELECTION (color_dialog->colorsel); + + gtk_color_selection_set_current_color (colorsel, &cell->color); + + toplevel = gtk_widget_get_toplevel (widget); + if (GTK_WIDGET_TOPLEVEL (toplevel)) + gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel)); + response = gtk_dialog_run (GTK_DIALOG (dialog)); + + if (response == GTK_RESPONSE_OK) + gtk_color_selection_get_current_color (colorsel, &color); + + gtk_widget_destroy (dialog); + + if (response == GTK_RESPONSE_OK) + g_signal_emit (cell, signals[COLOR_SET], 0, &color); + + return TRUE; + } + + return FALSE; +} diff --git a/moo/mooutils/moocellrenderercolor.h b/moo/mooutils/moocellrenderercolor.h new file mode 100644 index 00000000..43e03687 --- /dev/null +++ b/moo/mooutils/moocellrenderercolor.h @@ -0,0 +1,55 @@ +/* + * moocellrenderercolor.h + * + * Copyright (C) 2004-2005 by Yevgen Muntyan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * See COPYING file that comes with this distribution. + */ + +#ifndef __MOO_CELL_RENDERER_COLOR_H__ +#define __MOO_CELL_RENDERER_COLOR_H__ + +#include + +G_BEGIN_DECLS + + +#define MOO_TYPE_CELL_RENDERER_COLOR (moo_cell_renderer_color_get_type ()) +#define MOO_CELL_RENDERER_COLOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MOO_TYPE_CELL_RENDERER_COLOR, MooCellRendererColor)) +#define MOO_CELL_RENDERER_COLOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOO_TYPE_CELL_RENDERER_COLOR, MooCellRendererColorClass)) +#define MOO_IS_CELL_RENDERER_COLOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MOO_TYPE_CELL_RENDERER_COLOR)) +#define MOO_IS_CELL_RENDERER_COLOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOO_TYPE_CELL_RENDERER_COLOR)) +#define MOO_CELL_RENDERER_COLOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOO_TYPE_CELL_RENDERER_COLOR, MooCellRendererColorClass)) + +typedef struct _MooCellRendererColor MooCellRendererColor; +typedef struct _MooCellRendererColorClass MooCellRendererColorClass; + +struct _MooCellRendererColor +{ + GtkCellRenderer parent; + + GdkColor color; + guint color_set : 1; + guint activatable : 1; +}; + +struct _MooCellRendererColorClass +{ + GtkCellRendererClass parent_class; + + void (*color_set) (MooCellRendererColor *cell, + GdkColor *color); +}; + +GType moo_cell_renderer_color_get_type (void) G_GNUC_CONST; +GtkCellRenderer *moo_cell_renderer_color_new (void); + + +G_END_DECLS + +#endif /* __MOO_CELL_RENDERER_COLOR_H__ */ diff --git a/moo/mooutils/moohistorylist.c b/moo/mooutils/moohistorylist.c index 7eadc59a..b647aa5d 100644 --- a/moo/mooutils/moohistorylist.c +++ b/moo/mooutils/moohistorylist.c @@ -519,13 +519,17 @@ char* moo_history_list_display_basename (const char *filename, G_GNUC_UNUSED gpointer data) { - char *basename; + char *basename, *display; g_return_val_if_fail (filename != NULL, NULL); basename = g_path_get_basename (filename); g_return_val_if_fail (basename != NULL, NULL); - return g_filename_display_name (basename); + + display = g_filename_display_name (basename); + + g_free (basename); + return display; } diff --git a/moo/mooutils/moonotebook.c b/moo/mooutils/moonotebook.c index 3c437054..7ed30c30 100644 --- a/moo/mooutils/moonotebook.c +++ b/moo/mooutils/moonotebook.c @@ -978,24 +978,26 @@ static void moo_notebook_map (GtkWidget *widget) GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED); if (nb->priv->tabs_visible) + { gdk_window_show (nb->priv->tab_window); - if (nb->priv->action_widgets[LEFT] && - GTK_WIDGET_VISIBLE (nb->priv->action_widgets[LEFT])) + if (nb->priv->action_widgets[LEFT] && + GTK_WIDGET_VISIBLE (nb->priv->action_widgets[LEFT])) gtk_widget_map (nb->priv->action_widgets[LEFT]); - if (nb->priv->action_widgets[RIGHT] && - GTK_WIDGET_VISIBLE (nb->priv->action_widgets[RIGHT])) + if (nb->priv->action_widgets[RIGHT] && + GTK_WIDGET_VISIBLE (nb->priv->action_widgets[RIGHT])) gtk_widget_map (nb->priv->action_widgets[RIGHT]); - if (nb->priv->arrows_visible) - gtk_widget_map (nb->priv->arrows); + if (nb->priv->arrows_visible) + gtk_widget_map (nb->priv->arrows); - VISIBLE_FOREACH_START (nb, page) - { - gtk_widget_map (page->label->widget); + VISIBLE_FOREACH_START (nb, page) + { + gtk_widget_map (page->label->widget); + } + VISIBLE_FOREACH_END; } - VISIBLE_FOREACH_END; if (nb->priv->current_page) gtk_widget_map (nb->priv->current_page->child); @@ -1250,7 +1252,7 @@ static void child_visible_notify (GtkWidget *child, } else { - gtk_widget_show (page->label->widget); + gtk_widget_hide (page->label->widget); if (nb->priv->current_page == page) { int n; diff --git a/moo/mooutils/mooprefsdialog.c b/moo/mooutils/mooprefsdialog.c index 99f40d25..d1c6991f 100644 --- a/moo/mooutils/mooprefsdialog.c +++ b/moo/mooutils/mooprefsdialog.c @@ -16,9 +16,14 @@ #include "mooutils/moocompat.h" -/**************************************************************************/ -/* MooPrefsDialog class implementation - */ +enum { + ICON_COLUMN, + ICON_ID_COLUMN, + LABEL_COLUMN, + PAGE_COLUMN, + N_COLUMNS +}; + static void moo_prefs_dialog_set_property (GObject *object, guint prop_id, @@ -30,6 +35,8 @@ static void moo_prefs_dialog_get_property (GObject *object, GParamSpec *pspec); static void moo_prefs_dialog_destroy (GtkObject *object); +static void moo_prefs_dialog_response (GtkDialog *dialog, + int response); static void moo_prefs_dialog_init_sig (MooPrefsDialog *dialog); static void moo_prefs_dialog_apply (MooPrefsDialog *dialog); @@ -63,11 +70,12 @@ static void moo_prefs_dialog_class_init (MooPrefsDialogClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (klass); + GtkDialogClass *dialog_class = GTK_DIALOG_CLASS (klass); gobject_class->set_property = moo_prefs_dialog_set_property; gobject_class->get_property = moo_prefs_dialog_get_property; - gtkobject_class->destroy = moo_prefs_dialog_destroy; + dialog_class->response = moo_prefs_dialog_response; klass->init = moo_prefs_dialog_init_sig; klass->apply = moo_prefs_dialog_apply; @@ -127,7 +135,7 @@ static void moo_prefs_dialog_init (MooPrefsDialog *dialog) scrolledwindow = gtk_scrolled_window_new (NULL, NULL); gtk_widget_show (scrolledwindow); - gtk_box_pack_start (GTK_BOX (hbox), scrolledwindow, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), scrolledwindow, FALSE, FALSE, 0); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow), GTK_SHADOW_IN); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); @@ -146,6 +154,23 @@ static void moo_prefs_dialog_init (MooPrefsDialog *dialog) } +static gboolean +destroy_page (GtkTreeModel *model, + G_GNUC_UNUSED GtkTreePath *path, + GtkTreeIter *iter) +{ + GtkWidget *page = NULL; + + gtk_tree_model_get (model, iter, PAGE_COLUMN, &page, -1); + g_return_val_if_fail (page != NULL, FALSE); + + g_object_set_data (G_OBJECT (page), "moo-prefs-dialog-row", NULL); + gtk_widget_destroy (page); + g_object_unref (page); + + return FALSE; +} + static void moo_prefs_dialog_destroy (GtkObject *object) { @@ -153,8 +178,9 @@ moo_prefs_dialog_destroy (GtkObject *object) if (dialog->store) { - dialog->notebook = NULL; - dialog->pages_list = NULL; + gtk_tree_view_set_model (dialog->pages_list, NULL); + gtk_tree_model_foreach (GTK_TREE_MODEL (dialog->store), + (GtkTreeModelForeachFunc) destroy_page, NULL); g_object_unref (dialog->store); dialog->store = NULL; } @@ -163,14 +189,6 @@ moo_prefs_dialog_destroy (GtkObject *object) } -enum { - ICON_COLUMN, - ICON_ID_COLUMN, - LABEL_COLUMN, - PAGE_COLUMN, - N_COLUMNS -}; - static void setup_pages_list (MooPrefsDialog *dialog) { @@ -228,7 +246,7 @@ pages_list_selection_changed (MooPrefsDialog *dialog, gtk_tree_model_get (model, &iter, PAGE_COLUMN, &page, -1); g_return_if_fail (page != NULL); gtk_notebook_set_current_page (dialog->notebook, - gtk_notebook_page_num (dialog->notebook, GTK_WIDGET (page))); + gtk_notebook_page_num (dialog->notebook, GTK_WIDGET (page))); g_object_unref (page); } else @@ -289,15 +307,17 @@ static void moo_prefs_dialog_get_property (GObject *object, /* MooPrefsDialog methods */ -GtkWidget* moo_prefs_dialog_new (const char *title) +GtkWidget* +moo_prefs_dialog_new (const char *title) { return GTK_WIDGET (g_object_new (MOO_TYPE_PREFS_DIALOG, "title", title, NULL)); } -void moo_prefs_dialog_run (MooPrefsDialog *dialog, - GtkWidget *parent) +void +moo_prefs_dialog_run (MooPrefsDialog *dialog, + GtkWidget *parent) { GtkWindow *parent_window = NULL; @@ -310,27 +330,35 @@ void moo_prefs_dialog_run (MooPrefsDialog *dialog, } g_signal_emit_by_name (dialog, "init"); + gtk_window_present (GTK_WINDOW (dialog)); +} - while (TRUE) + +static void +moo_prefs_dialog_response (GtkDialog *dialog, + int response) +{ + G_GNUC_UNUSED GtkWindow *parent; + + switch (response) { - int res = gtk_dialog_run (GTK_DIALOG (dialog)); - - if (res == GTK_RESPONSE_OK || res == GTK_RESPONSE_APPLY) + case GTK_RESPONSE_APPLY: g_signal_emit_by_name (dialog, "apply"); + break; - if (res != GTK_RESPONSE_APPLY) - { - if (dialog->hide_on_delete) + case GTK_RESPONSE_OK: + g_signal_emit_by_name (dialog, "apply"); + /* fallthrough */ + default: + if (MOO_PREFS_DIALOG(dialog)->hide_on_delete) gtk_widget_hide (GTK_WIDGET (dialog)); else gtk_widget_destroy (GTK_WIDGET (dialog)); - -#ifdef __WIN32__ /* TODO: why? */ - if (parent_window) gtk_window_present (parent_window); -#endif /* __WIN32__ */ - - return; - } +#ifdef __WIN32__ + parent = gtk_window_get_transient_for (GTK_WINDOW (window)); + if (parent) + gtk_window_present (parent); +#endif } } @@ -406,7 +434,7 @@ moo_prefs_dialog_insert_page (MooPrefsDialog *dialog, } gtk_widget_show (page); - gtk_notebook_append_page (dialog->notebook, page, NULL); + gtk_notebook_insert_page (dialog->notebook, page, NULL, -1); g_object_get (page, "label", &label, diff --git a/moo/mooutils/mooprefsdialogpage.c b/moo/mooutils/mooprefsdialogpage.c index e3198ade..c8005025 100644 --- a/moo/mooutils/mooprefsdialogpage.c +++ b/moo/mooutils/mooprefsdialogpage.c @@ -326,6 +326,7 @@ moo_prefs_dialog_page_new_from_xml (const char *label, return NULL; } + /*XXX*/ page = moo_glade_xml_get_widget (xml, page_id); page->xml = xml; diff --git a/moo/mooutils/moowindow.c b/moo/mooutils/moowindow.c index a92e504b..1268a232 100644 --- a/moo/mooutils/moowindow.c +++ b/moo/mooutils/moowindow.c @@ -350,6 +350,13 @@ static void moo_window_finalize (GObject *object) { MooWindow *window = MOO_WINDOW(object); + if (window->priv->ui_xml) + g_object_unref (window->priv->ui_xml); + if (window->priv->actions) + g_object_unref (window->priv->actions); + + g_free (window->priv->name); + g_free (window->priv->id); g_free (window->priv->menubar_ui_name); g_free (window->priv->toolbar_ui_name);