commit
87cd264acf
51
configure.ac
51
configure.ac
|
@ -94,49 +94,25 @@ dnl ================================================================
|
|||
dnl spell plugins checks: enchant and iso-codes
|
||||
dnl ================================================================
|
||||
|
||||
ENCHANT_REQUIRED=1.2.0
|
||||
ISO_CODES_REQUIRED=0.35
|
||||
GSPELL_REQUIRED=0.2.5
|
||||
|
||||
AC_ARG_ENABLE([spell],
|
||||
AS_HELP_STRING([--disable-spell],[Disable spell plugin (default: enabled)]),
|
||||
[enable_enchant=$enableval],
|
||||
[enable_enchant=yes])
|
||||
[enable_spell=$enableval],
|
||||
[enable_spell=yes])
|
||||
|
||||
if test "x$enable_enchant" = "xyes" ; then
|
||||
if test "x$enable_spell" = "xyes" ; then
|
||||
|
||||
PKG_CHECK_MODULES(ENCHANT, enchant >= $ENCHANT_REQUIRED, \
|
||||
have_enchant=yes, have_enchant=no)
|
||||
PKG_CHECK_MODULES(GSPELL, gspell-1 >= $GSPELL_REQUIRED, \
|
||||
have_gspell=yes, have_gspell=no)
|
||||
|
||||
if test "x$have_enchant" = "xyes"; then
|
||||
|
||||
PKG_CHECK_EXISTS([iso-codes >= $ISO_CODES_REQUIRED],
|
||||
[have_iso_codes=yes],[have_iso_codes=no])
|
||||
|
||||
if test "x$have_iso_codes" = "xyes"; then
|
||||
AC_MSG_CHECKING([whether iso-codes has iso-639 and iso-3166 domains])
|
||||
if $PKG_CONFIG --variable=domains iso-codes | grep 639 > /dev/null && \
|
||||
$PKG_CONFIG --variable=domains iso-codes | grep 3166 > /dev/null ; then
|
||||
result=yes
|
||||
else
|
||||
result=no
|
||||
have_iso_codes=no
|
||||
fi
|
||||
AC_MSG_RESULT([$result])
|
||||
fi
|
||||
|
||||
if test "x$have_iso_codes" = "xyes"; then
|
||||
AC_DEFINE_UNQUOTED([ISO_CODES_PREFIX],["`$PKG_CONFIG --variable=prefix iso-codes`"],[ISO codes prefix])
|
||||
AC_DEFINE([HAVE_ISO_CODES],[1],[Define if you have the iso-codes package])
|
||||
else
|
||||
AC_MSG_ERROR([iso-codes is required to build the spell plugin. Use --disable-spell to build without spell plugin.])
|
||||
fi
|
||||
else
|
||||
enable_enchant=no
|
||||
AC_MSG_ERROR([Enchant library not found or too old. Use --disable-spell to build without spell plugin.])
|
||||
if test "x$have_gspell" = "xno"; then
|
||||
enable_spell=no
|
||||
AC_MSG_ERROR([gspell library not found or too old. Use --disable-spell to build without spell plugin.])
|
||||
fi
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(ENABLE_ENCHANT, test x"$enable_enchant" = "xyes")
|
||||
AM_CONDITIONAL(ENABLE_SPELL, test x"$enable_spell" = "xyes")
|
||||
|
||||
dnl ================================================================
|
||||
dnl Start of pkg-config checks
|
||||
|
@ -149,10 +125,11 @@ PKG_CHECK_MODULES(XED, [
|
|||
$GMODULE_ADD
|
||||
gthread-2.0 >= 2.13.0
|
||||
gio-2.0 >= 2.40.0
|
||||
gtk+-3.0 >= 3.18.0
|
||||
gtksourceview-3.0 >= 3.18.0
|
||||
gtk+-3.0 >= 3.19.3
|
||||
gtksourceview-3.0 >= 3.19.0
|
||||
libpeas-1.0 >= 1.12.0
|
||||
libpeas-gtk-1.0 >= 1.12.0
|
||||
xapp
|
||||
])
|
||||
|
||||
PKG_CHECK_MODULES(X11, [x11])
|
||||
|
@ -254,7 +231,7 @@ Configuration:
|
|||
|
||||
Source code location: ${srcdir}
|
||||
Compiler: ${CC}
|
||||
Spell Plugin enabled: $enable_enchant
|
||||
Spell Plugin enabled: $enable_spell
|
||||
Gvfs metadata enabled: $enable_gvfs_metadata
|
||||
GObject Introspection: ${enable_introspection}
|
||||
"
|
||||
|
|
|
@ -7,13 +7,13 @@ Build-Depends: autotools-dev,
|
|||
gobject-introspection,
|
||||
gtk-doc-tools,
|
||||
intltool,
|
||||
iso-codes,
|
||||
libenchant-dev,
|
||||
libgirepository1.0-dev,
|
||||
libglib2.0-dev,
|
||||
libgspell-1-dev,
|
||||
libgtk-3-dev,
|
||||
libgtksourceview-3.0-dev,
|
||||
libpeas-dev,
|
||||
libxapp-dev,
|
||||
libsm-dev,
|
||||
libx11-dev,
|
||||
libxml2-dev,
|
||||
|
@ -145,4 +145,4 @@ Description: Text editor (documentation files)
|
|||
includes support for spell checking, comparing files, viewing CVS
|
||||
ChangeLogs, and adjusting indentation levels.
|
||||
.
|
||||
This package contains the documentation files.
|
||||
This package contains the documentation files.
|
||||
|
|
|
@ -14,7 +14,7 @@ override_dh_auto_configure:
|
|||
# upstream tarball is without configure. autogen.sh will create it
|
||||
NOCONFIGURE=1 ./autogen.sh
|
||||
dh_auto_configure $(DHFLAGS) -- \
|
||||
--disable-silent-rules \
|
||||
--enable-silent-rules \
|
||||
--libexecdir=/usr/lib/ \
|
||||
--enable-gtk-doc
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ SUBDIRS = \
|
|||
time \
|
||||
trailsave
|
||||
|
||||
if ENABLE_ENCHANT
|
||||
if ENABLE_SPELL
|
||||
SUBDIRS += spell
|
||||
endif
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ plugindir = $(XED_PLUGINS_LIBS_DIR)
|
|||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir) \
|
||||
$(XED_CFLAGS) \
|
||||
$(ENCHANT_CFLAGS) \
|
||||
$(GSPELL_CFLAGS) \
|
||||
$(WARN_CFLAGS) \
|
||||
$(DISABLE_DEPRECATED_CFLAGS)
|
||||
|
||||
|
@ -17,25 +17,13 @@ plugin_LTLIBRARIES = libspell.la
|
|||
libspell_la_SOURCES = \
|
||||
xed-spell-plugin.c \
|
||||
xed-spell-plugin.h \
|
||||
xed-spell-checker.c \
|
||||
xed-spell-checker.h \
|
||||
xed-spell-checker-dialog.c \
|
||||
xed-spell-checker-dialog.h \
|
||||
xed-spell-checker-language.c \
|
||||
xed-spell-checker-language.h \
|
||||
xed-spell-language-dialog.c \
|
||||
xed-spell-language-dialog.h \
|
||||
xed-automatic-spell-checker.c \
|
||||
xed-automatic-spell-checker.h \
|
||||
xed-spell-utils.c \
|
||||
xed-spell-utils.h \
|
||||
$(BUILT_SOURCES)
|
||||
|
||||
libspell_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS)
|
||||
libspell_la_LIBADD = $(XED_LIBS) $(ENCHANT_LIBS)
|
||||
libspell_la_LIBADD = $(XED_LIBS) $(GSPELL_LIBS)
|
||||
|
||||
uidir = $(XED_PLUGINS_DATA_DIR)/spell
|
||||
ui_DATA = spell-checker.ui languages-dialog.ui xed-spell-setup-dialog.ui
|
||||
ui_DATA = xed-spell-setup-dialog.ui
|
||||
|
||||
xed-spell-marshal.h: xed-spell-marshal.list $(GLIB_GENMARSHAL)
|
||||
$(AM_V_GEN) $(GLIB_GENMARSHAL) $< --header --prefix=xed_marshal > $@
|
||||
|
|
|
@ -1,140 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.18.3 -->
|
||||
<!--*- mode: xml -*-->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.10"/>
|
||||
<object class="GtkDialog" id="dialog">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">Set language</property>
|
||||
<property name="modal">True</property>
|
||||
<property name="destroy_with_parent">True</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkBox" id="dialog-vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">2</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox" id="dialog-action_area1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="helpbutton1">
|
||||
<property name="label">gtk-help</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="closebutton1">
|
||||
<property name="label">gtk-cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button1">
|
||||
<property name="label">gtk-ok</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="content">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">11</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Select the _language of the current document.</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="mnemonic_widget">languages_treeview</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="scrolledwindow1">
|
||||
<property name="height_request">180</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="shadow_type">etched-in</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="languages_treeview">
|
||||
<property name="height_request">180</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_visible">False</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection" id="treeview-selection1"/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<action-widgets>
|
||||
<action-widget response="-11">helpbutton1</action-widget>
|
||||
<action-widget response="-6">closebutton1</action-widget>
|
||||
<action-widget response="-5">button1</action-widget>
|
||||
</action-widgets>
|
||||
</object>
|
||||
</interface>
|
|
@ -1,369 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.18.3 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.10"/>
|
||||
<object class="GtkWindow" id="check_spelling_window">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="destroy_with_parent">True</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<property name="skip_taskbar_hint">True</property>
|
||||
<property name="startup_id">Check spelling</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="content">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="border_width">12</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="row_spacing">6</property>
|
||||
<property name="column_spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Misspelled word:</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="misspelled_word_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">word</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Change _to:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="box1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkEntry" id="word_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="check_word_button">
|
||||
<property name="label" translatable="yes">Check _Word</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="row_spacing">6</property>
|
||||
<property name="column_spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">_Suggestions:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="scrolledwindow1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="suggestions_list">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_visible">False</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection" id="treeview-selection1"/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="box2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_bottom">6</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="row_spacing">12</property>
|
||||
<property name="column_spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="ignore_button">
|
||||
<property name="label" translatable="yes">_Ignore</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="ignore_all_button">
|
||||
<property name="label" translatable="yes">Ignore _All</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="change_button">
|
||||
<property name="label" translatable="yes">Cha_nge</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="change_all_button">
|
||||
<property name="label" translatable="yes">Change A_ll</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="box3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">11</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label4">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">User dictionary:</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="box7">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">6</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="add_word_button">
|
||||
<property name="label" translatable="yes">Add w_ord</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="box4">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label5">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Language:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="language_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Language</property>
|
||||
<property name="use_markup">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButtonBox" id="buttonbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="close_button">
|
||||
<property name="label" translatable="yes">_Close</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="use_underline">True</property>
|
||||
<style>
|
||||
<class name="text-button"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
|
@ -1,967 +0,0 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* xed-automatic-spell-checker.c
|
||||
* This file is part of xed
|
||||
*
|
||||
* Copyright (C) 2002 Paolo Maggi
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the xed Team, 2002. See the AUTHORS file for a
|
||||
* list of people on the xed Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*/
|
||||
|
||||
/* This is a modified version of gtkspell 2.0.5 (gtkspell.sf.net) */
|
||||
/* gtkspell - a spell-checking addon for GTK's TextView widget
|
||||
* Copyright (c) 2002 Evan Martin.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "xed-automatic-spell-checker.h"
|
||||
#include "xed-spell-utils.h"
|
||||
|
||||
struct _XedAutomaticSpellChecker
|
||||
{
|
||||
XedDocument *doc;
|
||||
GSList *views;
|
||||
|
||||
GtkTextMark *mark_insert_start;
|
||||
GtkTextMark *mark_insert_end;
|
||||
gboolean deferred_check;
|
||||
|
||||
GtkTextTag *tag_highlight;
|
||||
GtkTextMark *mark_click;
|
||||
|
||||
XedSpellChecker *spell_checker;
|
||||
};
|
||||
|
||||
static GQuark automatic_spell_checker_id = 0;
|
||||
static GQuark suggestion_id = 0;
|
||||
|
||||
static void xed_automatic_spell_checker_free_internal (XedAutomaticSpellChecker *spell);
|
||||
|
||||
static void
|
||||
view_destroy (XedView *view,
|
||||
XedAutomaticSpellChecker *spell)
|
||||
{
|
||||
xed_automatic_spell_checker_detach_view (spell, view);
|
||||
}
|
||||
|
||||
static void
|
||||
check_word (XedAutomaticSpellChecker *spell,
|
||||
GtkTextIter *start,
|
||||
GtkTextIter *end)
|
||||
{
|
||||
gchar *word;
|
||||
|
||||
word = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (spell->doc), start, end, FALSE);
|
||||
|
||||
/*
|
||||
g_print ("Check word: %s [%d - %d]\n", word, gtk_text_iter_get_offset (start),
|
||||
gtk_text_iter_get_offset (end));
|
||||
*/
|
||||
|
||||
if (!xed_spell_checker_check_word (spell->spell_checker, word, -1))
|
||||
{
|
||||
/*
|
||||
g_print ("Apply tag: [%d - %d]\n", gtk_text_iter_get_offset (start),
|
||||
gtk_text_iter_get_offset (end));
|
||||
*/
|
||||
gtk_text_buffer_apply_tag (GTK_TEXT_BUFFER (spell->doc), spell->tag_highlight, start, end);
|
||||
}
|
||||
|
||||
g_free (word);
|
||||
}
|
||||
|
||||
static void
|
||||
check_range (XedAutomaticSpellChecker *spell,
|
||||
GtkTextIter start,
|
||||
GtkTextIter end,
|
||||
gboolean force_all)
|
||||
{
|
||||
/* we need to "split" on word boundaries.
|
||||
* luckily, Pango knows what "words" are
|
||||
* so we don't have to figure it out. */
|
||||
|
||||
GtkTextIter wstart;
|
||||
GtkTextIter wend;
|
||||
GtkTextIter cursor;
|
||||
GtkTextIter precursor;
|
||||
gboolean highlight;
|
||||
|
||||
/*
|
||||
g_print ("Check range: [%d - %d]\n", gtk_text_iter_get_offset (&start),
|
||||
gtk_text_iter_get_offset (&end));
|
||||
*/
|
||||
|
||||
if (gtk_text_iter_inside_word (&end))
|
||||
{
|
||||
gtk_text_iter_forward_word_end (&end);
|
||||
}
|
||||
|
||||
if (!gtk_text_iter_starts_word (&start))
|
||||
{
|
||||
if (gtk_text_iter_inside_word (&start) || gtk_text_iter_ends_word (&start))
|
||||
{
|
||||
gtk_text_iter_backward_word_start (&start);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if we're neither at the beginning nor inside a word,
|
||||
* me must be in some spaces.
|
||||
* skip forward to the beginning of the next word. */
|
||||
|
||||
if (gtk_text_iter_forward_word_end (&start))
|
||||
{
|
||||
gtk_text_iter_backward_word_start (&start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (spell->doc),
|
||||
&cursor,
|
||||
gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (spell->doc)));
|
||||
|
||||
precursor = cursor;
|
||||
gtk_text_iter_backward_char (&precursor);
|
||||
|
||||
highlight = gtk_text_iter_has_tag (&cursor, spell->tag_highlight) ||
|
||||
gtk_text_iter_has_tag (&precursor, spell->tag_highlight);
|
||||
|
||||
gtk_text_buffer_remove_tag (GTK_TEXT_BUFFER (spell->doc), spell->tag_highlight, &start, &end);
|
||||
|
||||
/* Fix a corner case when replacement occurs at beginning of buffer:
|
||||
* An iter at offset 0 seems to always be inside a word,
|
||||
* even if it's not. Possibly a pango bug.
|
||||
*/
|
||||
if (gtk_text_iter_get_offset (&start) == 0)
|
||||
{
|
||||
gtk_text_iter_forward_word_end(&start);
|
||||
gtk_text_iter_backward_word_start(&start);
|
||||
}
|
||||
|
||||
wstart = start;
|
||||
|
||||
while (xed_spell_utils_skip_no_spell_check (&wstart, &end) && gtk_text_iter_compare (&wstart, &end) < 0)
|
||||
{
|
||||
gboolean inword;
|
||||
|
||||
/* move wend to the end of the current word. */
|
||||
wend = wstart;
|
||||
|
||||
gtk_text_iter_forward_word_end (&wend);
|
||||
|
||||
inword = (gtk_text_iter_compare (&wstart, &cursor) < 0) && (gtk_text_iter_compare (&cursor, &wend) <= 0);
|
||||
|
||||
if (inword && !force_all)
|
||||
{
|
||||
/* this word is being actively edited,
|
||||
* only check if it's already highligted,
|
||||
* otherwise defer this check until later. */
|
||||
if (highlight)
|
||||
{
|
||||
check_word (spell, &wstart, &wend);
|
||||
}
|
||||
else
|
||||
{
|
||||
spell->deferred_check = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
check_word (spell, &wstart, &wend);
|
||||
spell->deferred_check = FALSE;
|
||||
}
|
||||
|
||||
/* now move wend to the beginning of the next word, */
|
||||
gtk_text_iter_forward_word_end (&wend);
|
||||
gtk_text_iter_backward_word_start (&wend);
|
||||
|
||||
/* make sure we've actually advanced
|
||||
* (we don't advance in some corner cases), */
|
||||
if (gtk_text_iter_equal (&wstart, &wend))
|
||||
{
|
||||
break; /* we're done in these cases.. */
|
||||
}
|
||||
|
||||
/* and then pick this as the new next word beginning. */
|
||||
wstart = wend;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
check_deferred_range (XedAutomaticSpellChecker *spell,
|
||||
gboolean force_all)
|
||||
{
|
||||
GtkTextIter start, end;
|
||||
|
||||
gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (spell->doc), &start, spell->mark_insert_start);
|
||||
gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (spell->doc), &end, spell->mark_insert_end);
|
||||
|
||||
check_range (spell, start, end, force_all);
|
||||
}
|
||||
|
||||
/* insertion works like this:
|
||||
* - before the text is inserted, we mark the position in the buffer.
|
||||
* - after the text is inserted, we see where our mark is and use that and
|
||||
* the current position to check the entire range of inserted text.
|
||||
*
|
||||
* this may be overkill for the common case (inserting one character). */
|
||||
|
||||
static void
|
||||
insert_text_before (GtkTextBuffer *buffer,
|
||||
GtkTextIter *iter,
|
||||
gchar *text,
|
||||
gint len,
|
||||
XedAutomaticSpellChecker *spell)
|
||||
{
|
||||
gtk_text_buffer_move_mark (buffer, spell->mark_insert_start, iter);
|
||||
}
|
||||
|
||||
static void
|
||||
insert_text_after (GtkTextBuffer *buffer,
|
||||
GtkTextIter *iter,
|
||||
gchar *text,
|
||||
gint len,
|
||||
XedAutomaticSpellChecker *spell)
|
||||
{
|
||||
GtkTextIter start;
|
||||
|
||||
/* we need to check a range of text. */
|
||||
gtk_text_buffer_get_iter_at_mark (buffer, &start, spell->mark_insert_start);
|
||||
|
||||
check_range (spell, start, *iter, FALSE);
|
||||
|
||||
gtk_text_buffer_move_mark (buffer, spell->mark_insert_end, iter);
|
||||
}
|
||||
|
||||
/* deleting is more simple: we're given the range of deleted text.
|
||||
* after deletion, the start and end iters should be at the same position
|
||||
* (because all of the text between them was deleted!).
|
||||
* this means we only really check the words immediately bounding the
|
||||
* deletion.
|
||||
*/
|
||||
|
||||
static void
|
||||
delete_range_after (GtkTextBuffer *buffer,
|
||||
GtkTextIter *start,
|
||||
GtkTextIter *end,
|
||||
XedAutomaticSpellChecker *spell)
|
||||
{
|
||||
check_range (spell, *start, *end, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
mark_set (GtkTextBuffer *buffer,
|
||||
GtkTextIter *iter,
|
||||
GtkTextMark *mark,
|
||||
XedAutomaticSpellChecker *spell)
|
||||
{
|
||||
/* if the cursor has moved and there is a deferred check so handle it now */
|
||||
if ((mark == gtk_text_buffer_get_insert (buffer)) && spell->deferred_check)
|
||||
{
|
||||
check_deferred_range (spell, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_word_extents_from_mark (GtkTextBuffer *buffer,
|
||||
GtkTextIter *start,
|
||||
GtkTextIter *end,
|
||||
GtkTextMark *mark)
|
||||
{
|
||||
gtk_text_buffer_get_iter_at_mark(buffer, start, mark);
|
||||
|
||||
if (!gtk_text_iter_starts_word (start))
|
||||
{
|
||||
gtk_text_iter_backward_word_start (start);
|
||||
}
|
||||
|
||||
*end = *start;
|
||||
|
||||
if (gtk_text_iter_inside_word (end))
|
||||
{
|
||||
gtk_text_iter_forward_word_end (end);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
remove_tag_to_word (XedAutomaticSpellChecker *spell,
|
||||
const gchar *word)
|
||||
{
|
||||
GtkTextIter iter;
|
||||
GtkTextIter match_start, match_end;
|
||||
|
||||
gboolean found;
|
||||
|
||||
gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (spell->doc), &iter, 0);
|
||||
|
||||
found = TRUE;
|
||||
|
||||
while (found)
|
||||
{
|
||||
found = gtk_text_iter_forward_search (&iter,
|
||||
word,
|
||||
GTK_TEXT_SEARCH_VISIBLE_ONLY | GTK_TEXT_SEARCH_TEXT_ONLY,
|
||||
&match_start,
|
||||
&match_end,
|
||||
NULL);
|
||||
|
||||
if (found)
|
||||
{
|
||||
if (gtk_text_iter_starts_word (&match_start) && gtk_text_iter_ends_word (&match_end))
|
||||
{
|
||||
gtk_text_buffer_remove_tag (GTK_TEXT_BUFFER (spell->doc),
|
||||
spell->tag_highlight,
|
||||
&match_start,
|
||||
&match_end);
|
||||
}
|
||||
|
||||
iter = match_end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_to_dictionary (GtkWidget *menuitem,
|
||||
XedAutomaticSpellChecker *spell)
|
||||
{
|
||||
gchar *word;
|
||||
|
||||
GtkTextIter start, end;
|
||||
|
||||
get_word_extents_from_mark (GTK_TEXT_BUFFER (spell->doc), &start, &end, spell->mark_click);
|
||||
|
||||
word = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (spell->doc), &start, &end, FALSE);
|
||||
|
||||
xed_spell_checker_add_word_to_personal (spell->spell_checker, word, -1);
|
||||
|
||||
g_free (word);
|
||||
}
|
||||
|
||||
static void
|
||||
ignore_all (GtkWidget *menuitem,
|
||||
XedAutomaticSpellChecker *spell)
|
||||
{
|
||||
gchar *word;
|
||||
|
||||
GtkTextIter start, end;
|
||||
|
||||
get_word_extents_from_mark (GTK_TEXT_BUFFER (spell->doc), &start, &end, spell->mark_click);
|
||||
|
||||
word = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (spell->doc), &start, &end, FALSE);
|
||||
|
||||
xed_spell_checker_add_word_to_session (spell->spell_checker, word, -1);
|
||||
|
||||
g_free (word);
|
||||
}
|
||||
|
||||
static void
|
||||
replace_word (GtkWidget *menuitem,
|
||||
XedAutomaticSpellChecker *spell)
|
||||
{
|
||||
gchar *oldword;
|
||||
const gchar *newword;
|
||||
|
||||
GtkTextIter start, end;
|
||||
|
||||
get_word_extents_from_mark (GTK_TEXT_BUFFER (spell->doc), &start, &end, spell->mark_click);
|
||||
|
||||
oldword = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (spell->doc), &start, &end, FALSE);
|
||||
|
||||
newword = g_object_get_qdata (G_OBJECT (menuitem), suggestion_id);
|
||||
g_return_if_fail (newword != NULL);
|
||||
|
||||
gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (spell->doc));
|
||||
|
||||
gtk_text_buffer_delete (GTK_TEXT_BUFFER (spell->doc), &start, &end);
|
||||
gtk_text_buffer_insert (GTK_TEXT_BUFFER (spell->doc), &start, newword, -1);
|
||||
|
||||
gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (spell->doc));
|
||||
|
||||
xed_spell_checker_set_correction (spell->spell_checker,
|
||||
oldword, strlen (oldword),
|
||||
newword, strlen (newword));
|
||||
|
||||
g_free (oldword);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
build_suggestion_menu (XedAutomaticSpellChecker *spell,
|
||||
const gchar *word)
|
||||
{
|
||||
GtkWidget *topmenu, *menu;
|
||||
GtkWidget *mi;
|
||||
GSList *suggestions;
|
||||
GSList *list;
|
||||
gchar *label_text;
|
||||
|
||||
topmenu = menu = gtk_menu_new();
|
||||
|
||||
suggestions = xed_spell_checker_get_suggestions (spell->spell_checker, word, -1);
|
||||
|
||||
list = suggestions;
|
||||
|
||||
if (suggestions == NULL)
|
||||
{
|
||||
/* no suggestions. put something in the menu anyway... */
|
||||
GtkWidget *label;
|
||||
/* Translators: Displayed in the "Check Spelling" dialog if there are no suggestions for the current misspelled word */
|
||||
label = gtk_label_new (_("(no suggested words)"));
|
||||
|
||||
mi = gtk_menu_item_new ();
|
||||
gtk_widget_set_sensitive (mi, FALSE);
|
||||
gtk_container_add (GTK_CONTAINER(mi), label);
|
||||
gtk_widget_show_all (mi);
|
||||
gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), mi);
|
||||
}
|
||||
else
|
||||
{
|
||||
gint count = 0;
|
||||
|
||||
/* build a set of menus with suggestions. */
|
||||
while (suggestions != NULL)
|
||||
{
|
||||
GtkWidget *label;
|
||||
|
||||
if (count == 10)
|
||||
{
|
||||
/* Separator */
|
||||
mi = gtk_menu_item_new ();
|
||||
gtk_widget_show (mi);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
|
||||
|
||||
mi = gtk_menu_item_new_with_mnemonic (_("_More..."));
|
||||
gtk_widget_show (mi);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
|
||||
|
||||
menu = gtk_menu_new ();
|
||||
gtk_menu_item_set_submenu (GTK_MENU_ITEM (mi), menu);
|
||||
count = 0;
|
||||
}
|
||||
|
||||
label_text = g_strdup_printf ("<b>%s</b>", (gchar*) suggestions->data);
|
||||
|
||||
label = gtk_label_new (label_text);
|
||||
gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
|
||||
gtk_widget_set_halign (label, GTK_ALIGN_START);
|
||||
|
||||
mi = gtk_menu_item_new ();
|
||||
gtk_container_add (GTK_CONTAINER (mi), label);
|
||||
|
||||
gtk_widget_show_all (mi);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
|
||||
|
||||
g_object_set_qdata_full (G_OBJECT (mi),
|
||||
suggestion_id,
|
||||
g_strdup (suggestions->data),
|
||||
(GDestroyNotify)g_free);
|
||||
|
||||
g_free (label_text);
|
||||
g_signal_connect (mi, "activate",
|
||||
G_CALLBACK (replace_word), spell);
|
||||
|
||||
count++;
|
||||
|
||||
suggestions = g_slist_next (suggestions);
|
||||
}
|
||||
}
|
||||
|
||||
/* free the suggestion list */
|
||||
suggestions = list;
|
||||
|
||||
while (list)
|
||||
{
|
||||
g_free (list->data);
|
||||
list = g_slist_next (list);
|
||||
}
|
||||
|
||||
g_slist_free (suggestions);
|
||||
|
||||
/* Separator */
|
||||
mi = gtk_menu_item_new ();
|
||||
gtk_widget_show (mi);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (topmenu), mi);
|
||||
|
||||
/* Ignore all */
|
||||
mi = gtk_menu_item_new_with_mnemonic (_("_Ignore All"));
|
||||
|
||||
g_signal_connect (mi, "activate",
|
||||
G_CALLBACK(ignore_all), spell);
|
||||
|
||||
gtk_widget_show_all (mi);
|
||||
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (topmenu), mi);
|
||||
|
||||
/* + Add to Dictionary */
|
||||
mi = gtk_menu_item_new_with_mnemonic (_("_Add"));
|
||||
|
||||
g_signal_connect (mi, "activate",
|
||||
G_CALLBACK (add_to_dictionary), spell);
|
||||
|
||||
gtk_widget_show_all (mi);
|
||||
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (topmenu), mi);
|
||||
|
||||
return topmenu;
|
||||
}
|
||||
|
||||
static void
|
||||
populate_popup (GtkTextView *textview,
|
||||
GtkMenu *menu,
|
||||
XedAutomaticSpellChecker *spell)
|
||||
{
|
||||
GtkWidget *mi;
|
||||
GtkTextIter start, end;
|
||||
char *word;
|
||||
|
||||
/* we need to figure out if they picked a misspelled word. */
|
||||
get_word_extents_from_mark (GTK_TEXT_BUFFER (spell->doc), &start, &end, spell->mark_click);
|
||||
|
||||
/* if our highlight algorithm ever messes up,
|
||||
* this isn't correct, either. */
|
||||
if (!gtk_text_iter_has_tag (&start, spell->tag_highlight))
|
||||
{
|
||||
return; /* word wasn't misspelled. */
|
||||
}
|
||||
|
||||
/* menu separator comes first. */
|
||||
mi = gtk_menu_item_new ();
|
||||
gtk_widget_show (mi);
|
||||
gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), mi);
|
||||
|
||||
/* then, on top of it, the suggestions menu. */
|
||||
mi = gtk_menu_item_new_with_mnemonic (_("_Spelling Suggestions..."));
|
||||
|
||||
word = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (spell->doc), &start, &end, FALSE);
|
||||
gtk_menu_item_set_submenu (GTK_MENU_ITEM (mi), build_suggestion_menu (spell, word));
|
||||
g_free(word);
|
||||
|
||||
gtk_widget_show_all (mi);
|
||||
gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), mi);
|
||||
}
|
||||
|
||||
void
|
||||
xed_automatic_spell_checker_recheck_all (XedAutomaticSpellChecker *spell)
|
||||
{
|
||||
GtkTextIter start, end;
|
||||
|
||||
g_return_if_fail (spell != NULL);
|
||||
|
||||
gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (spell->doc), &start, &end);
|
||||
|
||||
check_range (spell, start, end, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
add_word_signal_cb (XedSpellChecker *checker,
|
||||
const gchar *word,
|
||||
gint len,
|
||||
XedAutomaticSpellChecker *spell)
|
||||
{
|
||||
gchar *w;
|
||||
|
||||
if (len < 0)
|
||||
{
|
||||
w = g_strdup (word);
|
||||
}
|
||||
else
|
||||
{
|
||||
w = g_strndup (word, len);
|
||||
}
|
||||
|
||||
remove_tag_to_word (spell, w);
|
||||
|
||||
g_free (w);
|
||||
}
|
||||
|
||||
static void
|
||||
set_language_cb (XedSpellChecker *checker,
|
||||
const XedSpellCheckerLanguage *lang,
|
||||
XedAutomaticSpellChecker *spell)
|
||||
{
|
||||
xed_automatic_spell_checker_recheck_all (spell);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_session_cb (XedSpellChecker *checker,
|
||||
XedAutomaticSpellChecker *spell)
|
||||
{
|
||||
xed_automatic_spell_checker_recheck_all (spell);
|
||||
}
|
||||
|
||||
/* When the user right-clicks on a word, they want to check that word.
|
||||
* Here, we do NOT move the cursor to the location of the clicked-upon word
|
||||
* since that prevents the use of edit functions on the context menu.
|
||||
*/
|
||||
static gboolean
|
||||
button_press_event (GtkTextView *view,
|
||||
GdkEventButton *event,
|
||||
XedAutomaticSpellChecker *spell)
|
||||
{
|
||||
if (event->button == 3)
|
||||
{
|
||||
gint x, y;
|
||||
GtkTextIter iter;
|
||||
|
||||
GtkTextBuffer *buffer = gtk_text_view_get_buffer (view);
|
||||
|
||||
/* handle deferred check if it exists */
|
||||
if (spell->deferred_check)
|
||||
{
|
||||
check_deferred_range (spell, TRUE);
|
||||
}
|
||||
|
||||
gtk_text_view_window_to_buffer_coords (view, GTK_TEXT_WINDOW_TEXT, event->x, event->y, &x, &y);
|
||||
|
||||
gtk_text_view_get_iter_at_location (view, &iter, x, y);
|
||||
|
||||
gtk_text_buffer_move_mark (buffer, spell->mark_click, &iter);
|
||||
}
|
||||
|
||||
return FALSE; /* false: let gtk process this event, too.
|
||||
we don't want to eat any events. */
|
||||
}
|
||||
|
||||
/* Move the insert mark before popping up the menu, otherwise it
|
||||
* will contain the wrong set of suggestions.
|
||||
*/
|
||||
static gboolean
|
||||
popup_menu_event (GtkTextView *view,
|
||||
XedAutomaticSpellChecker *spell)
|
||||
{
|
||||
GtkTextIter iter;
|
||||
GtkTextBuffer *buffer;
|
||||
|
||||
buffer = gtk_text_view_get_buffer (view);
|
||||
|
||||
/* handle deferred check if it exists */
|
||||
if (spell->deferred_check)
|
||||
{
|
||||
check_deferred_range (spell, TRUE);
|
||||
}
|
||||
|
||||
gtk_text_buffer_get_iter_at_mark (buffer, &iter, gtk_text_buffer_get_insert (buffer));
|
||||
gtk_text_buffer_move_mark (buffer, spell->mark_click, &iter);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
tag_table_changed (GtkTextTagTable *table,
|
||||
XedAutomaticSpellChecker *spell)
|
||||
{
|
||||
g_return_if_fail (spell->tag_highlight != NULL);
|
||||
|
||||
gtk_text_tag_set_priority (spell->tag_highlight, gtk_text_tag_table_get_size (table) - 1);
|
||||
}
|
||||
|
||||
static void
|
||||
tag_added_or_removed (GtkTextTagTable *table,
|
||||
GtkTextTag *tag,
|
||||
XedAutomaticSpellChecker *spell)
|
||||
{
|
||||
tag_table_changed (table, spell);
|
||||
}
|
||||
|
||||
static void
|
||||
tag_changed (GtkTextTagTable *table,
|
||||
GtkTextTag *tag,
|
||||
gboolean size_changed,
|
||||
XedAutomaticSpellChecker *spell)
|
||||
{
|
||||
tag_table_changed (table, spell);
|
||||
}
|
||||
|
||||
static void
|
||||
highlight_updated (GtkSourceBuffer *buffer,
|
||||
GtkTextIter *start,
|
||||
GtkTextIter *end,
|
||||
XedAutomaticSpellChecker *spell)
|
||||
{
|
||||
check_range (spell, *start, *end, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
spell_tag_destroyed (XedAutomaticSpellChecker *spell,
|
||||
GObject *where_the_object_was)
|
||||
{
|
||||
spell->tag_highlight = NULL;
|
||||
}
|
||||
|
||||
XedAutomaticSpellChecker *
|
||||
xed_automatic_spell_checker_new (XedDocument *doc,
|
||||
XedSpellChecker *checker)
|
||||
{
|
||||
XedAutomaticSpellChecker *spell;
|
||||
GtkTextTagTable *tag_table;
|
||||
GtkTextIter start, end;
|
||||
|
||||
g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL);
|
||||
g_return_val_if_fail (XED_IS_SPELL_CHECKER (checker), NULL);
|
||||
g_return_val_if_fail ((spell = xed_automatic_spell_checker_get_from_document (doc)) == NULL, spell);
|
||||
|
||||
/* attach to the widget */
|
||||
spell = g_new0 (XedAutomaticSpellChecker, 1);
|
||||
|
||||
spell->doc = doc;
|
||||
spell->spell_checker = g_object_ref (checker);
|
||||
|
||||
if (automatic_spell_checker_id == 0)
|
||||
{
|
||||
automatic_spell_checker_id = g_quark_from_string ("XedAutomaticSpellCheckerID");
|
||||
}
|
||||
if (suggestion_id == 0)
|
||||
{
|
||||
suggestion_id = g_quark_from_string ("XedAutoSuggestionID");
|
||||
}
|
||||
|
||||
g_object_set_qdata_full (G_OBJECT (doc), automatic_spell_checker_id,
|
||||
spell, (GDestroyNotify)xed_automatic_spell_checker_free_internal);
|
||||
|
||||
g_signal_connect (doc, "insert-text",
|
||||
G_CALLBACK (insert_text_before), spell);
|
||||
g_signal_connect_after (doc, "insert-text",
|
||||
G_CALLBACK (insert_text_after), spell);
|
||||
g_signal_connect_after (doc, "delete-range",
|
||||
G_CALLBACK (delete_range_after), spell);
|
||||
g_signal_connect (doc, "mark-set",
|
||||
G_CALLBACK (mark_set), spell);
|
||||
|
||||
g_signal_connect (doc, "highlight-updated",
|
||||
G_CALLBACK (highlight_updated), spell);
|
||||
|
||||
g_signal_connect (spell->spell_checker, "add_word_to_session",
|
||||
G_CALLBACK (add_word_signal_cb), spell);
|
||||
g_signal_connect (spell->spell_checker, "add_word_to_personal",
|
||||
G_CALLBACK (add_word_signal_cb), spell);
|
||||
g_signal_connect (spell->spell_checker, "clear_session",
|
||||
G_CALLBACK (clear_session_cb), spell);
|
||||
g_signal_connect (spell->spell_checker, "set_language",
|
||||
G_CALLBACK (set_language_cb), spell);
|
||||
|
||||
spell->tag_highlight = gtk_text_buffer_create_tag (GTK_TEXT_BUFFER (doc),
|
||||
"gtkspell-misspelled",
|
||||
"underline", PANGO_UNDERLINE_ERROR,
|
||||
NULL);
|
||||
|
||||
g_object_weak_ref (G_OBJECT (spell->tag_highlight), (GWeakNotify)spell_tag_destroyed, spell);
|
||||
|
||||
tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (doc));
|
||||
|
||||
gtk_text_tag_set_priority (spell->tag_highlight, gtk_text_tag_table_get_size (tag_table) - 1);
|
||||
|
||||
g_signal_connect (tag_table, "tag-added",
|
||||
G_CALLBACK (tag_added_or_removed), spell);
|
||||
g_signal_connect (tag_table, "tag-removed",
|
||||
G_CALLBACK (tag_added_or_removed), spell);
|
||||
g_signal_connect (tag_table, "tag-changed",
|
||||
G_CALLBACK (tag_changed), spell);
|
||||
|
||||
/* we create the mark here, but we don't use it until text is
|
||||
* inserted, so we don't really care where iter points. */
|
||||
gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (doc), &start, &end);
|
||||
|
||||
spell->mark_insert_start = gtk_text_buffer_get_mark (GTK_TEXT_BUFFER (doc),
|
||||
"xed-automatic-spell-checker-insert-start");
|
||||
|
||||
if (spell->mark_insert_start == NULL)
|
||||
{
|
||||
spell->mark_insert_start = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (doc),
|
||||
"xed-automatic-spell-checker-insert-start",
|
||||
&start,
|
||||
TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc), spell->mark_insert_start, &start);
|
||||
}
|
||||
|
||||
spell->mark_insert_end = gtk_text_buffer_get_mark (GTK_TEXT_BUFFER (doc),
|
||||
"xed-automatic-spell-checker-insert-end");
|
||||
|
||||
if (spell->mark_insert_end == NULL)
|
||||
{
|
||||
spell->mark_insert_end = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (doc),
|
||||
"xed-automatic-spell-checker-insert-end",
|
||||
&start,
|
||||
TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc), spell->mark_insert_end, &start);
|
||||
}
|
||||
|
||||
spell->mark_click = gtk_text_buffer_get_mark (GTK_TEXT_BUFFER (doc),
|
||||
"xed-automatic-spell-checker-click");
|
||||
|
||||
if (spell->mark_click == NULL)
|
||||
{
|
||||
spell->mark_click = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (doc),
|
||||
"xed-automatic-spell-checker-click",
|
||||
&start,
|
||||
TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc), spell->mark_click, &start);
|
||||
}
|
||||
|
||||
spell->deferred_check = FALSE;
|
||||
|
||||
return spell;
|
||||
}
|
||||
|
||||
XedAutomaticSpellChecker *
|
||||
xed_automatic_spell_checker_get_from_document (const XedDocument *doc)
|
||||
{
|
||||
g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL);
|
||||
|
||||
if (automatic_spell_checker_id == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return g_object_get_qdata (G_OBJECT (doc), automatic_spell_checker_id);
|
||||
}
|
||||
|
||||
void
|
||||
xed_automatic_spell_checker_free (XedAutomaticSpellChecker *spell)
|
||||
{
|
||||
g_return_if_fail (spell != NULL);
|
||||
g_return_if_fail (xed_automatic_spell_checker_get_from_document (spell->doc) == spell);
|
||||
|
||||
if (automatic_spell_checker_id == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g_object_set_qdata (G_OBJECT (spell->doc), automatic_spell_checker_id, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
xed_automatic_spell_checker_free_internal (XedAutomaticSpellChecker *spell)
|
||||
{
|
||||
GtkTextTagTable *table;
|
||||
GtkTextIter start, end;
|
||||
GSList *list;
|
||||
|
||||
g_return_if_fail (spell != NULL);
|
||||
|
||||
table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (spell->doc));
|
||||
|
||||
if (table != NULL && spell->tag_highlight != NULL)
|
||||
{
|
||||
gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (spell->doc), &start, &end);
|
||||
gtk_text_buffer_remove_tag (GTK_TEXT_BUFFER (spell->doc), spell->tag_highlight, &start, &end);
|
||||
|
||||
g_signal_handlers_disconnect_matched (G_OBJECT (table),
|
||||
G_SIGNAL_MATCH_DATA,
|
||||
0, 0, NULL, NULL,
|
||||
spell);
|
||||
|
||||
gtk_text_tag_table_remove (table, spell->tag_highlight);
|
||||
}
|
||||
|
||||
g_signal_handlers_disconnect_matched (G_OBJECT (spell->doc),
|
||||
G_SIGNAL_MATCH_DATA,
|
||||
0, 0, NULL, NULL,
|
||||
spell);
|
||||
|
||||
g_signal_handlers_disconnect_matched (G_OBJECT (spell->spell_checker),
|
||||
G_SIGNAL_MATCH_DATA,
|
||||
0, 0, NULL, NULL,
|
||||
spell);
|
||||
|
||||
g_object_unref (spell->spell_checker);
|
||||
|
||||
list = spell->views;
|
||||
while (list != NULL)
|
||||
{
|
||||
XedView *view = XED_VIEW (list->data);
|
||||
|
||||
g_signal_handlers_disconnect_matched (G_OBJECT (view),
|
||||
G_SIGNAL_MATCH_DATA,
|
||||
0, 0, NULL, NULL,
|
||||
spell);
|
||||
|
||||
g_signal_handlers_disconnect_matched (G_OBJECT (view),
|
||||
G_SIGNAL_MATCH_DATA,
|
||||
0, 0, NULL, NULL,
|
||||
spell);
|
||||
|
||||
list = g_slist_next (list);
|
||||
}
|
||||
|
||||
g_slist_free (spell->views);
|
||||
|
||||
g_free (spell);
|
||||
}
|
||||
|
||||
void
|
||||
xed_automatic_spell_checker_attach_view (XedAutomaticSpellChecker *spell,
|
||||
XedView *view)
|
||||
{
|
||||
g_return_if_fail (spell != NULL);
|
||||
g_return_if_fail (XED_IS_VIEW (view));
|
||||
|
||||
g_return_if_fail (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)) == GTK_TEXT_BUFFER (spell->doc));
|
||||
|
||||
g_signal_connect (view, "button-press-event",
|
||||
G_CALLBACK (button_press_event), spell);
|
||||
g_signal_connect (view, "popup-menu",
|
||||
G_CALLBACK (popup_menu_event), spell);
|
||||
g_signal_connect (view, "populate-popup",
|
||||
G_CALLBACK (populate_popup), spell);
|
||||
g_signal_connect (view, "destroy",
|
||||
G_CALLBACK (view_destroy), spell);
|
||||
|
||||
spell->views = g_slist_prepend (spell->views, view);
|
||||
}
|
||||
|
||||
void
|
||||
xed_automatic_spell_checker_detach_view (XedAutomaticSpellChecker *spell,
|
||||
XedView *view)
|
||||
{
|
||||
g_return_if_fail (spell != NULL);
|
||||
g_return_if_fail (XED_IS_VIEW (view));
|
||||
|
||||
g_return_if_fail (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)) == GTK_TEXT_BUFFER (spell->doc));
|
||||
g_return_if_fail (spell->views != NULL);
|
||||
|
||||
g_signal_handlers_disconnect_matched (G_OBJECT (view),
|
||||
G_SIGNAL_MATCH_DATA,
|
||||
0, 0, NULL, NULL,
|
||||
spell);
|
||||
|
||||
g_signal_handlers_disconnect_matched (G_OBJECT (view),
|
||||
G_SIGNAL_MATCH_DATA,
|
||||
0, 0, NULL, NULL,
|
||||
spell);
|
||||
|
||||
spell->views = g_slist_remove (spell->views, view);
|
||||
}
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* xed-automatic-spell-checker.h
|
||||
* This file is part of xed
|
||||
*
|
||||
* Copyright (C) 2002 Paolo Maggi
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the xed Team, 2002. See the AUTHORS file for a
|
||||
* list of people on the xed Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*/
|
||||
|
||||
/* This is a modified version of gtkspell 2.0.2 (gtkspell.sf.net) */
|
||||
/* gtkspell - a spell-checking addon for GTK's TextView widget
|
||||
* Copyright (c) 2002 Evan Martin.
|
||||
*/
|
||||
|
||||
#ifndef __XED_AUTOMATIC_SPELL_CHECKER_H__
|
||||
#define __XED_AUTOMATIC_SPELL_CHECKER_H__
|
||||
|
||||
#include <xed/xed-document.h>
|
||||
#include <xed/xed-view.h>
|
||||
|
||||
#include "xed-spell-checker.h"
|
||||
|
||||
typedef struct _XedAutomaticSpellChecker XedAutomaticSpellChecker;
|
||||
|
||||
XedAutomaticSpellChecker *xed_automatic_spell_checker_new (
|
||||
XedDocument *doc,
|
||||
XedSpellChecker *checker);
|
||||
|
||||
XedAutomaticSpellChecker *xed_automatic_spell_checker_get_from_document (
|
||||
const XedDocument *doc);
|
||||
|
||||
void xed_automatic_spell_checker_free (
|
||||
XedAutomaticSpellChecker *spell);
|
||||
|
||||
void xed_automatic_spell_checker_attach_view (
|
||||
XedAutomaticSpellChecker *spell,
|
||||
XedView *view);
|
||||
|
||||
void xed_automatic_spell_checker_detach_view (
|
||||
XedAutomaticSpellChecker *spell,
|
||||
XedView *view);
|
||||
|
||||
void xed_automatic_spell_checker_recheck_all (
|
||||
XedAutomaticSpellChecker *spell);
|
||||
|
||||
#endif /* __XED_AUTOMATIC_SPELL_CHECKER_H__ */
|
||||
|
|
@ -1,726 +0,0 @@
|
|||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* xed-spell-checker-dialog.c
|
||||
* This file is part of xed
|
||||
*
|
||||
* Copyright (C) 2002 Paolo Maggi
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the xed Team, 2002. See the AUTHORS file for a
|
||||
* list of people on the xed Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <xed/xed-utils.h>
|
||||
#include "xed-spell-checker-dialog.h"
|
||||
#include "xed-spell-marshal.h"
|
||||
|
||||
struct _XedSpellCheckerDialog
|
||||
{
|
||||
GtkWindow parent_instance;
|
||||
|
||||
XedSpellChecker *spell_checker;
|
||||
|
||||
gchar *misspelled_word;
|
||||
|
||||
GtkWidget *misspelled_word_label;
|
||||
GtkWidget *word_entry;
|
||||
GtkWidget *check_word_button;
|
||||
GtkWidget *ignore_button;
|
||||
GtkWidget *ignore_all_button;
|
||||
GtkWidget *change_button;
|
||||
GtkWidget *change_all_button;
|
||||
GtkWidget *add_word_button;
|
||||
GtkWidget *close_button;
|
||||
GtkWidget *suggestions_list;
|
||||
GtkWidget *language_label;
|
||||
|
||||
GtkTreeModel *suggestions_list_model;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
IGNORE,
|
||||
IGNORE_ALL,
|
||||
CHANGE,
|
||||
CHANGE_ALL,
|
||||
ADD_WORD_TO_PERSONAL,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
COLUMN_SUGGESTIONS,
|
||||
NUM_COLUMNS
|
||||
};
|
||||
|
||||
static void update_suggestions_list_model (XedSpellCheckerDialog *dlg,
|
||||
GSList *suggestions);
|
||||
|
||||
static void word_entry_changed_handler (GtkEditable *editable,
|
||||
XedSpellCheckerDialog *dlg);
|
||||
static void close_button_clicked_handler (GtkButton *button,
|
||||
XedSpellCheckerDialog *dlg);
|
||||
static void suggestions_list_selection_changed_handler (GtkTreeSelection *selection,
|
||||
XedSpellCheckerDialog *dlg);
|
||||
static void check_word_button_clicked_handler (GtkButton *button,
|
||||
XedSpellCheckerDialog *dlg);
|
||||
static void add_word_button_clicked_handler (GtkButton *button,
|
||||
XedSpellCheckerDialog *dlg);
|
||||
static void ignore_button_clicked_handler (GtkButton *button,
|
||||
XedSpellCheckerDialog *dlg);
|
||||
static void ignore_all_button_clicked_handler (GtkButton *button,
|
||||
XedSpellCheckerDialog *dlg);
|
||||
static void change_button_clicked_handler (GtkButton *button,
|
||||
XedSpellCheckerDialog *dlg);
|
||||
static void change_all_button_clicked_handler (GtkButton *button,
|
||||
XedSpellCheckerDialog *dlg);
|
||||
static void suggestions_list_row_activated_handler (GtkTreeView *view,
|
||||
GtkTreePath *path,
|
||||
GtkTreeViewColumn *column,
|
||||
XedSpellCheckerDialog *dlg);
|
||||
|
||||
|
||||
static guint signals [LAST_SIGNAL] = { 0 };
|
||||
|
||||
G_DEFINE_TYPE(XedSpellCheckerDialog, xed_spell_checker_dialog, GTK_TYPE_WINDOW)
|
||||
|
||||
static void
|
||||
xed_spell_checker_dialog_dispose (GObject *object)
|
||||
{
|
||||
XedSpellCheckerDialog *dlg = XED_SPELL_CHECKER_DIALOG (object);
|
||||
|
||||
if (dlg->spell_checker != NULL)
|
||||
{
|
||||
g_object_unref (dlg->spell_checker);
|
||||
dlg->spell_checker = NULL;
|
||||
}
|
||||
|
||||
if (dlg->misspelled_word != NULL)
|
||||
{
|
||||
g_free (dlg->misspelled_word);
|
||||
dlg->misspelled_word = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (xed_spell_checker_dialog_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
xed_spell_checker_dialog_class_init (XedSpellCheckerDialogClass * klass)
|
||||
{
|
||||
GObjectClass *object_class;
|
||||
|
||||
object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->dispose = xed_spell_checker_dialog_dispose;
|
||||
|
||||
signals[IGNORE] =
|
||||
g_signal_new ("ignore",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (XedSpellCheckerDialogClass, ignore),
|
||||
NULL, NULL,
|
||||
xed_marshal_VOID__STRING,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
G_TYPE_STRING);
|
||||
|
||||
signals[IGNORE_ALL] =
|
||||
g_signal_new ("ignore_all",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (XedSpellCheckerDialogClass, ignore_all),
|
||||
NULL, NULL,
|
||||
xed_marshal_VOID__STRING,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
G_TYPE_STRING);
|
||||
|
||||
signals[CHANGE] =
|
||||
g_signal_new ("change",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (XedSpellCheckerDialogClass, change),
|
||||
NULL, NULL,
|
||||
xed_marshal_VOID__STRING_STRING,
|
||||
G_TYPE_NONE,
|
||||
2,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_STRING);
|
||||
|
||||
signals[CHANGE_ALL] =
|
||||
g_signal_new ("change_all",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (XedSpellCheckerDialogClass, change_all),
|
||||
NULL, NULL,
|
||||
xed_marshal_VOID__STRING_STRING,
|
||||
G_TYPE_NONE,
|
||||
2,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_STRING);
|
||||
|
||||
signals[ADD_WORD_TO_PERSONAL] =
|
||||
g_signal_new ("add_word_to_personal",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (XedSpellCheckerDialogClass, add_word_to_personal),
|
||||
NULL, NULL,
|
||||
xed_marshal_VOID__STRING,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
G_TYPE_STRING);
|
||||
}
|
||||
|
||||
static void
|
||||
create_dialog (XedSpellCheckerDialog *dlg,
|
||||
const gchar *data_dir)
|
||||
{
|
||||
GtkWidget *error_widget;
|
||||
GtkWidget *content;
|
||||
GtkTreeViewColumn *column;
|
||||
GtkCellRenderer *cell;
|
||||
GtkTreeSelection *selection;
|
||||
gchar *root_objects[] = {
|
||||
"content",
|
||||
"check_word_image",
|
||||
"add_word_image",
|
||||
"ignore_image",
|
||||
"change_image",
|
||||
"ignore_all_image",
|
||||
"change_all_image",
|
||||
NULL
|
||||
};
|
||||
gboolean ret;
|
||||
gchar *ui_file;
|
||||
|
||||
g_return_if_fail (dlg != NULL);
|
||||
|
||||
dlg->spell_checker = NULL;
|
||||
dlg->misspelled_word = NULL;
|
||||
|
||||
ui_file = g_build_filename (data_dir, "spell-checker.ui", NULL);
|
||||
ret = xed_utils_get_ui_objects (ui_file,
|
||||
root_objects,
|
||||
&error_widget,
|
||||
|
||||
"content", &content,
|
||||
"misspelled_word_label", &dlg->misspelled_word_label,
|
||||
"word_entry", &dlg->word_entry,
|
||||
"check_word_button", &dlg->check_word_button,
|
||||
"ignore_button", &dlg->ignore_button,
|
||||
"ignore_all_button", &dlg->ignore_all_button,
|
||||
"change_button", &dlg->change_button,
|
||||
"change_all_button", &dlg->change_all_button,
|
||||
"add_word_button", &dlg->add_word_button,
|
||||
"close_button", &dlg->close_button,
|
||||
"suggestions_list", &dlg->suggestions_list,
|
||||
"language_label", &dlg->language_label,
|
||||
NULL);
|
||||
g_free (ui_file);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
gtk_widget_show (error_widget);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
|
||||
error_widget, TRUE, TRUE, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_label_set_label (GTK_LABEL (dlg->misspelled_word_label), "");
|
||||
gtk_widget_set_sensitive (dlg->word_entry, FALSE);
|
||||
gtk_widget_set_sensitive (dlg->check_word_button, FALSE);
|
||||
gtk_widget_set_sensitive (dlg->ignore_button, FALSE);
|
||||
gtk_widget_set_sensitive (dlg->ignore_all_button, FALSE);
|
||||
gtk_widget_set_sensitive (dlg->change_button, FALSE);
|
||||
gtk_widget_set_sensitive (dlg->change_all_button, FALSE);
|
||||
gtk_widget_set_sensitive (dlg->add_word_button, FALSE);
|
||||
|
||||
gtk_label_set_label (GTK_LABEL (dlg->language_label), "");
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (dlg), content);
|
||||
g_object_unref (content);
|
||||
|
||||
gtk_window_set_resizable (GTK_WINDOW (dlg), FALSE);
|
||||
gtk_window_set_title (GTK_WINDOW (dlg), _("Check Spelling"));
|
||||
|
||||
/* Suggestion list */
|
||||
dlg->suggestions_list_model = GTK_TREE_MODEL (
|
||||
gtk_list_store_new (NUM_COLUMNS, G_TYPE_STRING));
|
||||
|
||||
gtk_tree_view_set_model (GTK_TREE_VIEW (dlg->suggestions_list),
|
||||
dlg->suggestions_list_model);
|
||||
|
||||
/* Add the suggestions column */
|
||||
cell = gtk_cell_renderer_text_new ();
|
||||
column = gtk_tree_view_column_new_with_attributes (_("Suggestions"), cell,
|
||||
"text", COLUMN_SUGGESTIONS, NULL);
|
||||
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (dlg->suggestions_list), column);
|
||||
|
||||
gtk_tree_view_set_search_column (GTK_TREE_VIEW (dlg->suggestions_list),
|
||||
COLUMN_SUGGESTIONS);
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->suggestions_list));
|
||||
|
||||
gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
|
||||
|
||||
/* Set default button */
|
||||
gtk_widget_set_can_default (dlg->change_button, TRUE);
|
||||
gtk_widget_grab_default (dlg->change_button);
|
||||
|
||||
gtk_entry_set_activates_default (GTK_ENTRY (dlg->word_entry), TRUE);
|
||||
|
||||
/* Connect signals */
|
||||
g_signal_connect (dlg->word_entry, "changed",
|
||||
G_CALLBACK (word_entry_changed_handler), dlg);
|
||||
g_signal_connect (dlg->close_button, "clicked",
|
||||
G_CALLBACK (close_button_clicked_handler), dlg);
|
||||
g_signal_connect (selection, "changed",
|
||||
G_CALLBACK (suggestions_list_selection_changed_handler),
|
||||
dlg);
|
||||
g_signal_connect (dlg->check_word_button, "clicked",
|
||||
G_CALLBACK (check_word_button_clicked_handler), dlg);
|
||||
g_signal_connect (dlg->add_word_button, "clicked",
|
||||
G_CALLBACK (add_word_button_clicked_handler), dlg);
|
||||
g_signal_connect (dlg->ignore_button, "clicked",
|
||||
G_CALLBACK (ignore_button_clicked_handler), dlg);
|
||||
g_signal_connect (dlg->ignore_all_button, "clicked",
|
||||
G_CALLBACK (ignore_all_button_clicked_handler), dlg);
|
||||
g_signal_connect (dlg->change_button, "clicked",
|
||||
G_CALLBACK (change_button_clicked_handler), dlg);
|
||||
g_signal_connect (dlg->change_all_button, "clicked",
|
||||
G_CALLBACK (change_all_button_clicked_handler), dlg);
|
||||
g_signal_connect (dlg->suggestions_list, "row-activated",
|
||||
G_CALLBACK (suggestions_list_row_activated_handler), dlg);
|
||||
}
|
||||
|
||||
static void
|
||||
xed_spell_checker_dialog_init (XedSpellCheckerDialog *dlg)
|
||||
{
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
xed_spell_checker_dialog_new (const gchar *data_dir)
|
||||
{
|
||||
XedSpellCheckerDialog *dlg;
|
||||
|
||||
dlg = XED_SPELL_CHECKER_DIALOG (
|
||||
g_object_new (XED_TYPE_SPELL_CHECKER_DIALOG, NULL));
|
||||
|
||||
g_return_val_if_fail (dlg != NULL, NULL);
|
||||
|
||||
create_dialog (dlg, data_dir);
|
||||
|
||||
return GTK_WIDGET (dlg);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
xed_spell_checker_dialog_new_from_spell_checker (XedSpellChecker *spell,
|
||||
const gchar *data_dir)
|
||||
{
|
||||
XedSpellCheckerDialog *dlg;
|
||||
|
||||
g_return_val_if_fail (spell != NULL, NULL);
|
||||
|
||||
dlg = XED_SPELL_CHECKER_DIALOG (
|
||||
g_object_new (XED_TYPE_SPELL_CHECKER_DIALOG, NULL));
|
||||
|
||||
g_return_val_if_fail (dlg != NULL, NULL);
|
||||
|
||||
create_dialog (dlg, data_dir);
|
||||
|
||||
xed_spell_checker_dialog_set_spell_checker (dlg, spell);
|
||||
|
||||
return GTK_WIDGET (dlg);
|
||||
}
|
||||
|
||||
void
|
||||
xed_spell_checker_dialog_set_spell_checker (XedSpellCheckerDialog *dlg, XedSpellChecker *spell)
|
||||
{
|
||||
const XedSpellCheckerLanguage* language;
|
||||
const gchar *lang;
|
||||
gchar *tmp;
|
||||
|
||||
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
|
||||
g_return_if_fail (spell != NULL);
|
||||
|
||||
if (dlg->spell_checker != NULL)
|
||||
g_object_unref (dlg->spell_checker);
|
||||
|
||||
dlg->spell_checker = spell;
|
||||
g_object_ref (dlg->spell_checker);
|
||||
|
||||
language = xed_spell_checker_get_language (dlg->spell_checker);
|
||||
|
||||
lang = xed_spell_checker_language_to_string (language);
|
||||
tmp = g_strdup_printf("<b>%s</b>", lang);
|
||||
|
||||
gtk_label_set_label (GTK_LABEL (dlg->language_label), tmp);
|
||||
g_free (tmp);
|
||||
|
||||
if (dlg->misspelled_word != NULL)
|
||||
xed_spell_checker_dialog_set_misspelled_word (dlg, dlg->misspelled_word, -1);
|
||||
else
|
||||
gtk_list_store_clear (GTK_LIST_STORE (dlg->suggestions_list_model));
|
||||
|
||||
/* TODO: reset all widgets */
|
||||
}
|
||||
|
||||
void
|
||||
xed_spell_checker_dialog_set_misspelled_word (XedSpellCheckerDialog *dlg,
|
||||
const gchar *word,
|
||||
gint len)
|
||||
{
|
||||
gchar *tmp;
|
||||
GSList *sug;
|
||||
|
||||
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
|
||||
g_return_if_fail (word != NULL);
|
||||
|
||||
g_return_if_fail (dlg->spell_checker != NULL);
|
||||
g_return_if_fail (!xed_spell_checker_check_word (dlg->spell_checker, word, -1));
|
||||
|
||||
/* build_suggestions_list */
|
||||
if (dlg->misspelled_word != NULL)
|
||||
g_free (dlg->misspelled_word);
|
||||
|
||||
dlg->misspelled_word = g_strdup (word);
|
||||
|
||||
tmp = g_strdup_printf("<b>%s</b>", word);
|
||||
gtk_label_set_label (GTK_LABEL (dlg->misspelled_word_label), tmp);
|
||||
g_free (tmp);
|
||||
|
||||
sug = xed_spell_checker_get_suggestions (dlg->spell_checker,
|
||||
dlg->misspelled_word,
|
||||
-1);
|
||||
|
||||
update_suggestions_list_model (dlg, sug);
|
||||
|
||||
/* free the suggestion list */
|
||||
g_slist_foreach (sug, (GFunc)g_free, NULL);
|
||||
g_slist_free (sug);
|
||||
|
||||
gtk_widget_set_sensitive (dlg->ignore_button, TRUE);
|
||||
gtk_widget_set_sensitive (dlg->ignore_all_button, TRUE);
|
||||
gtk_widget_set_sensitive (dlg->add_word_button, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
update_suggestions_list_model (XedSpellCheckerDialog *dlg, GSList *suggestions)
|
||||
{
|
||||
GtkListStore *store;
|
||||
GtkTreeIter iter;
|
||||
GtkTreeSelection *sel;
|
||||
|
||||
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
|
||||
g_return_if_fail (GTK_IS_LIST_STORE (dlg->suggestions_list_model));
|
||||
|
||||
store = GTK_LIST_STORE (dlg->suggestions_list_model);
|
||||
gtk_list_store_clear (store);
|
||||
|
||||
gtk_widget_set_sensitive (dlg->word_entry, TRUE);
|
||||
|
||||
if (suggestions == NULL)
|
||||
{
|
||||
gtk_list_store_append (store, &iter);
|
||||
gtk_list_store_set (store, &iter,
|
||||
/* Translators: Displayed in the "Check Spelling" dialog if there are no suggestions
|
||||
* for the current misspelled word */
|
||||
COLUMN_SUGGESTIONS, _("(no suggested words)"),
|
||||
-1);
|
||||
|
||||
gtk_entry_set_text (GTK_ENTRY (dlg->word_entry), "");
|
||||
|
||||
gtk_widget_set_sensitive (dlg->suggestions_list, FALSE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_widget_set_sensitive (dlg->suggestions_list, TRUE);
|
||||
|
||||
gtk_entry_set_text (GTK_ENTRY (dlg->word_entry), (gchar*)suggestions->data);
|
||||
|
||||
while (suggestions != NULL)
|
||||
{
|
||||
gtk_list_store_append (store, &iter);
|
||||
gtk_list_store_set (store, &iter,
|
||||
COLUMN_SUGGESTIONS, (gchar*)suggestions->data,
|
||||
-1);
|
||||
|
||||
suggestions = g_slist_next (suggestions);
|
||||
}
|
||||
|
||||
sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->suggestions_list));
|
||||
gtk_tree_model_get_iter_first (dlg->suggestions_list_model, &iter);
|
||||
gtk_tree_selection_select_iter (sel, &iter);
|
||||
}
|
||||
|
||||
static void
|
||||
word_entry_changed_handler (GtkEditable *editable, XedSpellCheckerDialog *dlg)
|
||||
{
|
||||
const gchar *text;
|
||||
|
||||
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
|
||||
|
||||
text = gtk_entry_get_text (GTK_ENTRY (dlg->word_entry));
|
||||
|
||||
if (g_utf8_strlen (text, -1) > 0)
|
||||
{
|
||||
gtk_widget_set_sensitive (dlg->check_word_button, TRUE);
|
||||
gtk_widget_set_sensitive (dlg->change_button, TRUE);
|
||||
gtk_widget_set_sensitive (dlg->change_all_button, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_set_sensitive (dlg->check_word_button, FALSE);
|
||||
gtk_widget_set_sensitive (dlg->change_button, FALSE);
|
||||
gtk_widget_set_sensitive (dlg->change_all_button, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
close_button_clicked_handler (GtkButton *button, XedSpellCheckerDialog *dlg)
|
||||
{
|
||||
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
|
||||
|
||||
gtk_widget_destroy (GTK_WIDGET (dlg));
|
||||
}
|
||||
|
||||
static void
|
||||
suggestions_list_selection_changed_handler (GtkTreeSelection *selection,
|
||||
XedSpellCheckerDialog *dlg)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
GValue value = {0, };
|
||||
const gchar *text;
|
||||
|
||||
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
|
||||
|
||||
if (! gtk_tree_selection_get_selected (selection, NULL, &iter))
|
||||
return;
|
||||
|
||||
gtk_tree_model_get_value (dlg->suggestions_list_model, &iter,
|
||||
COLUMN_SUGGESTIONS,
|
||||
&value);
|
||||
|
||||
text = g_value_get_string (&value);
|
||||
|
||||
gtk_entry_set_text (GTK_ENTRY (dlg->word_entry), text);
|
||||
|
||||
g_value_unset (&value);
|
||||
}
|
||||
|
||||
static void
|
||||
check_word_button_clicked_handler (GtkButton *button, XedSpellCheckerDialog *dlg)
|
||||
{
|
||||
const gchar *word;
|
||||
gssize len;
|
||||
|
||||
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
|
||||
|
||||
word = gtk_entry_get_text (GTK_ENTRY (dlg->word_entry));
|
||||
len = strlen (word);
|
||||
g_return_if_fail (len > 0);
|
||||
|
||||
if (xed_spell_checker_check_word (dlg->spell_checker, word, len))
|
||||
{
|
||||
GtkListStore *store;
|
||||
GtkTreeIter iter;
|
||||
|
||||
store = GTK_LIST_STORE (dlg->suggestions_list_model);
|
||||
gtk_list_store_clear (store);
|
||||
|
||||
gtk_list_store_append (store, &iter);
|
||||
gtk_list_store_set (store, &iter,
|
||||
/* Translators: Displayed in the "Check Spelling" dialog if the current word isn't misspelled */
|
||||
COLUMN_SUGGESTIONS, _("(correct spelling)"),
|
||||
-1);
|
||||
|
||||
gtk_widget_set_sensitive (dlg->suggestions_list, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
GSList *sug;
|
||||
|
||||
sug = xed_spell_checker_get_suggestions (dlg->spell_checker,
|
||||
word,
|
||||
len);
|
||||
|
||||
update_suggestions_list_model (dlg, sug);
|
||||
|
||||
/* free the suggestion list */
|
||||
g_slist_foreach (sug, (GFunc)g_free, NULL);
|
||||
g_slist_free (sug);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_word_button_clicked_handler (GtkButton *button, XedSpellCheckerDialog *dlg)
|
||||
{
|
||||
gchar *word;
|
||||
|
||||
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
|
||||
g_return_if_fail (dlg->misspelled_word != NULL);
|
||||
|
||||
xed_spell_checker_add_word_to_personal (dlg->spell_checker,
|
||||
dlg->misspelled_word,
|
||||
-1);
|
||||
|
||||
word = g_strdup (dlg->misspelled_word);
|
||||
|
||||
g_signal_emit (G_OBJECT (dlg), signals [ADD_WORD_TO_PERSONAL], 0, word);
|
||||
|
||||
g_free (word);
|
||||
}
|
||||
|
||||
static void
|
||||
ignore_button_clicked_handler (GtkButton *button, XedSpellCheckerDialog *dlg)
|
||||
{
|
||||
gchar *word;
|
||||
|
||||
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
|
||||
g_return_if_fail (dlg->misspelled_word != NULL);
|
||||
|
||||
word = g_strdup (dlg->misspelled_word);
|
||||
|
||||
g_signal_emit (G_OBJECT (dlg), signals [IGNORE], 0, word);
|
||||
|
||||
g_free (word);
|
||||
}
|
||||
|
||||
static void
|
||||
ignore_all_button_clicked_handler (GtkButton *button, XedSpellCheckerDialog *dlg)
|
||||
{
|
||||
gchar *word;
|
||||
|
||||
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
|
||||
g_return_if_fail (dlg->misspelled_word != NULL);
|
||||
|
||||
xed_spell_checker_add_word_to_session (dlg->spell_checker,
|
||||
dlg->misspelled_word,
|
||||
-1);
|
||||
|
||||
word = g_strdup (dlg->misspelled_word);
|
||||
|
||||
g_signal_emit (G_OBJECT (dlg), signals [IGNORE_ALL], 0, word);
|
||||
|
||||
g_free (word);
|
||||
}
|
||||
|
||||
static void
|
||||
change_button_clicked_handler (GtkButton *button, XedSpellCheckerDialog *dlg)
|
||||
{
|
||||
const gchar *entry_text;
|
||||
gchar *change;
|
||||
gchar *word;
|
||||
|
||||
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
|
||||
g_return_if_fail (dlg->misspelled_word != NULL);
|
||||
|
||||
entry_text = gtk_entry_get_text (GTK_ENTRY (dlg->word_entry));
|
||||
g_return_if_fail (entry_text != NULL);
|
||||
g_return_if_fail (*entry_text != '\0');
|
||||
change = g_strdup (entry_text);
|
||||
|
||||
xed_spell_checker_set_correction (dlg->spell_checker,
|
||||
dlg->misspelled_word, -1,
|
||||
change, -1);
|
||||
|
||||
word = g_strdup (dlg->misspelled_word);
|
||||
|
||||
g_signal_emit (G_OBJECT (dlg), signals [CHANGE], 0, word, change);
|
||||
|
||||
g_free (word);
|
||||
g_free (change);
|
||||
}
|
||||
|
||||
/* double click on one of the suggestions is like clicking on "change" */
|
||||
static void
|
||||
suggestions_list_row_activated_handler (GtkTreeView *view,
|
||||
GtkTreePath *path,
|
||||
GtkTreeViewColumn *column,
|
||||
XedSpellCheckerDialog *dlg)
|
||||
{
|
||||
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
|
||||
|
||||
change_button_clicked_handler (GTK_BUTTON (dlg->change_button), dlg);
|
||||
}
|
||||
|
||||
static void
|
||||
change_all_button_clicked_handler (GtkButton *button, XedSpellCheckerDialog *dlg)
|
||||
{
|
||||
const gchar *entry_text;
|
||||
gchar *change;
|
||||
gchar *word;
|
||||
|
||||
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
|
||||
g_return_if_fail (dlg->misspelled_word != NULL);
|
||||
|
||||
entry_text = gtk_entry_get_text (GTK_ENTRY (dlg->word_entry));
|
||||
g_return_if_fail (entry_text != NULL);
|
||||
g_return_if_fail (*entry_text != '\0');
|
||||
change = g_strdup (entry_text);
|
||||
|
||||
xed_spell_checker_set_correction (dlg->spell_checker,
|
||||
dlg->misspelled_word, -1,
|
||||
change, -1);
|
||||
|
||||
word = g_strdup (dlg->misspelled_word);
|
||||
|
||||
g_signal_emit (G_OBJECT (dlg), signals [CHANGE_ALL], 0, word, change);
|
||||
|
||||
g_free (word);
|
||||
g_free (change);
|
||||
}
|
||||
|
||||
void
|
||||
xed_spell_checker_dialog_set_completed (XedSpellCheckerDialog *dlg)
|
||||
{
|
||||
gchar *tmp;
|
||||
|
||||
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
|
||||
|
||||
tmp = g_strdup_printf("<b>%s</b>", _("Completed spell checking"));
|
||||
gtk_label_set_label (GTK_LABEL (dlg->misspelled_word_label),
|
||||
tmp);
|
||||
g_free (tmp);
|
||||
|
||||
gtk_list_store_clear (GTK_LIST_STORE (dlg->suggestions_list_model));
|
||||
gtk_entry_set_text (GTK_ENTRY (dlg->word_entry), "");
|
||||
|
||||
gtk_widget_set_sensitive (dlg->word_entry, FALSE);
|
||||
gtk_widget_set_sensitive (dlg->check_word_button, FALSE);
|
||||
gtk_widget_set_sensitive (dlg->ignore_button, FALSE);
|
||||
gtk_widget_set_sensitive (dlg->ignore_all_button, FALSE);
|
||||
gtk_widget_set_sensitive (dlg->change_button, FALSE);
|
||||
gtk_widget_set_sensitive (dlg->change_all_button, FALSE);
|
||||
gtk_widget_set_sensitive (dlg->add_word_button, FALSE);
|
||||
gtk_widget_set_sensitive (dlg->suggestions_list, FALSE);
|
||||
}
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* xed-spell-checker-dialog.h
|
||||
* This file is part of xed
|
||||
*
|
||||
* Copyright (C) 2002 Paolo Maggi
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the xed Team, 2002. See the AUTHORS file for a
|
||||
* list of people on the xed Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*/
|
||||
|
||||
#ifndef __XED_SPELL_CHECKER_DIALOG_H__
|
||||
#define __XED_SPELL_CHECKER_DIALOG_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "xed-spell-checker.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define XED_TYPE_SPELL_CHECKER_DIALOG (xed_spell_checker_dialog_get_type ())
|
||||
#define XED_SPELL_CHECKER_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XED_TYPE_SPELL_CHECKER_DIALOG, XedSpellCheckerDialog))
|
||||
#define XED_SPELL_CHECKER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), XED_TYPE_SPELL_CHECKER_DIALOG, XedSpellCheckerDialog))
|
||||
#define XED_IS_SPELL_CHECKER_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XED_TYPE_SPELL_CHECKER_DIALOG))
|
||||
#define XED_IS_SPELL_CHECKER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_SPELL_CHECKER_DIALOG))
|
||||
#define XED_SPELL_CHECKER_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), XED_TYPE_SPELL_CHECKER_DIALOG, XedSpellCheckerDialog))
|
||||
|
||||
|
||||
typedef struct _XedSpellCheckerDialog XedSpellCheckerDialog;
|
||||
|
||||
typedef struct _XedSpellCheckerDialogClass XedSpellCheckerDialogClass;
|
||||
|
||||
struct _XedSpellCheckerDialogClass
|
||||
{
|
||||
GtkWindowClass parent_class;
|
||||
|
||||
/* Signals */
|
||||
void (*ignore) (XedSpellCheckerDialog *dlg,
|
||||
const gchar *word);
|
||||
void (*ignore_all) (XedSpellCheckerDialog *dlg,
|
||||
const gchar *word);
|
||||
void (*change) (XedSpellCheckerDialog *dlg,
|
||||
const gchar *word,
|
||||
const gchar *change_to);
|
||||
void (*change_all) (XedSpellCheckerDialog *dlg,
|
||||
const gchar *word,
|
||||
const gchar *change_to);
|
||||
void (*add_word_to_personal) (XedSpellCheckerDialog *dlg,
|
||||
const gchar *word);
|
||||
|
||||
};
|
||||
|
||||
GType xed_spell_checker_dialog_get_type (void) G_GNUC_CONST;
|
||||
|
||||
/* Constructors */
|
||||
GtkWidget *xed_spell_checker_dialog_new (const gchar *data_dir);
|
||||
GtkWidget *xed_spell_checker_dialog_new_from_spell_checker
|
||||
(XedSpellChecker *spell,
|
||||
const gchar *data_dir);
|
||||
|
||||
void xed_spell_checker_dialog_set_spell_checker
|
||||
(XedSpellCheckerDialog *dlg,
|
||||
XedSpellChecker *spell);
|
||||
void xed_spell_checker_dialog_set_misspelled_word
|
||||
(XedSpellCheckerDialog *dlg,
|
||||
const gchar* word,
|
||||
gint len);
|
||||
|
||||
void xed_spell_checker_dialog_set_completed
|
||||
(XedSpellCheckerDialog *dlg);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __XED_SPELL_CHECKER_DIALOG_H__ */
|
||||
|
|
@ -1,439 +0,0 @@
|
|||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* xed-spell-checker-language.c
|
||||
* This file is part of xed
|
||||
*
|
||||
* Copyright (C) 2006 Paolo Maggi
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the xed Team, 2006. See the AUTHORS file for a
|
||||
* list of people on the xed Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*/
|
||||
|
||||
/* Part of the code taked from Epiphany.
|
||||
*
|
||||
* Copyright (C) 2003, 2004 Christian Persch
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <enchant.h>
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <libxml/xmlreader.h>
|
||||
|
||||
#include "xed-spell-checker-language.h"
|
||||
|
||||
#include <xed/xed-debug.h>
|
||||
|
||||
#define ISO_639_DOMAIN "iso_639"
|
||||
#define ISO_3166_DOMAIN "iso_3166"
|
||||
|
||||
#define ISOCODESLOCALEDIR ISO_CODES_PREFIX "/share/locale"
|
||||
|
||||
struct _XedSpellCheckerLanguage
|
||||
{
|
||||
gchar *abrev;
|
||||
gchar *name;
|
||||
};
|
||||
|
||||
static gboolean available_languages_initialized = FALSE;
|
||||
static GSList *available_languages = NULL;
|
||||
|
||||
static GHashTable *iso_639_table = NULL;
|
||||
static GHashTable *iso_3166_table = NULL;
|
||||
|
||||
static void
|
||||
bind_iso_domains (void)
|
||||
{
|
||||
static gboolean bound = FALSE;
|
||||
|
||||
if (bound == FALSE)
|
||||
{
|
||||
bindtextdomain (ISO_639_DOMAIN, ISOCODESLOCALEDIR);
|
||||
bind_textdomain_codeset (ISO_639_DOMAIN, "UTF-8");
|
||||
|
||||
bindtextdomain(ISO_3166_DOMAIN, ISOCODESLOCALEDIR);
|
||||
bind_textdomain_codeset (ISO_3166_DOMAIN, "UTF-8");
|
||||
|
||||
bound = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
read_iso_639_entry (xmlTextReaderPtr reader,
|
||||
GHashTable *table)
|
||||
{
|
||||
xmlChar *code, *name;
|
||||
|
||||
code = xmlTextReaderGetAttribute (reader, (const xmlChar *) "iso_639_1_code");
|
||||
name = xmlTextReaderGetAttribute (reader, (const xmlChar *) "name");
|
||||
|
||||
/* Get iso-639-2 code */
|
||||
if (code == NULL || code[0] == '\0')
|
||||
{
|
||||
xmlFree (code);
|
||||
/* FIXME: use the 2T or 2B code? */
|
||||
code = xmlTextReaderGetAttribute (reader, (const xmlChar *) "iso_639_2T_code");
|
||||
}
|
||||
|
||||
if (code != NULL && code[0] != '\0' && name != NULL && name[0] != '\0')
|
||||
{
|
||||
g_hash_table_insert (table, code, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
xmlFree (code);
|
||||
xmlFree (name);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
read_iso_3166_entry (xmlTextReaderPtr reader,
|
||||
GHashTable *table)
|
||||
{
|
||||
xmlChar *code, *name;
|
||||
|
||||
code = xmlTextReaderGetAttribute (reader, (const xmlChar *) "alpha_2_code");
|
||||
name = xmlTextReaderGetAttribute (reader, (const xmlChar *) "name");
|
||||
|
||||
if (code != NULL && code[0] != '\0' && name != NULL && name[0] != '\0')
|
||||
{
|
||||
char *lcode;
|
||||
|
||||
lcode = g_ascii_strdown ((char *) code, -1);
|
||||
xmlFree (code);
|
||||
|
||||
/* g_print ("%s -> %s\n", lcode, name); */
|
||||
|
||||
g_hash_table_insert (table, lcode, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
xmlFree (code);
|
||||
xmlFree (name);
|
||||
}
|
||||
}
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STATE_START,
|
||||
STATE_STOP,
|
||||
STATE_ENTRIES,
|
||||
} ParserState;
|
||||
|
||||
static void
|
||||
load_iso_entries (int iso,
|
||||
GFunc read_entry_func,
|
||||
gpointer user_data)
|
||||
{
|
||||
xmlTextReaderPtr reader;
|
||||
ParserState state = STATE_START;
|
||||
xmlChar iso_entries[32], iso_entry[32];
|
||||
char *filename;
|
||||
int ret = -1;
|
||||
|
||||
xed_debug_message (DEBUG_PLUGINS, "Loading ISO-%d codes", iso);
|
||||
|
||||
filename = g_strdup_printf (ISO_CODES_PREFIX "/share/xml/iso-codes/iso_%d.xml", iso);
|
||||
reader = xmlNewTextReaderFilename (filename);
|
||||
if (reader == NULL) goto out;
|
||||
|
||||
xmlStrPrintf (iso_entries, sizeof (iso_entries), (const xmlChar *)"iso_%d_entries", iso);
|
||||
xmlStrPrintf (iso_entry, sizeof (iso_entry), (const xmlChar *)"iso_%d_entry", iso);
|
||||
|
||||
ret = xmlTextReaderRead (reader);
|
||||
|
||||
while (ret == 1)
|
||||
{
|
||||
const xmlChar *tag;
|
||||
xmlReaderTypes type;
|
||||
|
||||
tag = xmlTextReaderConstName (reader);
|
||||
type = xmlTextReaderNodeType (reader);
|
||||
|
||||
if (state == STATE_ENTRIES &&
|
||||
type == XML_READER_TYPE_ELEMENT &&
|
||||
xmlStrEqual (tag, iso_entry))
|
||||
{
|
||||
read_entry_func (reader, user_data);
|
||||
}
|
||||
else if (state == STATE_START &&
|
||||
type == XML_READER_TYPE_ELEMENT &&
|
||||
xmlStrEqual (tag, iso_entries))
|
||||
{
|
||||
state = STATE_ENTRIES;
|
||||
}
|
||||
else if (state == STATE_ENTRIES &&
|
||||
type == XML_READER_TYPE_END_ELEMENT &&
|
||||
xmlStrEqual (tag, iso_entries))
|
||||
{
|
||||
state = STATE_STOP;
|
||||
}
|
||||
else if (type == XML_READER_TYPE_SIGNIFICANT_WHITESPACE ||
|
||||
type == XML_READER_TYPE_WHITESPACE ||
|
||||
type == XML_READER_TYPE_TEXT ||
|
||||
type == XML_READER_TYPE_COMMENT)
|
||||
{
|
||||
/* eat it */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ignore it */
|
||||
}
|
||||
|
||||
ret = xmlTextReaderRead (reader);
|
||||
}
|
||||
|
||||
xmlFreeTextReader (reader);
|
||||
|
||||
out:
|
||||
if (ret < 0 || state != STATE_STOP)
|
||||
{
|
||||
g_warning ("Failed to load ISO-%d codes from %s!\n",
|
||||
iso, filename);
|
||||
}
|
||||
|
||||
g_free (filename);
|
||||
}
|
||||
|
||||
static GHashTable *
|
||||
create_iso_639_table (void)
|
||||
{
|
||||
GHashTable *table;
|
||||
|
||||
bind_iso_domains ();
|
||||
table = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
(GDestroyNotify) xmlFree,
|
||||
(GDestroyNotify) xmlFree);
|
||||
|
||||
load_iso_entries (639, (GFunc) read_iso_639_entry, table);
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
static GHashTable *
|
||||
create_iso_3166_table (void)
|
||||
{
|
||||
GHashTable *table;
|
||||
|
||||
bind_iso_domains ();
|
||||
table = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
(GDestroyNotify) g_free,
|
||||
(GDestroyNotify) xmlFree);
|
||||
|
||||
load_iso_entries (3166, (GFunc) read_iso_3166_entry, table);
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
static char *
|
||||
create_name_for_language (const char *code)
|
||||
{
|
||||
char **str;
|
||||
char *name = NULL;
|
||||
const char *langname, *localename;
|
||||
int len;
|
||||
|
||||
g_return_val_if_fail (iso_639_table != NULL, NULL);
|
||||
g_return_val_if_fail (iso_3166_table != NULL, NULL);
|
||||
|
||||
str = g_strsplit (code, "_", -1);
|
||||
len = g_strv_length (str);
|
||||
g_return_val_if_fail (len != 0, NULL);
|
||||
|
||||
langname = (const char *) g_hash_table_lookup (iso_639_table, str[0]);
|
||||
|
||||
if (len == 1 && langname != NULL)
|
||||
{
|
||||
name = g_strdup (dgettext (ISO_639_DOMAIN, langname));
|
||||
}
|
||||
else if (len == 2 && langname != NULL)
|
||||
{
|
||||
gchar *locale_code = g_ascii_strdown (str[1], -1);
|
||||
|
||||
localename = (const char *) g_hash_table_lookup (iso_3166_table, locale_code);
|
||||
g_free (locale_code);
|
||||
|
||||
if (localename != NULL)
|
||||
{
|
||||
/* Translators: the first %s is the language name, and
|
||||
* the second %s is the locale name. Example:
|
||||
* "French (France)"
|
||||
*/
|
||||
name = g_strdup_printf (C_("language", "%s (%s)"),
|
||||
dgettext (ISO_639_DOMAIN, langname),
|
||||
dgettext (ISO_3166_DOMAIN, localename));
|
||||
}
|
||||
else
|
||||
{
|
||||
name = g_strdup_printf (C_("language", "%s (%s)"),
|
||||
dgettext (ISO_639_DOMAIN, langname), str[1]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Translators: this refers to an unknown language code
|
||||
* (one which isn't in our built-in list).
|
||||
*/
|
||||
name = g_strdup_printf (C_("language", "Unknown (%s)"), code);
|
||||
}
|
||||
|
||||
g_strfreev (str);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
static void
|
||||
enumerate_dicts (const char * const lang_tag,
|
||||
const char * const provider_name,
|
||||
const char * const provider_desc,
|
||||
const char * const provider_file,
|
||||
void * user_data)
|
||||
{
|
||||
gchar *lang_name;
|
||||
|
||||
GTree *dicts = (GTree *)user_data;
|
||||
|
||||
lang_name = create_name_for_language (lang_tag);
|
||||
g_return_if_fail (lang_name != NULL);
|
||||
|
||||
/* g_print ("%s - %s\n", lang_tag, lang_name); */
|
||||
|
||||
g_tree_replace (dicts, g_strdup (lang_tag), lang_name);
|
||||
}
|
||||
|
||||
static gint
|
||||
key_cmp (gconstpointer a, gconstpointer b, gpointer user_data)
|
||||
{
|
||||
return strcmp (a, b);
|
||||
}
|
||||
|
||||
static gint
|
||||
lang_cmp (const XedSpellCheckerLanguage *a,
|
||||
const XedSpellCheckerLanguage *b)
|
||||
{
|
||||
return g_utf8_collate (a->name, b->name);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
build_langs_list (const gchar *key,
|
||||
const gchar *value,
|
||||
gpointer data)
|
||||
{
|
||||
XedSpellCheckerLanguage *lang = g_new (XedSpellCheckerLanguage, 1);
|
||||
|
||||
lang->abrev = g_strdup (key);
|
||||
lang->name = g_strdup (value);
|
||||
|
||||
available_languages = g_slist_insert_sorted (available_languages,
|
||||
lang,
|
||||
(GCompareFunc)lang_cmp);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const GSList *
|
||||
xed_spell_checker_get_available_languages (void)
|
||||
{
|
||||
EnchantBroker *broker;
|
||||
GTree *dicts;
|
||||
|
||||
if (available_languages_initialized)
|
||||
return available_languages;
|
||||
|
||||
g_return_val_if_fail (available_languages == NULL, NULL);
|
||||
|
||||
available_languages_initialized = TRUE;
|
||||
|
||||
broker = enchant_broker_init ();
|
||||
g_return_val_if_fail (broker != NULL, NULL);
|
||||
|
||||
/* Use a GTree to efficiently remove duplicates while building the list */
|
||||
dicts = g_tree_new_full (key_cmp,
|
||||
NULL,
|
||||
(GDestroyNotify)g_free,
|
||||
(GDestroyNotify)g_free);
|
||||
|
||||
iso_639_table = create_iso_639_table ();
|
||||
iso_3166_table = create_iso_3166_table ();
|
||||
|
||||
enchant_broker_list_dicts (broker, enumerate_dicts, dicts);
|
||||
|
||||
enchant_broker_free (broker);
|
||||
|
||||
g_hash_table_destroy (iso_639_table);
|
||||
g_hash_table_destroy (iso_3166_table);
|
||||
|
||||
iso_639_table = NULL;
|
||||
iso_3166_table = NULL;
|
||||
|
||||
g_tree_foreach (dicts, (GTraverseFunc)build_langs_list, NULL);
|
||||
|
||||
g_tree_destroy (dicts);
|
||||
|
||||
return available_languages;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
xed_spell_checker_language_to_string (const XedSpellCheckerLanguage *lang)
|
||||
{
|
||||
if (lang == NULL)
|
||||
/* Translators: this refers the Default language used by the
|
||||
* spell checker
|
||||
*/
|
||||
return C_("language", "Default");
|
||||
|
||||
return lang->name;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
xed_spell_checker_language_to_key (const XedSpellCheckerLanguage *lang)
|
||||
{
|
||||
g_return_val_if_fail (lang != NULL, NULL);
|
||||
|
||||
return lang->abrev;
|
||||
}
|
||||
|
||||
const XedSpellCheckerLanguage *
|
||||
xed_spell_checker_language_from_key (const gchar *key)
|
||||
{
|
||||
const GSList *langs;
|
||||
|
||||
g_return_val_if_fail (key != NULL, NULL);
|
||||
|
||||
langs = xed_spell_checker_get_available_languages ();
|
||||
|
||||
while (langs != NULL)
|
||||
{
|
||||
const XedSpellCheckerLanguage *l = (const XedSpellCheckerLanguage *)langs->data;
|
||||
|
||||
if (g_ascii_strcasecmp (key, l->abrev) == 0)
|
||||
return l;
|
||||
|
||||
langs = g_slist_next (langs);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* xed-spell-checker-language.h
|
||||
* This file is part of xed
|
||||
*
|
||||
* Copyright (C) 2006 Paolo Maggi
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the xed Team, 2006. See the AUTHORS file for a
|
||||
* list of people on the xed Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*/
|
||||
|
||||
#ifndef __XED_SPELL_CHECKER_LANGUAGE_H__
|
||||
#define __XED_SPELL_CHECKER_LANGUAGE_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _XedSpellCheckerLanguage XedSpellCheckerLanguage;
|
||||
|
||||
const gchar *xed_spell_checker_language_to_string (const XedSpellCheckerLanguage *lang);
|
||||
|
||||
const gchar *xed_spell_checker_language_to_key (const XedSpellCheckerLanguage *lang);
|
||||
|
||||
const XedSpellCheckerLanguage *xed_spell_checker_language_from_key (const gchar *key);
|
||||
|
||||
/* GSList contains "XedSpellCheckerLanguage*" items */
|
||||
const GSList *xed_spell_checker_get_available_languages
|
||||
(void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __XED_SPELL_CHECKER_LANGUAGE_H__ */
|
|
@ -1,520 +0,0 @@
|
|||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* xed-spell-checker.c
|
||||
* This file is part of xed
|
||||
*
|
||||
* Copyright (C) 2002-2006 Paolo Maggi
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the xed Team, 2002-2006. See the AUTHORS file for a
|
||||
* list of people on the xed Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <enchant.h>
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "xed-spell-checker.h"
|
||||
#include "xed-spell-utils.h"
|
||||
#include "xed-spell-marshal.h"
|
||||
|
||||
struct _XedSpellChecker
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
EnchantDict *dict;
|
||||
EnchantBroker *broker;
|
||||
const XedSpellCheckerLanguage *active_lang;
|
||||
};
|
||||
|
||||
/* GObject properties */
|
||||
enum {
|
||||
PROP_0 = 0,
|
||||
PROP_LANGUAGE,
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
/* Signals */
|
||||
enum {
|
||||
ADD_WORD_TO_PERSONAL = 0,
|
||||
ADD_WORD_TO_SESSION,
|
||||
SET_LANGUAGE,
|
||||
CLEAR_SESSION,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
G_DEFINE_TYPE(XedSpellChecker, xed_spell_checker, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
xed_spell_checker_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
/*
|
||||
XedSpellChecker *spell = XED_SPELL_CHECKER (object);
|
||||
*/
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_LANGUAGE:
|
||||
/* TODO */
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
xed_spell_checker_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
/*
|
||||
XedSpellChecker *spell = XED_SPELL_CHECKER (object);
|
||||
*/
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_LANGUAGE:
|
||||
/* TODO */
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
xed_spell_checker_finalize (GObject *object)
|
||||
{
|
||||
XedSpellChecker *spell_checker;
|
||||
|
||||
g_return_if_fail (XED_IS_SPELL_CHECKER (object));
|
||||
|
||||
spell_checker = XED_SPELL_CHECKER (object);
|
||||
|
||||
if (spell_checker->dict != NULL)
|
||||
enchant_broker_free_dict (spell_checker->broker, spell_checker->dict);
|
||||
|
||||
if (spell_checker->broker != NULL)
|
||||
enchant_broker_free (spell_checker->broker);
|
||||
|
||||
G_OBJECT_CLASS (xed_spell_checker_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
xed_spell_checker_class_init (XedSpellCheckerClass * klass)
|
||||
{
|
||||
GObjectClass *object_class;
|
||||
|
||||
object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->set_property = xed_spell_checker_set_property;
|
||||
object_class->get_property = xed_spell_checker_get_property;
|
||||
|
||||
object_class->finalize = xed_spell_checker_finalize;
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_LANGUAGE,
|
||||
g_param_spec_pointer ("language",
|
||||
"Language",
|
||||
"The language used by the spell checker",
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
signals[ADD_WORD_TO_PERSONAL] =
|
||||
g_signal_new ("add_word_to_personal",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (XedSpellCheckerClass, add_word_to_personal),
|
||||
NULL, NULL,
|
||||
xed_marshal_VOID__STRING_INT,
|
||||
G_TYPE_NONE,
|
||||
2,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_INT);
|
||||
|
||||
signals[ADD_WORD_TO_SESSION] =
|
||||
g_signal_new ("add_word_to_session",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (XedSpellCheckerClass, add_word_to_session),
|
||||
NULL, NULL,
|
||||
xed_marshal_VOID__STRING_INT,
|
||||
G_TYPE_NONE,
|
||||
2,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_INT);
|
||||
|
||||
signals[SET_LANGUAGE] =
|
||||
g_signal_new ("set_language",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (XedSpellCheckerClass, set_language),
|
||||
NULL, NULL,
|
||||
xed_marshal_VOID__POINTER,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
G_TYPE_POINTER);
|
||||
|
||||
signals[CLEAR_SESSION] =
|
||||
g_signal_new ("clear_session",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (XedSpellCheckerClass, clear_session),
|
||||
NULL, NULL,
|
||||
xed_marshal_VOID__VOID,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
}
|
||||
|
||||
static void
|
||||
xed_spell_checker_init (XedSpellChecker *spell_checker)
|
||||
{
|
||||
spell_checker->broker = enchant_broker_init ();
|
||||
spell_checker->dict = NULL;
|
||||
spell_checker->active_lang = NULL;
|
||||
}
|
||||
|
||||
XedSpellChecker *
|
||||
xed_spell_checker_new (void)
|
||||
{
|
||||
XedSpellChecker *spell;
|
||||
|
||||
spell = XED_SPELL_CHECKER (
|
||||
g_object_new (XED_TYPE_SPELL_CHECKER, NULL));
|
||||
|
||||
g_return_val_if_fail (spell != NULL, NULL);
|
||||
|
||||
return spell;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
lazy_init (XedSpellChecker *spell,
|
||||
const XedSpellCheckerLanguage *language)
|
||||
{
|
||||
if (spell->dict != NULL)
|
||||
return TRUE;
|
||||
|
||||
g_return_val_if_fail (spell->broker != NULL, FALSE);
|
||||
|
||||
spell->active_lang = NULL;
|
||||
|
||||
if (language != NULL)
|
||||
{
|
||||
spell->active_lang = language;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* First try to get a default language */
|
||||
const XedSpellCheckerLanguage *l;
|
||||
gint i = 0;
|
||||
const gchar * const *lang_tags = g_get_language_names ();
|
||||
|
||||
while (lang_tags [i])
|
||||
{
|
||||
l = xed_spell_checker_language_from_key (lang_tags [i]);
|
||||
|
||||
if (l != NULL)
|
||||
{
|
||||
spell->active_lang = l;
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Second try to get a default language */
|
||||
if (spell->active_lang == NULL)
|
||||
spell->active_lang = xed_spell_checker_language_from_key ("en_US");
|
||||
|
||||
/* Last try to get a default language */
|
||||
if (spell->active_lang == NULL)
|
||||
{
|
||||
const GSList *langs;
|
||||
langs = xed_spell_checker_get_available_languages ();
|
||||
if (langs != NULL)
|
||||
spell->active_lang = (const XedSpellCheckerLanguage *)langs->data;
|
||||
}
|
||||
|
||||
if (spell->active_lang != NULL)
|
||||
{
|
||||
const gchar *key;
|
||||
|
||||
key = xed_spell_checker_language_to_key (spell->active_lang);
|
||||
|
||||
spell->dict = enchant_broker_request_dict (spell->broker,
|
||||
key);
|
||||
}
|
||||
|
||||
if (spell->dict == NULL)
|
||||
{
|
||||
spell->active_lang = NULL;
|
||||
|
||||
if (language != NULL)
|
||||
g_warning ("Spell checker plugin: cannot select a default language.");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
xed_spell_checker_set_language (XedSpellChecker *spell,
|
||||
const XedSpellCheckerLanguage *language)
|
||||
{
|
||||
gboolean ret;
|
||||
|
||||
g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE);
|
||||
|
||||
if (spell->dict != NULL)
|
||||
{
|
||||
enchant_broker_free_dict (spell->broker, spell->dict);
|
||||
spell->dict = NULL;
|
||||
}
|
||||
|
||||
ret = lazy_init (spell, language);
|
||||
|
||||
if (ret)
|
||||
g_signal_emit (G_OBJECT (spell), signals[SET_LANGUAGE], 0, language);
|
||||
else
|
||||
g_warning ("Spell checker plugin: cannot use language %s.",
|
||||
xed_spell_checker_language_to_string (language));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const XedSpellCheckerLanguage *
|
||||
xed_spell_checker_get_language (XedSpellChecker *spell)
|
||||
{
|
||||
g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), NULL);
|
||||
|
||||
if (!lazy_init (spell, spell->active_lang))
|
||||
return NULL;
|
||||
|
||||
return spell->active_lang;
|
||||
}
|
||||
|
||||
gboolean
|
||||
xed_spell_checker_check_word (XedSpellChecker *spell,
|
||||
const gchar *word,
|
||||
gssize len)
|
||||
{
|
||||
gint enchant_result;
|
||||
gboolean res = FALSE;
|
||||
|
||||
g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE);
|
||||
g_return_val_if_fail (word != NULL, FALSE);
|
||||
|
||||
if (!lazy_init (spell, spell->active_lang))
|
||||
return FALSE;
|
||||
|
||||
if (len < 0)
|
||||
len = strlen (word);
|
||||
|
||||
if (strcmp (word, "xed") == 0)
|
||||
return TRUE;
|
||||
|
||||
if (xed_spell_utils_is_digit (word, len))
|
||||
return TRUE;
|
||||
|
||||
g_return_val_if_fail (spell->dict != NULL, FALSE);
|
||||
enchant_result = enchant_dict_check (spell->dict, word, len);
|
||||
|
||||
switch (enchant_result)
|
||||
{
|
||||
case -1:
|
||||
/* error */
|
||||
res = FALSE;
|
||||
|
||||
g_warning ("Spell checker plugin: error checking word '%s' (%s).",
|
||||
word, enchant_dict_get_error (spell->dict));
|
||||
|
||||
break;
|
||||
case 1:
|
||||
/* it is not in the directory */
|
||||
res = FALSE;
|
||||
break;
|
||||
case 0:
|
||||
/* is is in the directory */
|
||||
res = TRUE;
|
||||
break;
|
||||
default:
|
||||
g_return_val_if_reached (FALSE);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* return NULL on error or if no suggestions are found */
|
||||
GSList *
|
||||
xed_spell_checker_get_suggestions (XedSpellChecker *spell,
|
||||
const gchar *word,
|
||||
gssize len)
|
||||
{
|
||||
gchar **suggestions;
|
||||
size_t n_suggestions = 0;
|
||||
GSList *suggestions_list = NULL;
|
||||
gint i;
|
||||
|
||||
g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), NULL);
|
||||
g_return_val_if_fail (word != NULL, NULL);
|
||||
|
||||
if (!lazy_init (spell, spell->active_lang))
|
||||
return NULL;
|
||||
|
||||
g_return_val_if_fail (spell->dict != NULL, NULL);
|
||||
|
||||
if (len < 0)
|
||||
len = strlen (word);
|
||||
|
||||
suggestions = enchant_dict_suggest (spell->dict, word, len, &n_suggestions);
|
||||
|
||||
if (n_suggestions == 0)
|
||||
return NULL;
|
||||
|
||||
g_return_val_if_fail (suggestions != NULL, NULL);
|
||||
|
||||
for (i = 0; i < (gint)n_suggestions; i++)
|
||||
{
|
||||
suggestions_list = g_slist_prepend (suggestions_list,
|
||||
suggestions[i]);
|
||||
}
|
||||
|
||||
/* The single suggestions will be freed by the caller */
|
||||
g_free (suggestions);
|
||||
|
||||
suggestions_list = g_slist_reverse (suggestions_list);
|
||||
|
||||
return suggestions_list;
|
||||
}
|
||||
|
||||
gboolean
|
||||
xed_spell_checker_add_word_to_personal (XedSpellChecker *spell,
|
||||
const gchar *word,
|
||||
gssize len)
|
||||
{
|
||||
g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE);
|
||||
g_return_val_if_fail (word != NULL, FALSE);
|
||||
|
||||
if (!lazy_init (spell, spell->active_lang))
|
||||
return FALSE;
|
||||
|
||||
g_return_val_if_fail (spell->dict != NULL, FALSE);
|
||||
|
||||
if (len < 0)
|
||||
len = strlen (word);
|
||||
|
||||
enchant_dict_add_to_pwl (spell->dict, word, len);
|
||||
|
||||
g_signal_emit (G_OBJECT (spell), signals[ADD_WORD_TO_PERSONAL], 0, word, len);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
xed_spell_checker_add_word_to_session (XedSpellChecker *spell,
|
||||
const gchar *word,
|
||||
gssize len)
|
||||
{
|
||||
g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE);
|
||||
g_return_val_if_fail (word != NULL, FALSE);
|
||||
|
||||
if (!lazy_init (spell, spell->active_lang))
|
||||
return FALSE;
|
||||
|
||||
g_return_val_if_fail (spell->dict != NULL, FALSE);
|
||||
|
||||
if (len < 0)
|
||||
len = strlen (word);
|
||||
|
||||
enchant_dict_add_to_session (spell->dict, word, len);
|
||||
|
||||
g_signal_emit (G_OBJECT (spell), signals[ADD_WORD_TO_SESSION], 0, word, len);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
xed_spell_checker_clear_session (XedSpellChecker *spell)
|
||||
{
|
||||
g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE);
|
||||
|
||||
/* free and re-request dictionary */
|
||||
if (spell->dict != NULL)
|
||||
{
|
||||
enchant_broker_free_dict (spell->broker, spell->dict);
|
||||
spell->dict = NULL;
|
||||
}
|
||||
|
||||
if (!lazy_init (spell, spell->active_lang))
|
||||
return FALSE;
|
||||
|
||||
g_signal_emit (G_OBJECT (spell), signals[CLEAR_SESSION], 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Informs dictionary, that word 'word' will be replaced/corrected by word
|
||||
* 'replacement'
|
||||
*/
|
||||
gboolean
|
||||
xed_spell_checker_set_correction (XedSpellChecker *spell,
|
||||
const gchar *word,
|
||||
gssize w_len,
|
||||
const gchar *replacement,
|
||||
gssize r_len)
|
||||
{
|
||||
g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE);
|
||||
g_return_val_if_fail (word != NULL, FALSE);
|
||||
g_return_val_if_fail (replacement != NULL, FALSE);
|
||||
|
||||
if (!lazy_init (spell, spell->active_lang))
|
||||
return FALSE;
|
||||
|
||||
g_return_val_if_fail (spell->dict != NULL, FALSE);
|
||||
|
||||
if (w_len < 0)
|
||||
w_len = strlen (word);
|
||||
|
||||
if (r_len < 0)
|
||||
r_len = strlen (replacement);
|
||||
|
||||
enchant_dict_store_replacement (spell->dict,
|
||||
word,
|
||||
w_len,
|
||||
replacement,
|
||||
r_len);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* xed-spell-checker.h
|
||||
* This file is part of xed
|
||||
*
|
||||
* Copyright (C) 2002-2006 Paolo Maggi
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the xed Team, 2002. See the AUTHORS file for a
|
||||
* list of people on the xed Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*/
|
||||
|
||||
#ifndef __XED_SPELL_CHECKER_H__
|
||||
#define __XED_SPELL_CHECKER_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "xed-spell-checker-language.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define XED_TYPE_SPELL_CHECKER (xed_spell_checker_get_type ())
|
||||
#define XED_SPELL_CHECKER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XED_TYPE_SPELL_CHECKER, XedSpellChecker))
|
||||
#define XED_SPELL_CHECKER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), XED_TYPE_SPELL_CHECKER, XedSpellChecker))
|
||||
#define XED_IS_SPELL_CHECKER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XED_TYPE_SPELL_CHECKER))
|
||||
#define XED_IS_SPELL_CHECKER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_SPELL_CHECKER))
|
||||
#define XED_SPELL_CHECKER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), XED_TYPE_SPELL_CHECKER, XedSpellChecker))
|
||||
|
||||
typedef struct _XedSpellChecker XedSpellChecker;
|
||||
|
||||
typedef struct _XedSpellCheckerClass XedSpellCheckerClass;
|
||||
|
||||
struct _XedSpellCheckerClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
/* Signals */
|
||||
void (*add_word_to_personal) (XedSpellChecker *spell,
|
||||
const gchar *word,
|
||||
gint len);
|
||||
|
||||
void (*add_word_to_session) (XedSpellChecker *spell,
|
||||
const gchar *word,
|
||||
gint len);
|
||||
|
||||
void (*set_language) (XedSpellChecker *spell,
|
||||
const XedSpellCheckerLanguage *lang);
|
||||
|
||||
void (*clear_session) (XedSpellChecker *spell);
|
||||
};
|
||||
|
||||
|
||||
GType xed_spell_checker_get_type (void) G_GNUC_CONST;
|
||||
|
||||
/* Constructors */
|
||||
XedSpellChecker *xed_spell_checker_new (void);
|
||||
|
||||
gboolean xed_spell_checker_set_language (XedSpellChecker *spell,
|
||||
const XedSpellCheckerLanguage *lang);
|
||||
const XedSpellCheckerLanguage
|
||||
*xed_spell_checker_get_language (XedSpellChecker *spell);
|
||||
|
||||
gboolean xed_spell_checker_check_word (XedSpellChecker *spell,
|
||||
const gchar *word,
|
||||
gssize len);
|
||||
|
||||
GSList *xed_spell_checker_get_suggestions (XedSpellChecker *spell,
|
||||
const gchar *word,
|
||||
gssize len);
|
||||
|
||||
gboolean xed_spell_checker_add_word_to_personal
|
||||
(XedSpellChecker *spell,
|
||||
const gchar *word,
|
||||
gssize len);
|
||||
|
||||
gboolean xed_spell_checker_add_word_to_session
|
||||
(XedSpellChecker *spell,
|
||||
const gchar *word,
|
||||
gssize len);
|
||||
|
||||
gboolean xed_spell_checker_clear_session (XedSpellChecker *spell);
|
||||
|
||||
gboolean xed_spell_checker_set_correction (XedSpellChecker *spell,
|
||||
const gchar *word,
|
||||
gssize w_len,
|
||||
const gchar *replacement,
|
||||
gssize r_len);
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __XED_SPELL_CHECKER_H__ */
|
||||
|
|
@ -1,284 +0,0 @@
|
|||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* xed-spell-language-dialog.c
|
||||
* This file is part of xed
|
||||
*
|
||||
* Copyright (C) 2002 Paolo Maggi
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the xed Team, 2002. See the AUTHORS file for a
|
||||
* list of people on the xed Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <xed/xed-utils.h>
|
||||
#include <xed/xed-app.h>
|
||||
#include "xed-spell-language-dialog.h"
|
||||
#include "xed-spell-checker-language.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
COLUMN_LANGUAGE_NAME = 0,
|
||||
COLUMN_LANGUAGE_POINTER,
|
||||
ENCODING_NUM_COLS
|
||||
};
|
||||
|
||||
|
||||
struct _XedSpellLanguageDialog
|
||||
{
|
||||
GtkDialog dialog;
|
||||
|
||||
GtkWidget *languages_treeview;
|
||||
GtkTreeModel *model;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (XedSpellLanguageDialog, xed_spell_language_dialog, GTK_TYPE_DIALOG)
|
||||
|
||||
|
||||
static void
|
||||
xed_spell_language_dialog_class_init (XedSpellLanguageDialogClass *klass)
|
||||
{
|
||||
/* GObjectClass *object_class = G_OBJECT_CLASS (klass); */
|
||||
}
|
||||
|
||||
static void
|
||||
dialog_response_handler (GtkDialog *dlg,
|
||||
gint res_id)
|
||||
{
|
||||
if (res_id == GTK_RESPONSE_HELP)
|
||||
{
|
||||
xed_app_show_help (XED_APP (g_application_get_default ()), GTK_WINDOW (dlg), NULL, "xed-spell-checker-plugin");
|
||||
|
||||
g_signal_stop_emission_by_name (dlg, "response");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
scroll_to_selected (GtkTreeView *tree_view)
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
GtkTreeSelection *selection;
|
||||
GtkTreeIter iter;
|
||||
|
||||
model = gtk_tree_view_get_model (tree_view);
|
||||
g_return_if_fail (model != NULL);
|
||||
|
||||
/* Scroll to selected */
|
||||
selection = gtk_tree_view_get_selection (tree_view);
|
||||
g_return_if_fail (selection != NULL);
|
||||
|
||||
if (gtk_tree_selection_get_selected (selection, NULL, &iter))
|
||||
{
|
||||
GtkTreePath* path;
|
||||
|
||||
path = gtk_tree_model_get_path (model, &iter);
|
||||
g_return_if_fail (path != NULL);
|
||||
|
||||
gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 1.0, 0.0);
|
||||
gtk_tree_path_free (path);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
language_row_activated (GtkTreeView *tree_view,
|
||||
GtkTreePath *path,
|
||||
GtkTreeViewColumn *column,
|
||||
XedSpellLanguageDialog *dialog)
|
||||
{
|
||||
gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
|
||||
}
|
||||
|
||||
static void
|
||||
create_dialog (XedSpellLanguageDialog *dlg,
|
||||
const gchar *data_dir)
|
||||
{
|
||||
GtkWidget *error_widget;
|
||||
GtkWidget *content;
|
||||
gboolean ret;
|
||||
GtkCellRenderer *cell;
|
||||
GtkTreeViewColumn *column;
|
||||
gchar *ui_file;
|
||||
gchar *root_objects[] = {
|
||||
"content",
|
||||
NULL
|
||||
};
|
||||
|
||||
gtk_dialog_add_buttons (GTK_DIALOG (dlg),
|
||||
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
||||
_("_OK"), GTK_RESPONSE_OK,
|
||||
_("_Help"), GTK_RESPONSE_HELP,
|
||||
NULL);
|
||||
|
||||
gtk_window_set_title (GTK_WINDOW (dlg), _("Set language"));
|
||||
gtk_window_set_modal (GTK_WINDOW (dlg), TRUE);
|
||||
gtk_window_set_destroy_with_parent (GTK_WINDOW (dlg), TRUE);
|
||||
|
||||
/* HIG defaults */
|
||||
gtk_container_set_border_width (GTK_CONTAINER (dlg), 5);
|
||||
gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))), 2);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (gtk_dialog_get_action_area (GTK_DIALOG (dlg))), 5);
|
||||
gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_action_area (GTK_DIALOG (dlg))), 6);
|
||||
|
||||
g_signal_connect (dlg, "response",
|
||||
G_CALLBACK (dialog_response_handler), NULL);
|
||||
|
||||
ui_file = g_build_filename (data_dir, "languages-dialog.ui", NULL);
|
||||
ret = xed_utils_get_ui_objects (ui_file,
|
||||
root_objects,
|
||||
&error_widget,
|
||||
"content", &content,
|
||||
"languages_treeview", &dlg->languages_treeview,
|
||||
NULL);
|
||||
g_free (ui_file);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
gtk_widget_show (error_widget);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))), error_widget, TRUE, TRUE, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))), content, TRUE, TRUE, 0);
|
||||
g_object_unref (content);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (content), 5);
|
||||
|
||||
dlg->model = GTK_TREE_MODEL (gtk_list_store_new (ENCODING_NUM_COLS, G_TYPE_STRING, G_TYPE_POINTER));
|
||||
|
||||
gtk_tree_view_set_model (GTK_TREE_VIEW (dlg->languages_treeview), dlg->model);
|
||||
|
||||
g_object_unref (dlg->model);
|
||||
|
||||
/* Add the encoding column */
|
||||
cell = gtk_cell_renderer_text_new ();
|
||||
column = gtk_tree_view_column_new_with_attributes (_("Languages"),
|
||||
cell,
|
||||
"text",
|
||||
COLUMN_LANGUAGE_NAME,
|
||||
NULL);
|
||||
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (dlg->languages_treeview), column);
|
||||
|
||||
gtk_tree_view_set_search_column (GTK_TREE_VIEW (dlg->languages_treeview), COLUMN_LANGUAGE_NAME);
|
||||
|
||||
g_signal_connect (dlg->languages_treeview, "realize",
|
||||
G_CALLBACK (scroll_to_selected), dlg);
|
||||
g_signal_connect (dlg->languages_treeview, "row-activated",
|
||||
G_CALLBACK (language_row_activated), dlg);
|
||||
}
|
||||
|
||||
static void
|
||||
xed_spell_language_dialog_init (XedSpellLanguageDialog *dlg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
populate_language_list (XedSpellLanguageDialog *dlg,
|
||||
const XedSpellCheckerLanguage *cur_lang)
|
||||
{
|
||||
GtkListStore *store;
|
||||
GtkTreeIter iter;
|
||||
|
||||
const GSList* langs;
|
||||
|
||||
/* create list store */
|
||||
store = GTK_LIST_STORE (dlg->model);
|
||||
|
||||
langs = xed_spell_checker_get_available_languages ();
|
||||
|
||||
while (langs)
|
||||
{
|
||||
const gchar *name;
|
||||
|
||||
name = xed_spell_checker_language_to_string ((const XedSpellCheckerLanguage*)langs->data);
|
||||
|
||||
gtk_list_store_append (store, &iter);
|
||||
gtk_list_store_set (store, &iter,
|
||||
COLUMN_LANGUAGE_NAME, name,
|
||||
COLUMN_LANGUAGE_POINTER, langs->data,
|
||||
-1);
|
||||
|
||||
if (langs->data == cur_lang)
|
||||
{
|
||||
GtkTreeSelection *selection;
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->languages_treeview));
|
||||
g_return_if_fail (selection != NULL);
|
||||
|
||||
gtk_tree_selection_select_iter (selection, &iter);
|
||||
}
|
||||
|
||||
langs = g_slist_next (langs);
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
xed_spell_language_dialog_new (GtkWindow *parent,
|
||||
const XedSpellCheckerLanguage *cur_lang,
|
||||
const gchar *data_dir)
|
||||
{
|
||||
XedSpellLanguageDialog *dlg;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_WINDOW (parent), NULL);
|
||||
|
||||
dlg = g_object_new (XED_TYPE_SPELL_LANGUAGE_DIALOG, NULL);
|
||||
|
||||
create_dialog (dlg, data_dir);
|
||||
|
||||
populate_language_list (dlg, cur_lang);
|
||||
|
||||
gtk_window_set_transient_for (GTK_WINDOW (dlg), parent);
|
||||
gtk_widget_grab_focus (dlg->languages_treeview);
|
||||
|
||||
return GTK_WIDGET (dlg);
|
||||
}
|
||||
|
||||
const XedSpellCheckerLanguage *
|
||||
xed_spell_language_get_selected_language (XedSpellLanguageDialog *dlg)
|
||||
{
|
||||
GValue value = {0, };
|
||||
const XedSpellCheckerLanguage* lang;
|
||||
|
||||
GtkTreeIter iter;
|
||||
GtkTreeSelection *selection;
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->languages_treeview));
|
||||
g_return_val_if_fail (selection != NULL, NULL);
|
||||
|
||||
if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gtk_tree_model_get_value (dlg->model, &iter, COLUMN_LANGUAGE_POINTER, &value);
|
||||
|
||||
lang = (const XedSpellCheckerLanguage* ) g_value_get_pointer (&value);
|
||||
|
||||
return lang;
|
||||
}
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* xed-spell-language-dialog.h
|
||||
* This file is part of xed
|
||||
*
|
||||
* Copyright (C) 2002 Paolo Maggi
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the xed Team, 2002. See the AUTHORS file for a
|
||||
* list of people on the xed Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*/
|
||||
|
||||
#ifndef __XED_SPELL_LANGUAGE_DIALOG_H__
|
||||
#define __XED_SPELL_LANGUAGE_DIALOG_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "xed-spell-checker-language.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define XED_TYPE_SPELL_LANGUAGE_DIALOG (xed_spell_language_dialog_get_type())
|
||||
#define XED_SPELL_LANGUAGE_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XED_TYPE_SPELL_LANGUAGE_DIALOG, XedSpellLanguageDialog))
|
||||
#define XED_SPELL_LANGUAGE_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XED_TYPE_SPELL_LANGUAGE_DIALOG, XedSpellLanguageDialogClass))
|
||||
#define XED_IS_SPELL_LANGUAGE_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XED_TYPE_SPELL_LANGUAGE_DIALOG))
|
||||
#define XED_IS_SPELL_LANGUAGE_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_SPELL_LANGUAGE_DIALOG))
|
||||
#define XED_SPELL_LANGUAGE_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XED_TYPE_SPELL_LANGUAGE_DIALOG, XedSpellLanguageDialogClass))
|
||||
|
||||
|
||||
typedef struct _XedSpellLanguageDialog XedSpellLanguageDialog;
|
||||
typedef struct _XedSpellLanguageDialogClass XedSpellLanguageDialogClass;
|
||||
|
||||
struct _XedSpellLanguageDialogClass
|
||||
{
|
||||
GtkDialogClass parent_class;
|
||||
};
|
||||
|
||||
GType xed_spell_language_dialog_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget *xed_spell_language_dialog_new (GtkWindow *parent,
|
||||
const XedSpellCheckerLanguage *cur_lang,
|
||||
const gchar *data_dir);
|
||||
|
||||
const XedSpellCheckerLanguage *xed_spell_language_get_selected_language (XedSpellLanguageDialog *dlg);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __XED_SPELL_LANGUAGE_DIALOG_H__ */
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,94 +0,0 @@
|
|||
/*
|
||||
* xed-spell-utils.c
|
||||
* This file is part of xed
|
||||
*
|
||||
* Copyright (C) 2010 - Jesse van den Kieboom
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "xed-spell-utils.h"
|
||||
#include <gtksourceview/gtksource.h>
|
||||
|
||||
gboolean
|
||||
xed_spell_utils_is_digit (const char *text, gssize length)
|
||||
{
|
||||
gunichar c;
|
||||
const gchar *p;
|
||||
const gchar *end;
|
||||
|
||||
g_return_val_if_fail (text != NULL, FALSE);
|
||||
|
||||
if (length < 0)
|
||||
length = strlen (text);
|
||||
|
||||
p = text;
|
||||
end = text + length;
|
||||
|
||||
while (p != end) {
|
||||
const gchar *next;
|
||||
next = g_utf8_next_char (p);
|
||||
|
||||
c = g_utf8_get_char (p);
|
||||
|
||||
if (!g_unichar_isdigit (c) && c != '.' && c != ',')
|
||||
return FALSE;
|
||||
|
||||
p = next;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
xed_spell_utils_skip_no_spell_check (GtkTextIter *start,
|
||||
GtkTextIter *end)
|
||||
{
|
||||
GtkSourceBuffer *buffer = GTK_SOURCE_BUFFER (gtk_text_iter_get_buffer (start));
|
||||
|
||||
while (gtk_source_buffer_iter_has_context_class (buffer, start, "no-spell-check"))
|
||||
{
|
||||
GtkTextIter last = *start;
|
||||
|
||||
if (!gtk_source_buffer_iter_forward_to_context_class_toggle (buffer, start, "no-spell-check"))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (gtk_text_iter_compare (start, &last) <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gtk_text_iter_forward_word_end (start);
|
||||
gtk_text_iter_backward_word_start (start);
|
||||
|
||||
if (gtk_text_iter_compare (start, &last) <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (gtk_text_iter_compare (start, end) >= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* xed-spell-utils.h
|
||||
* This file is part of xed
|
||||
*
|
||||
* Copyright (C) 2010 - Jesse van den Kieboom
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __XED_SPELL_UTILS_H__
|
||||
#define __XED_SPELL_UTILS_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
gboolean xed_spell_utils_is_digit (const char *text, gssize length);
|
||||
|
||||
gboolean xed_spell_utils_skip_no_spell_check (GtkTextIter *start, GtkTextIter *end);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __XED_SPELL_UTILS_H__ */
|
||||
|
|
@ -40,10 +40,12 @@ NOINST_H_FILES = \
|
|||
xed-close-button.h \
|
||||
xed-close-confirmation-dialog.h \
|
||||
xed-dirs.h \
|
||||
xed-document-private.h \
|
||||
xed-documents-panel.h \
|
||||
xed-encodings-dialog.h \
|
||||
xed-history-entry.h \
|
||||
xed-io-error-info-bar.h \
|
||||
xed-metadata-manager.h \
|
||||
xed-paned.h \
|
||||
xed-plugins-engine.h \
|
||||
xed-preferences-dialog.h \
|
||||
|
@ -80,10 +82,6 @@ INST_H_FILES = \
|
|||
xed-window.h \
|
||||
xed-window-activatable.h
|
||||
|
||||
if !ENABLE_GVFS_METADATA
|
||||
NOINST_H_FILES += xed-metadata-manager.h
|
||||
endif
|
||||
|
||||
headerdir = $(prefix)/include/xed
|
||||
|
||||
header_DATA = \
|
||||
|
@ -119,6 +117,7 @@ libxed_c_files = \
|
|||
xed-message-bus.c \
|
||||
xed-message-type.c \
|
||||
xed-message.c \
|
||||
xed-metadata-manager.c \
|
||||
xed-notebook.c \
|
||||
xed-paned.c \
|
||||
xed-panel.c \
|
||||
|
@ -146,10 +145,6 @@ libxed_la_SOURCES = \
|
|||
$(NOINST_H_FILES) \
|
||||
$(INST_H_FILES)
|
||||
|
||||
if !ENABLE_GVFS_METADATA
|
||||
libxed_la_SOURCES += xed-metadata-manager.c
|
||||
endif
|
||||
|
||||
xed-enum-types.h: xed-enum-types.h.template $(INST_H_FILES) $(GLIB_MKENUMS)
|
||||
$(AM_V_GEN) (cd $(srcdir) && $(GLIB_MKENUMS) --template xed-enum-types.h.template $(INST_H_FILES)) > $@
|
||||
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
.xed-map-frame:dir(ltr) {
|
||||
.xed-map-frame:dir(ltr) border {
|
||||
border-width: 0 0 0 1px;
|
||||
}
|
||||
|
||||
.xed-map-frame:dir(rtl) {
|
||||
.xed-map-frame:dir(rtl) border {
|
||||
border-width: 0 1px 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.xed-searchbar .close-button {
|
||||
padding: 0;
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
.xed-window .primary-toolbar {
|
||||
border: 0px solid @borders;
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
|
||||
.xed-statusbar {
|
||||
border: 0px solid @borders;
|
||||
border-top-width: 1px;
|
||||
}
|
||||
|
||||
.xed-searchbar {
|
||||
box-shadow: inset 0 1px @borders;
|
||||
}
|
||||
|
||||
.xed-statusbar button {
|
||||
padding: 0 4px;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,335 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 3.17 -->
|
||||
<object class="GtkShortcutsWindow" id="shortcuts-xed">
|
||||
<property name="modal">1</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsSection">
|
||||
<property name="visible">1</property>
|
||||
<property name="section-name">shortcuts</property>
|
||||
<property name="max-height">12</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsGroup">
|
||||
<property name="visible">1</property>
|
||||
<property name="title" translatable="yes">Documents</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl>N</property>
|
||||
<property name="title" translatable="yes">Create a new document</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl>O</property>
|
||||
<property name="title" translatable="yes">Open a document</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl>S</property>
|
||||
<property name="title" translatable="yes">Save the document</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl><shift>S</property>
|
||||
<property name="title" translatable="yes">Save the document with a new filename</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl><shift>L</property>
|
||||
<property name="title" translatable="yes">Save all the documents</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl>W</property>
|
||||
<property name="title" translatable="yes">Close the document</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl><shift>W</property>
|
||||
<property name="title" translatable="yes">Close all the documents</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl><Alt>Page_Down</property>
|
||||
<property name="title" translatable="yes">Switch to the next document</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl><Alt>Page_Up</property>
|
||||
<property name="title" translatable="yes">Switch to the previous document</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><Alt>1...9</property>
|
||||
<property name="title" translatable="yes">Switch to the first - ninth document</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsGroup">
|
||||
<property name="visible">1</property>
|
||||
<property name="title" translatable="yes">Windows and Panes</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator">F9</property>
|
||||
<property name="title" translatable="yes">Show side pane</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl>F9</property>
|
||||
<property name="title" translatable="yes">Show bottom pane</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator">F11</property>
|
||||
<property name="title" translatable="yes">Fullscreen on / off</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl>Q</property>
|
||||
<property name="title" translatable="yes">Quit the application</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsGroup">
|
||||
<property name="visible">1</property>
|
||||
<property name="title" translatable="yes">Find and Replace</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl>F</property>
|
||||
<property name="title" translatable="yes">Find</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl>G</property>
|
||||
<property name="title" translatable="yes">Find the next match</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl><Shift>G</property>
|
||||
<property name="title" translatable="yes">Find the previous match</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl>H</property>
|
||||
<property name="title" translatable="yes">Find and Replace</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl>I</property>
|
||||
<property name="title" translatable="yes">Go to line</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsGroup">
|
||||
<property name="visible">1</property>
|
||||
<property name="title" translatable="yes">Copy and Paste</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl>C</property>
|
||||
<property name="title" translatable="yes">Copy selected text to clipboard</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl>X</property>
|
||||
<property name="title" translatable="yes">Cut selected text to clipboard</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl>V</property>
|
||||
<property name="title" translatable="yes">Paste text from clipboard</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsGroup">
|
||||
<property name="visible">1</property>
|
||||
<property name="title" translatable="yes">Undo and Redo</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl>Z</property>
|
||||
<property name="title" translatable="yes">Undo previous command</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl>Y</property>
|
||||
<property name="title" translatable="yes">Redo previous command</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsGroup">
|
||||
<property name="visible">1</property>
|
||||
<property name="title" translatable="yes">Selection</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl>A</property>
|
||||
<property name="title" translatable="yes">Select all text</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsGroup">
|
||||
<property name="visible">1</property>
|
||||
<property name="title" translatable="yes">Tools</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><shift>F7</property>
|
||||
<property name="title" translatable="yes">Check spelling</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl>P</property>
|
||||
<property name="title" translatable="yes">Print the document</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsGroup">
|
||||
<property name="visible">1</property>
|
||||
<property name="title" translatable="yes">Editing</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator">Insert</property>
|
||||
<property name="title" translatable="yes">Toggle insert / overwrite</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl>D</property>
|
||||
<property name="title" translatable="yes">Delete current line</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><alt>Up</property>
|
||||
<property name="title" translatable="yes">Move current line up</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><alt>Down</property>
|
||||
<property name="title" translatable="yes">Move current line down</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><alt>Left</property>
|
||||
<property name="title" translatable="yes">Move current word left</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><alt>Right</property>
|
||||
<property name="title" translatable="yes">Move current word right</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl>U</property>
|
||||
<property name="title" translatable="yes">Convert to uppercase</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl>L</property>
|
||||
<property name="title" translatable="yes">Convert to lowercase</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl>T</property>
|
||||
<property name="title" translatable="yes">Convert to title case</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl>asciitilde</property>
|
||||
<property name="title" translatable="yes">Invert case</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl><shift>a</property>
|
||||
<property name="title" translatable="yes">Increment number at cursor</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">1</property>
|
||||
<property name="accelerator"><ctrl><shift>x</property>
|
||||
<property name="title" translatable="yes">Decrement number at cursor</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
|
@ -123,6 +123,8 @@
|
|||
<menu name="HelpMenu" action="Help">
|
||||
<menuitem name="HelpContentsMenu" action="HelpContents"/>
|
||||
<menuitem name="HelpAboutMenu" action="HelpAbout"/>
|
||||
<menuitem name="HelpAboutMenu" action="HelpAbout"/>
|
||||
<menuitem name="HelpShortcutsMenu" action="HelpShortcuts"/>
|
||||
</menu>
|
||||
</menubar>
|
||||
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
<file preprocess="xml-stripblanks">ui/xed-preferences-dialog.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/xed-print-preferences.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/xed-searchbar.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/xed-shortcuts.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/xed-view-frame.ui</file>
|
||||
<file>css/xed-style.css</file>
|
||||
<file>css/xed.adwaita.css</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
</gresources>
|
||||
|
|
|
@ -223,6 +223,54 @@ set_initial_theme_style (XedApp *app)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
theme_changed (GtkSettings *settings,
|
||||
GParamSpec *pspec,
|
||||
gpointer data)
|
||||
{
|
||||
static GtkCssProvider *provider;
|
||||
gchar *theme;
|
||||
GdkScreen *screen;
|
||||
|
||||
g_object_get (settings, "gtk-theme-name", &theme, NULL);
|
||||
screen = gdk_screen_get_default ();
|
||||
|
||||
if (g_str_equal (theme, "Adwaita"))
|
||||
{
|
||||
if (provider == NULL)
|
||||
{
|
||||
GFile *file;
|
||||
|
||||
provider = gtk_css_provider_new ();
|
||||
file = g_file_new_for_uri ("resource:///org/x/editor/css/xed.adwaita.css");
|
||||
gtk_css_provider_load_from_file (provider, file, NULL);
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
gtk_style_context_add_provider_for_screen (screen,
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||
}
|
||||
else if (provider != NULL)
|
||||
{
|
||||
gtk_style_context_remove_provider_for_screen (screen, GTK_STYLE_PROVIDER (provider));
|
||||
g_clear_object (&provider);
|
||||
}
|
||||
|
||||
g_free (theme);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_theme_extensions (void)
|
||||
{
|
||||
GtkSettings *settings;
|
||||
|
||||
settings = gtk_settings_get_default ();
|
||||
g_signal_connect (settings, "notify::gtk-theme-name",
|
||||
G_CALLBACK (theme_changed), NULL);
|
||||
theme_changed (settings, NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
xed_app_startup (GApplication *application)
|
||||
{
|
||||
|
@ -251,6 +299,8 @@ xed_app_startup (GApplication *application)
|
|||
gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), icon_dir);
|
||||
g_free (icon_dir);
|
||||
|
||||
setup_theme_extensions ();
|
||||
|
||||
#ifndef ENABLE_GVFS_METADATA
|
||||
/* Setup metadata-manager */
|
||||
cache_dir = xed_dirs_get_user_cache_dir ();
|
||||
|
|
|
@ -32,10 +32,13 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "xed-close-confirmation-dialog.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "xed-close-confirmation-dialog.h"
|
||||
#include <xed/xed-app.h>
|
||||
#include <xed/xed-document.h>
|
||||
#include <xed/xed-document-private.h>
|
||||
#include <xed/xed-utils.h>
|
||||
#include <xed/xed-window.h>
|
||||
|
||||
|
|
|
@ -38,31 +38,27 @@
|
|||
#include <gio/gio.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "xed-debug.h"
|
||||
#include "xed-document.h"
|
||||
#include "xed-document-private.h"
|
||||
#include "xed-commands.h"
|
||||
#include "xed-window.h"
|
||||
#include "xed-window-private.h"
|
||||
#include "xed-statusbar.h"
|
||||
#include "xed-debug.h"
|
||||
#include "xed-utils.h"
|
||||
#include "xed-file-chooser-dialog.h"
|
||||
#include "xed-close-confirmation-dialog.h"
|
||||
|
||||
/* Defined constants */
|
||||
#define XED_OPEN_DIALOG_KEY "xed-open-dialog-key"
|
||||
#define XED_TAB_TO_SAVE_AS "xed-tab-to-save-as"
|
||||
#define XED_LIST_OF_TABS_TO_SAVE_AS "xed-list-of-tabs-to-save-as"
|
||||
#define XED_IS_CLOSING_ALL "xed-is-closing-all"
|
||||
#define XED_IS_QUITTING "xed-is-quitting"
|
||||
#define XED_IS_CLOSING_TAB "xed-is-closing-tab"
|
||||
#define XED_IS_QUITTING_ALL "xed-is-quitting-all"
|
||||
|
||||
static void tab_state_changed_while_saving (XedTab *tab,
|
||||
GParamSpec *pspec,
|
||||
XedWindow *window);
|
||||
|
||||
static void save_as_tab (XedTab *tab,
|
||||
XedWindow *window);
|
||||
|
||||
void
|
||||
_xed_cmd_file_new (GtkAction *action,
|
||||
XedWindow *window)
|
||||
|
@ -521,110 +517,70 @@ replace_read_only_file (GtkWindow *parent,
|
|||
}
|
||||
|
||||
static void
|
||||
save_finish_cb (XedTab *tab,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
tab_save_as_ready_cb (XedTab *tab,
|
||||
GAsyncResult *result,
|
||||
GTask *task)
|
||||
{
|
||||
_xed_tab_save_finish (tab, result);
|
||||
gboolean success = _xed_tab_save_finish (tab, result);
|
||||
g_task_return_boolean (task, success);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
save_dialog_response_cb (XedFileChooserDialog *dialog,
|
||||
gint response_id,
|
||||
XedWindow *window)
|
||||
GTask *task)
|
||||
{
|
||||
XedTab *tab;
|
||||
gpointer data;
|
||||
GSList *tabs_to_save_as;
|
||||
XedWindow *window;
|
||||
GFile *location;
|
||||
gchar *parse_name;
|
||||
GtkSourceNewlineType newline_type;
|
||||
const GtkSourceEncoding *encoding;
|
||||
|
||||
xed_debug (DEBUG_COMMANDS);
|
||||
|
||||
tab = XED_TAB (g_object_get_data (G_OBJECT (dialog), XED_TAB_TO_SAVE_AS));
|
||||
tab = g_task_get_source_object (task);
|
||||
window = g_task_get_task_data (task);
|
||||
|
||||
if (response_id != GTK_RESPONSE_OK)
|
||||
{
|
||||
gtk_widget_destroy (GTK_WIDGET (dialog));
|
||||
|
||||
goto save_next_tab;
|
||||
}
|
||||
|
||||
if (tab != NULL)
|
||||
{
|
||||
GFile *location;
|
||||
XedDocument *doc;
|
||||
gchar *parse_name;
|
||||
GtkSourceNewlineType newline_type;
|
||||
const GtkSourceEncoding *encoding;
|
||||
|
||||
doc = xed_tab_get_document (tab);
|
||||
|
||||
location = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
|
||||
g_return_if_fail (location != NULL);
|
||||
|
||||
encoding = xed_file_chooser_dialog_get_encoding (dialog);
|
||||
newline_type = xed_file_chooser_dialog_get_newline_type (dialog);
|
||||
|
||||
gtk_widget_destroy (GTK_WIDGET (dialog));
|
||||
|
||||
doc = xed_tab_get_document (tab);
|
||||
g_return_if_fail (XED_IS_DOCUMENT (doc));
|
||||
|
||||
parse_name = g_file_get_parse_name (location);
|
||||
|
||||
xed_statusbar_flash_message (XED_STATUSBAR (window->priv->statusbar),
|
||||
window->priv->generic_message_cid,
|
||||
_("Saving file '%s'\342\200\246"),
|
||||
parse_name);
|
||||
|
||||
g_free (parse_name);
|
||||
|
||||
/* let's remember the dir we navigated too,
|
||||
* even if the saving fails... */
|
||||
_xed_window_set_default_location (window, location);
|
||||
|
||||
_xed_tab_save_as_async (tab,
|
||||
location,
|
||||
encoding,
|
||||
newline_type,
|
||||
NULL,
|
||||
(GAsyncReadyCallback) save_finish_cb,
|
||||
NULL);
|
||||
|
||||
g_object_unref (location);
|
||||
}
|
||||
|
||||
save_next_tab:
|
||||
|
||||
data = g_object_get_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS);
|
||||
if (data == NULL)
|
||||
{
|
||||
g_task_return_boolean (task, FALSE);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Save As the next tab of the list (we are Saving All files) */
|
||||
tabs_to_save_as = (GSList *)data;
|
||||
g_return_if_fail (tab == XED_TAB (tabs_to_save_as->data));
|
||||
location = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
|
||||
g_return_if_fail (location != NULL);
|
||||
|
||||
/* Remove the first item of the list */
|
||||
tabs_to_save_as = g_slist_delete_link (tabs_to_save_as, tabs_to_save_as);
|
||||
encoding = xed_file_chooser_dialog_get_encoding (dialog);
|
||||
newline_type = xed_file_chooser_dialog_get_newline_type (dialog);
|
||||
|
||||
g_object_set_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS, tabs_to_save_as);
|
||||
gtk_widget_destroy (GTK_WIDGET (dialog));
|
||||
|
||||
if (tabs_to_save_as != NULL)
|
||||
{
|
||||
tab = XED_TAB (tabs_to_save_as->data);
|
||||
parse_name = g_file_get_parse_name (location);
|
||||
|
||||
if (GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (tab), XED_IS_CLOSING_TAB)) == TRUE)
|
||||
{
|
||||
g_object_set_data (G_OBJECT (tab), XED_IS_CLOSING_TAB, NULL);
|
||||
xed_statusbar_flash_message (XED_STATUSBAR (window->priv->statusbar),
|
||||
window->priv->generic_message_cid,
|
||||
_("Saving file '%s'\342\200\246"),
|
||||
parse_name);
|
||||
|
||||
/* Trace tab state changes */
|
||||
g_signal_connect (tab, "notify::state", G_CALLBACK (tab_state_changed_while_saving), window);
|
||||
}
|
||||
g_free (parse_name);
|
||||
|
||||
xed_window_set_active_tab (window, tab);
|
||||
save_as_tab (tab, window);
|
||||
}
|
||||
/* let's remember the dir we navigated too, even if the saving fails... */
|
||||
_xed_window_set_default_location (window, location);
|
||||
|
||||
_xed_tab_save_as_async (tab,
|
||||
location,
|
||||
encoding,
|
||||
newline_type,
|
||||
g_task_get_cancellable (task),
|
||||
(GAsyncReadyCallback) tab_save_as_ready_cb,
|
||||
task);
|
||||
|
||||
g_object_unref (location);
|
||||
}
|
||||
|
||||
static GtkFileChooserConfirmation
|
||||
|
@ -663,16 +619,20 @@ confirm_overwrite_callback (GtkFileChooser *dialog,
|
|||
return res;
|
||||
}
|
||||
|
||||
/* Call save_as_tab_finish() in @callback. */
|
||||
static void
|
||||
save_as_tab (XedTab *tab,
|
||||
XedWindow *window)
|
||||
save_as_tab_async (XedTab *tab,
|
||||
XedWindow *window,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
GtkWidget *save_dialog;
|
||||
GtkWindowGroup *wg;
|
||||
XedDocument *doc;
|
||||
GtkSourceFile *file;
|
||||
GFile *location;
|
||||
gboolean uri_set = FALSE;
|
||||
const GtkSourceEncoding *encoding;
|
||||
GtkSourceNewlineType newline_type;
|
||||
|
||||
|
@ -681,6 +641,9 @@ save_as_tab (XedTab *tab,
|
|||
|
||||
xed_debug (DEBUG_COMMANDS);
|
||||
|
||||
task = g_task_new (tab, cancellable, callback, user_data);
|
||||
g_task_set_task_data (task, g_object_ref (window), g_object_unref);
|
||||
|
||||
save_dialog = xed_file_chooser_dialog_new (_("Save As\342\200\246"),
|
||||
GTK_WINDOW (window),
|
||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
|
@ -706,11 +669,11 @@ save_as_tab (XedTab *tab,
|
|||
|
||||
if (location != NULL)
|
||||
{
|
||||
uri_set = gtk_file_chooser_set_file (GTK_FILE_CHOOSER (save_dialog), location, NULL);
|
||||
gtk_file_chooser_set_file (GTK_FILE_CHOOSER (save_dialog), location, NULL);
|
||||
}
|
||||
|
||||
|
||||
if (!uri_set)
|
||||
else
|
||||
{
|
||||
GFile *default_path;
|
||||
gchar *docname;
|
||||
|
@ -734,7 +697,7 @@ save_as_tab (XedTab *tab,
|
|||
g_free (docname);
|
||||
}
|
||||
|
||||
/* Set suggested encoding */
|
||||
/* Set suggested encoding and newline type */
|
||||
encoding = gtk_source_file_get_encoding (file);
|
||||
|
||||
if (encoding == NULL)
|
||||
|
@ -748,39 +711,94 @@ save_as_tab (XedTab *tab,
|
|||
|
||||
xed_file_chooser_dialog_set_newline_type (XED_FILE_CHOOSER_DIALOG (save_dialog), newline_type);
|
||||
|
||||
g_object_set_data (G_OBJECT (save_dialog), XED_TAB_TO_SAVE_AS, tab);
|
||||
|
||||
g_signal_connect (save_dialog, "response", G_CALLBACK (save_dialog_response_cb), window);
|
||||
g_signal_connect (save_dialog, "response", G_CALLBACK (save_dialog_response_cb), task);
|
||||
|
||||
gtk_widget_show (save_dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
save_tab (XedTab *tab,
|
||||
XedWindow *window)
|
||||
static gboolean
|
||||
save_as_tab_finish (XedTab *tab,
|
||||
GAsyncResult *result)
|
||||
{
|
||||
XedDocument *doc;
|
||||
g_return_val_if_fail (g_task_is_valid (result, tab), FALSE);
|
||||
|
||||
return g_task_propagate_boolean (G_TASK (result), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
save_as_tab_ready_cb (XedTab *tab,
|
||||
GAsyncResult *result,
|
||||
GTask *task)
|
||||
{
|
||||
gboolean success = save_as_tab_finish (tab, result);
|
||||
|
||||
g_task_return_boolean (task, success);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
tab_save_ready_cb (XedTab *tab,
|
||||
GAsyncResult *result,
|
||||
GTask *task)
|
||||
{
|
||||
gboolean success = _xed_tab_save_finish (tab, result);
|
||||
|
||||
g_task_return_boolean (task, success);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
/**
|
||||
* xed_commands_save_document_async:
|
||||
* @document: the #XedDocument to save.
|
||||
* @window: a #XedWindow.
|
||||
* @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
|
||||
* @callback: (scope async): a #GAsyncReadyCallback to call when the operation
|
||||
* is finished.
|
||||
* @user_data: (closure): the data to pass to the @callback function.
|
||||
*
|
||||
* Asynchronously save the @document. @document must belong to @window. The
|
||||
* source object of the async task is @document (which will be the first
|
||||
* parameter of the #GAsyncReadyCallback).
|
||||
*
|
||||
* When the operation is finished, @callback will be called. You can then call
|
||||
* xed_commands_save_document_finish() to get the result of the operation.
|
||||
*/
|
||||
void
|
||||
xed_commands_save_document_async (XedDocument *document,
|
||||
XedWindow *window,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
XedTab *tab;
|
||||
gchar *uri_for_display;
|
||||
|
||||
xed_debug (DEBUG_COMMANDS);
|
||||
|
||||
g_return_if_fail (XED_IS_TAB (tab));
|
||||
g_return_if_fail (XED_IS_DOCUMENT (document));
|
||||
g_return_if_fail (XED_IS_WINDOW (window));
|
||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
doc = xed_tab_get_document (tab);
|
||||
g_return_if_fail (XED_IS_DOCUMENT (doc));
|
||||
task = g_task_new (document, cancellable, callback, user_data);
|
||||
|
||||
if (xed_document_is_untitled (doc) ||
|
||||
xed_document_get_readonly (doc))
|
||||
tab = xed_tab_get_from_document (document);
|
||||
|
||||
if (xed_document_is_untitled (document) ||
|
||||
xed_document_get_readonly (document))
|
||||
{
|
||||
xed_debug_message (DEBUG_COMMANDS, "Untitled or Readonly");
|
||||
|
||||
save_as_tab (tab, window);
|
||||
save_as_tab_async (tab,
|
||||
window,
|
||||
cancellable,
|
||||
(GAsyncReadyCallback) save_as_tab_ready_cb,
|
||||
task);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
uri_for_display = xed_document_get_uri_for_display (doc);
|
||||
uri_for_display = xed_document_get_uri_for_display (document);
|
||||
xed_statusbar_flash_message (XED_STATUSBAR (window->priv->statusbar),
|
||||
window->priv->generic_message_cid,
|
||||
_("Saving file '%s'\342\200\246"),
|
||||
|
@ -789,9 +807,53 @@ save_tab (XedTab *tab,
|
|||
g_free (uri_for_display);
|
||||
|
||||
_xed_tab_save_async (tab,
|
||||
NULL,
|
||||
(GAsyncReadyCallback) save_finish_cb,
|
||||
NULL);
|
||||
cancellable,
|
||||
(GAsyncReadyCallback) tab_save_ready_cb,
|
||||
task);
|
||||
}
|
||||
|
||||
/**
|
||||
* xed_commands_save_document_finish:
|
||||
* @document: a #XedDocument.
|
||||
* @result: a #GAsyncResult.
|
||||
*
|
||||
* Finishes an asynchronous document saving operation started with
|
||||
* xed_commands_save_document_async().
|
||||
*
|
||||
* Note that there is no error parameter because the errors are already handled
|
||||
* by xed.
|
||||
*
|
||||
* Returns: %TRUE if the document has been correctly saved, %FALSE otherwise.
|
||||
*/
|
||||
gboolean
|
||||
xed_commands_save_document_finish (XedDocument *document,
|
||||
GAsyncResult *result)
|
||||
{
|
||||
g_return_val_if_fail (g_task_is_valid (result, document), FALSE);
|
||||
|
||||
return g_task_propagate_boolean (G_TASK (result), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
save_tab_ready_cb (XedDocument *doc,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
xed_commands_save_document_finish (doc, result);
|
||||
}
|
||||
|
||||
/* Save tab asynchronously, but without results. */
|
||||
static void
|
||||
save_tab (XedTab *tab,
|
||||
XedWindow *window)
|
||||
{
|
||||
XedDocument *doc = xed_tab_get_document (tab);
|
||||
|
||||
xed_commands_save_document_async (doc,
|
||||
window,
|
||||
NULL,
|
||||
(GAsyncReadyCallback) save_tab_ready_cb,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -803,12 +865,18 @@ _xed_cmd_file_save (GtkAction *action,
|
|||
xed_debug (DEBUG_COMMANDS);
|
||||
|
||||
tab = xed_window_get_active_tab (window);
|
||||
if (tab == NULL)
|
||||
if (tab != NULL)
|
||||
{
|
||||
return;
|
||||
save_tab (tab, window);
|
||||
}
|
||||
}
|
||||
|
||||
save_tab (tab, window);
|
||||
static void
|
||||
_xed_cmd_file_save_as_cb (XedTab *tab,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
save_as_tab_finish (tab, result);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -820,12 +888,149 @@ _xed_cmd_file_save_as (GtkAction *action,
|
|||
xed_debug (DEBUG_COMMANDS);
|
||||
|
||||
tab = xed_window_get_active_tab (window);
|
||||
if (tab == NULL)
|
||||
if (tab != NULL)
|
||||
{
|
||||
save_as_tab_async (tab,
|
||||
window,
|
||||
NULL,
|
||||
(GAsyncReadyCallback) _xed_cmd_file_save_as_cb,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
quit_if_needed (XedWindow *window)
|
||||
{
|
||||
gboolean is_quitting;
|
||||
gboolean is_quitting_all;
|
||||
|
||||
is_quitting = GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (window), XED_IS_QUITTING));
|
||||
|
||||
is_quitting_all = GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (window), XED_IS_QUITTING_ALL));
|
||||
|
||||
if (is_quitting)
|
||||
{
|
||||
gtk_widget_destroy (GTK_WIDGET (window));
|
||||
}
|
||||
|
||||
if (is_quitting_all)
|
||||
{
|
||||
GtkApplication *app;
|
||||
|
||||
app = GTK_APPLICATION (g_application_get_default ());
|
||||
|
||||
if (gtk_application_get_windows (app) == NULL)
|
||||
{
|
||||
g_application_quit (G_APPLICATION (app));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
really_close_tab (XedTab *tab)
|
||||
{
|
||||
GtkWidget *toplevel;
|
||||
XedWindow *window;
|
||||
|
||||
xed_debug (DEBUG_COMMANDS);
|
||||
|
||||
g_return_val_if_fail (xed_tab_get_state (tab) == XED_TAB_STATE_CLOSING, FALSE);
|
||||
|
||||
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tab));
|
||||
g_return_val_if_fail (XED_IS_WINDOW (toplevel), FALSE);
|
||||
|
||||
window = XED_WINDOW (toplevel);
|
||||
|
||||
xed_window_close_tab (window, tab);
|
||||
|
||||
if (xed_window_get_active_tab (window) == NULL)
|
||||
{
|
||||
quit_if_needed (window);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
close_tab (XedTab *tab)
|
||||
{
|
||||
XedDocument *doc;
|
||||
|
||||
doc = xed_tab_get_document (tab);
|
||||
g_return_if_fail (doc != NULL);
|
||||
|
||||
/* If the user has modified again the document, do not close the tab. */
|
||||
if (_xed_document_needs_saving (doc))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
save_as_tab (tab, window);
|
||||
/* Close the document only if it has been succesfully saved.
|
||||
* Tab state is set to CLOSING (it is a state without exiting
|
||||
* transitions) and the tab is closed in an idle handler.
|
||||
*/
|
||||
_xed_tab_mark_for_closing (tab);
|
||||
|
||||
g_idle_add_full (G_PRIORITY_HIGH_IDLE,
|
||||
(GSourceFunc) really_close_tab,
|
||||
tab,
|
||||
NULL);
|
||||
}
|
||||
|
||||
typedef struct _SaveAsData SaveAsData;
|
||||
|
||||
struct _SaveAsData
|
||||
{
|
||||
/* Reffed */
|
||||
XedWindow *window;
|
||||
|
||||
/* List of reffed GeditTab's */
|
||||
GSList *tabs_to_save_as;
|
||||
|
||||
guint close_tabs : 1;
|
||||
};
|
||||
|
||||
static void save_as_documents_list (SaveAsData *data);
|
||||
|
||||
static void
|
||||
save_as_documents_list_cb (XedTab *tab,
|
||||
GAsyncResult *result,
|
||||
SaveAsData *data)
|
||||
{
|
||||
gboolean saved = save_as_tab_finish (tab, result);
|
||||
|
||||
if (saved && data->close_tabs)
|
||||
{
|
||||
close_tab (tab);
|
||||
}
|
||||
|
||||
g_return_if_fail (tab == XED_TAB (data->tabs_to_save_as->data));
|
||||
g_object_unref (data->tabs_to_save_as->data);
|
||||
data->tabs_to_save_as = g_slist_delete_link (data->tabs_to_save_as, data->tabs_to_save_as);
|
||||
|
||||
if (data->tabs_to_save_as != NULL)
|
||||
{
|
||||
save_as_documents_list (data);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_object_unref (data->window);
|
||||
g_slice_free (SaveAsData, data);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
save_as_documents_list (SaveAsData *data)
|
||||
{
|
||||
XedTab *next_tab = XED_TAB (data->tabs_to_save_as->data);
|
||||
|
||||
xed_window_set_active_tab (data->window, next_tab);
|
||||
|
||||
save_as_tab_async (next_tab,
|
||||
data->window,
|
||||
NULL,
|
||||
(GAsyncReadyCallback) save_as_documents_list_cb,
|
||||
data);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -835,8 +1040,8 @@ static void
|
|||
save_documents_list (XedWindow *window,
|
||||
GList *docs)
|
||||
{
|
||||
SaveAsData *data = NULL;
|
||||
GList *l;
|
||||
GSList *tabs_to_save_as = NULL;
|
||||
|
||||
xed_debug (DEBUG_COMMANDS);
|
||||
|
||||
|
@ -868,9 +1073,17 @@ save_documents_list (XedWindow *window,
|
|||
if (xed_document_is_untitled (doc) || xed_document_get_readonly (doc))
|
||||
{
|
||||
if (_xed_document_needs_saving (doc))
|
||||
{
|
||||
if (data == NULL)
|
||||
{
|
||||
tabs_to_save_as = g_slist_prepend (tabs_to_save_as, t);
|
||||
data = g_slice_new (SaveAsData);
|
||||
data->window = g_object_ref (window);
|
||||
data->tabs_to_save_as = NULL;
|
||||
data->close_tabs = FALSE;
|
||||
}
|
||||
|
||||
data->tabs_to_save_as = g_slist_prepend (data->tabs_to_save_as, g_object_ref (t));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -913,23 +1126,21 @@ save_documents_list (XedWindow *window,
|
|||
l = g_list_next (l);
|
||||
}
|
||||
|
||||
if (tabs_to_save_as != NULL)
|
||||
if (data != NULL)
|
||||
{
|
||||
XedTab *tab;
|
||||
|
||||
tabs_to_save_as = g_slist_reverse (tabs_to_save_as );
|
||||
|
||||
g_return_if_fail (g_object_get_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS) == NULL);
|
||||
|
||||
g_object_set_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS, tabs_to_save_as);
|
||||
|
||||
tab = XED_TAB (tabs_to_save_as->data);
|
||||
|
||||
xed_window_set_active_tab (window, tab);
|
||||
save_as_tab (tab, window);
|
||||
data->tabs_to_save_as = g_slist_reverse (data->tabs_to_save_as);
|
||||
save_as_documents_list (data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* xed_commands_save_all_documents:
|
||||
* @window: a #XedWindow.
|
||||
*
|
||||
* Asynchronously save all documents belonging to @window. The result of the
|
||||
* operation is not available, so it's difficult to know whether all the
|
||||
* documents are correctly saved.
|
||||
*/
|
||||
void
|
||||
xed_commands_save_all_documents (XedWindow *window)
|
||||
{
|
||||
|
@ -953,6 +1164,14 @@ _xed_cmd_file_save_all (GtkAction *action,
|
|||
xed_commands_save_all_documents (window);
|
||||
}
|
||||
|
||||
/**
|
||||
* xed_commands_save_document:
|
||||
* @window: a #XedWindow.
|
||||
* @document: the #XedDocument to save.
|
||||
*
|
||||
* Asynchronously save @document. @document must belong to @window. If you need
|
||||
* the result of the operation, use xed_commands_save_document_async().
|
||||
*/
|
||||
void
|
||||
xed_commands_save_document (XedWindow *window,
|
||||
XedDocument *document)
|
||||
|
@ -1161,39 +1380,6 @@ _xed_cmd_file_revert (GtkAction *action,
|
|||
gtk_widget_show (dialog);
|
||||
}
|
||||
|
||||
/* Close tab */
|
||||
static gboolean
|
||||
really_close_tab (XedTab *tab)
|
||||
{
|
||||
GtkWidget *toplevel;
|
||||
XedWindow *window;
|
||||
|
||||
xed_debug (DEBUG_COMMANDS);
|
||||
|
||||
g_return_val_if_fail (xed_tab_get_state (tab) == XED_TAB_STATE_CLOSING, FALSE);
|
||||
|
||||
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tab));
|
||||
g_return_val_if_fail (XED_IS_WINDOW (toplevel), FALSE);
|
||||
|
||||
window = XED_WINDOW (toplevel);
|
||||
|
||||
xed_window_close_tab (window, tab);
|
||||
|
||||
if (xed_window_get_active_tab (window) == NULL)
|
||||
{
|
||||
gboolean is_quitting;
|
||||
|
||||
is_quitting = GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (window), XED_IS_QUITTING));
|
||||
|
||||
if (is_quitting)
|
||||
{
|
||||
gtk_widget_destroy (GTK_WIDGET (window));
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
tab_state_changed_while_saving (XedTab *tab,
|
||||
GParamSpec *pspec,
|
||||
|
@ -1209,26 +1395,9 @@ tab_state_changed_while_saving (XedTab *tab,
|
|||
finished */
|
||||
if (ts == XED_TAB_STATE_NORMAL)
|
||||
{
|
||||
XedDocument *doc;
|
||||
|
||||
g_signal_handlers_disconnect_by_func (tab, G_CALLBACK (tab_state_changed_while_saving), window);
|
||||
|
||||
doc = xed_tab_get_document (tab);
|
||||
g_return_if_fail (doc != NULL);
|
||||
|
||||
/* If the saving operation failed or was interrupted, then the
|
||||
document is still "modified" -> do not close the tab */
|
||||
if (_xed_document_needs_saving (doc))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Close the document only if it has been succesfully saved.
|
||||
Tab state is set to CLOSING (it is a state without exiting
|
||||
transitions) and the tab is closed in a idle handler */
|
||||
_xed_tab_mark_for_closing (tab);
|
||||
|
||||
g_idle_add_full (G_PRIORITY_HIGH_IDLE, (GSourceFunc)really_close_tab, tab, NULL);
|
||||
close_tab (tab);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1244,21 +1413,6 @@ save_and_close (XedTab *tab,
|
|||
save_tab (tab, window);
|
||||
}
|
||||
|
||||
static void
|
||||
save_as_and_close (XedTab *tab,
|
||||
XedWindow *window)
|
||||
{
|
||||
xed_debug (DEBUG_COMMANDS);
|
||||
|
||||
g_object_set_data (G_OBJECT (tab), XED_IS_CLOSING_TAB, NULL);
|
||||
|
||||
/* Trace tab state changes */
|
||||
g_signal_connect (tab, "notify::state", G_CALLBACK (tab_state_changed_while_saving), window);
|
||||
|
||||
xed_window_set_active_tab (window, tab);
|
||||
save_as_tab (tab, window);
|
||||
}
|
||||
|
||||
static void
|
||||
save_and_close_all_documents (const GList *docs,
|
||||
XedWindow *window)
|
||||
|
@ -1266,9 +1420,9 @@ save_and_close_all_documents (const GList *docs,
|
|||
GList *tabs;
|
||||
GList *l;
|
||||
GSList *sl;
|
||||
GSList *tabs_to_save_as;
|
||||
GSList *tabs_to_save_and_close;
|
||||
GList *tabs_to_close;
|
||||
SaveAsData *data = NULL;
|
||||
GSList *tabs_to_save_and_close = NULL;
|
||||
GList *tabs_to_close = NULL;
|
||||
|
||||
xed_debug (DEBUG_COMMANDS);
|
||||
|
||||
|
@ -1276,19 +1430,13 @@ save_and_close_all_documents (const GList *docs,
|
|||
|
||||
tabs = gtk_container_get_children (GTK_CONTAINER (_xed_window_get_notebook (window)));
|
||||
|
||||
tabs_to_save_as = NULL;
|
||||
tabs_to_save_and_close = NULL;
|
||||
tabs_to_close = NULL;
|
||||
|
||||
l = tabs;
|
||||
while (l != NULL)
|
||||
{
|
||||
XedTab *t;
|
||||
XedTab *t = XED_TAB (l->data);;
|
||||
XedTabState state;
|
||||
XedDocument *doc;
|
||||
|
||||
t = XED_TAB (l->data);
|
||||
|
||||
state = xed_tab_get_state (t);
|
||||
doc = xed_tab_get_document (t);
|
||||
|
||||
|
@ -1337,9 +1485,15 @@ save_and_close_all_documents (const GList *docs,
|
|||
user is running xed - Paolo (Dec. 8, 2005) */
|
||||
if (xed_document_is_untitled (doc) || xed_document_get_readonly (doc))
|
||||
{
|
||||
g_object_set_data (G_OBJECT (t), XED_IS_CLOSING_TAB, GBOOLEAN_TO_POINTER (TRUE));
|
||||
if (data == NULL)
|
||||
{
|
||||
data = g_slice_new (SaveAsData);
|
||||
data->window = g_object_ref (window);
|
||||
data->tabs_to_save_as = NULL;
|
||||
data->close_tabs = TRUE;
|
||||
}
|
||||
|
||||
tabs_to_save_as = g_slist_prepend (tabs_to_save_as, t);
|
||||
data->tabs_to_save_as = g_slist_prepend (data->tabs_to_save_as, g_object_ref (t));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1371,20 +1525,11 @@ save_and_close_all_documents (const GList *docs,
|
|||
}
|
||||
g_slist_free (tabs_to_save_and_close);
|
||||
|
||||
/* Save As and close all the files in tabs_to_save_as */
|
||||
if (tabs_to_save_as != NULL)
|
||||
/* Save As and close all the files in data->tabs_to_save_as. */
|
||||
if (data != NULL)
|
||||
{
|
||||
XedTab *tab;
|
||||
|
||||
tabs_to_save_as = g_slist_reverse (tabs_to_save_as );
|
||||
|
||||
g_return_if_fail (g_object_get_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS) == NULL);
|
||||
|
||||
g_object_set_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS, tabs_to_save_as);
|
||||
|
||||
tab = XED_TAB (tabs_to_save_as->data);
|
||||
|
||||
save_as_and_close (tab, window);
|
||||
data->tabs_to_save_as = g_slist_reverse (data->tabs_to_save_as);
|
||||
save_as_documents_list (data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
void _xed_cmd_help_contents (GtkAction *action,
|
||||
XedWindow *window)
|
||||
{
|
||||
xed_debug(DEBUG_COMMANDS);
|
||||
xed_debug (DEBUG_COMMANDS);
|
||||
|
||||
xed_app_show_help (XED_APP (g_application_get_default ()), GTK_WINDOW (window), NULL, NULL);
|
||||
}
|
||||
|
@ -67,3 +67,33 @@ void _xed_cmd_help_about (GtkAction *action,
|
|||
"website", "http://github.com/linuxmint/xed",
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
_xed_cmd_help_keyboard_shortcuts (GtkAction *action,
|
||||
XedWindow *window)
|
||||
{
|
||||
static GtkWidget *shortcuts_window;
|
||||
|
||||
xed_debug (DEBUG_COMMANDS);
|
||||
|
||||
if (shortcuts_window == NULL)
|
||||
{
|
||||
GtkBuilder *builder;
|
||||
|
||||
builder = gtk_builder_new_from_resource ("/org/x/editor/ui/xed-shortcuts.ui");
|
||||
shortcuts_window = GTK_WIDGET (gtk_builder_get_object (builder, "shortcuts-xed"));
|
||||
|
||||
g_signal_connect (shortcuts_window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &shortcuts_window);
|
||||
|
||||
g_object_unref (builder);
|
||||
}
|
||||
|
||||
if (GTK_WINDOW (window) != gtk_window_get_transient_for (GTK_WINDOW (shortcuts_window)))
|
||||
{
|
||||
gtk_window_set_transient_for (GTK_WINDOW (shortcuts_window), GTK_WINDOW (window));
|
||||
}
|
||||
|
||||
gtk_widget_show_all (shortcuts_window);
|
||||
gtk_window_present (GTK_WINDOW (shortcuts_window));
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ void xed_commands_load_location (XedWindow *window, GFile *location, const GtkSo
|
|||
/* Ignore non-existing URIs */
|
||||
GSList *xed_commands_load_locations (XedWindow *window, const GSList *locations, const GtkSourceEncoding *encoding, gint line_pos);
|
||||
void xed_commands_save_document (XedWindow *window, XedDocument *document);
|
||||
void xed_commands_save_document_async (XedDocument *document, XedWindow *window, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
|
||||
gboolean xed_commands_save_document_finish (XedDocument *document, GAsyncResult *result);
|
||||
void xed_commands_save_all_documents (XedWindow *window);
|
||||
|
||||
/*
|
||||
|
@ -64,6 +66,7 @@ void _xed_cmd_documents_move_to_new_window (GtkAction *action, XedWindow *window
|
|||
|
||||
void _xed_cmd_help_contents (GtkAction *action, XedWindow *window);
|
||||
void _xed_cmd_help_about (GtkAction *action, XedWindow *window);
|
||||
void _xed_cmd_help_keyboard_shortcuts (GtkAction *action, XedWindow *window);
|
||||
|
||||
void _xed_cmd_file_close_tab (XedTab *tab, XedWindow *window);
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef __XED_DOCUMENT_PRIVATE_H__
|
||||
#define __XED_DOCUMENT_PRIVATE_H__
|
||||
|
||||
#include "xed-document.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
glong _xed_document_get_seconds_since_last_save_or_load (XedDocument *doc);
|
||||
|
||||
gboolean _xed_document_needs_saving (XedDocument *doc);
|
||||
|
||||
gboolean _xed_document_get_empty_search (XedDocument *doc);
|
||||
|
||||
void _xed_document_set_create (XedDocument *doc,
|
||||
gboolean create);
|
||||
|
||||
gboolean _xed_document_get_create (XedDocument *doc);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __XED_DOCUMENT_PRIVATE_H__ */
|
File diff suppressed because it is too large
Load Diff
|
@ -37,29 +37,14 @@
|
|||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define XED_TYPE_DOCUMENT (xed_document_get_type())
|
||||
#define XED_DOCUMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XED_TYPE_DOCUMENT, XedDocument))
|
||||
#define XED_DOCUMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XED_TYPE_DOCUMENT, XedDocumentClass))
|
||||
#define XED_IS_DOCUMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XED_TYPE_DOCUMENT))
|
||||
#define XED_IS_DOCUMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_DOCUMENT))
|
||||
#define XED_DOCUMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XED_TYPE_DOCUMENT, XedDocumentClass))
|
||||
#define XED_TYPE_DOCUMENT (xed_document_get_type())
|
||||
|
||||
G_DECLARE_DERIVABLE_TYPE (XedDocument, xed_document, XED, DOCUMENT, GtkSourceBuffer)
|
||||
|
||||
#define XED_METADATA_ATTRIBUTE_POSITION "metadata::xed-position"
|
||||
#define XED_METADATA_ATTRIBUTE_ENCODING "metadata::xed-encoding"
|
||||
#define XED_METADATA_ATTRIBUTE_LANGUAGE "metadata::xed-language"
|
||||
|
||||
typedef struct _XedDocument XedDocument;
|
||||
typedef struct _XedDocumentPrivate XedDocumentPrivate;
|
||||
typedef struct _XedDocumentClass XedDocumentClass;
|
||||
|
||||
struct _XedDocument
|
||||
{
|
||||
GtkSourceBuffer buffer;
|
||||
|
||||
/*< private > */
|
||||
XedDocumentPrivate *priv;
|
||||
};
|
||||
|
||||
struct _XedDocumentClass
|
||||
{
|
||||
GtkSourceBufferClass parent_class;
|
||||
|
@ -77,8 +62,6 @@ struct _XedDocumentClass
|
|||
void (* saved) (XedDocument *document);
|
||||
};
|
||||
|
||||
GType xed_document_get_type (void) G_GNUC_CONST;
|
||||
|
||||
XedDocument *xed_document_new (void);
|
||||
|
||||
GtkSourceFile *xed_document_get_file (XedDocument *doc);
|
||||
|
@ -138,24 +121,6 @@ void xed_document_set_search_context (XedDocument *doc,
|
|||
|
||||
GtkSourceSearchContext *xed_document_get_search_context (XedDocument *doc);
|
||||
|
||||
/* Non exported functions */
|
||||
|
||||
glong _xed_document_get_seconds_since_last_save_or_load (XedDocument *doc);
|
||||
|
||||
void _xed_document_apply_error_style (XedDocument *doc,
|
||||
GtkTextIter *start,
|
||||
GtkTextIter *end);
|
||||
|
||||
/* Note: this is a sync stat: use only on local files */
|
||||
gboolean _xed_document_check_externally_modified (XedDocument *doc);
|
||||
|
||||
gboolean _xed_document_needs_saving (XedDocument *doc);
|
||||
|
||||
void _xed_document_set_create (XedDocument *doc,
|
||||
gboolean create);
|
||||
|
||||
gboolean _xed_document_get_create (XedDocument *doc);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __XED_DOCUMENT_H__ */
|
||||
|
|
|
@ -21,23 +21,15 @@
|
|||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the xed Team, 2003-2007. See the AUTHORS file for a
|
||||
* list of people on the xed Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <libxml/xmlreader.h>
|
||||
#include "xed-metadata-manager.h"
|
||||
#include "xed-debug.h"
|
||||
|
||||
/*
|
||||
#define XED_METADATA_VERBOSE_DEBUG 1
|
||||
#define XED_METADATA_VERBOSE_DEBUG 1
|
||||
*/
|
||||
|
||||
#define MAX_ITEMS 50
|
||||
#define MAX_ITEMS 50
|
||||
|
||||
typedef struct _XedMetadataManager XedMetadataManager;
|
||||
|
||||
|
@ -45,21 +37,21 @@ typedef struct _Item Item;
|
|||
|
||||
struct _Item
|
||||
{
|
||||
time_t atime; /* time of last access */
|
||||
gint64 atime; /* time of last access in seconds since January 1, 1970 UTC */
|
||||
|
||||
GHashTable *values;
|
||||
GHashTable *values;
|
||||
};
|
||||
|
||||
struct _XedMetadataManager
|
||||
{
|
||||
gboolean values_loaded; /* It is true if the file
|
||||
has been read */
|
||||
gboolean values_loaded; /* It is true if the file
|
||||
has been read */
|
||||
|
||||
guint timeout_id;
|
||||
guint timeout_id;
|
||||
|
||||
GHashTable *items;
|
||||
GHashTable *items;
|
||||
|
||||
gchar *metadata_filename;
|
||||
gchar *metadata_filename;
|
||||
};
|
||||
|
||||
static gboolean xed_metadata_manager_save (gpointer data);
|
||||
|
@ -70,34 +62,34 @@ static XedMetadataManager *xed_metadata_manager = NULL;
|
|||
static void
|
||||
item_free (gpointer data)
|
||||
{
|
||||
Item *item;
|
||||
Item *item;
|
||||
|
||||
g_return_if_fail (data != NULL);
|
||||
g_return_if_fail (data != NULL);
|
||||
|
||||
#ifdef XED_METADATA_VERBOSE_DEBUG
|
||||
xed_debug (DEBUG_METADATA);
|
||||
xed_debug (DEBUG_METADATA);
|
||||
#endif
|
||||
|
||||
item = (Item *)data;
|
||||
item = (Item *)data;
|
||||
|
||||
if (item->values != NULL)
|
||||
g_hash_table_destroy (item->values);
|
||||
if (item->values != NULL)
|
||||
g_hash_table_destroy (item->values);
|
||||
|
||||
g_free (item);
|
||||
g_free (item);
|
||||
}
|
||||
|
||||
static void
|
||||
xed_metadata_manager_arm_timeout (void)
|
||||
{
|
||||
if (xed_metadata_manager->timeout_id == 0)
|
||||
{
|
||||
xed_metadata_manager->timeout_id =
|
||||
g_timeout_add_seconds_full (G_PRIORITY_DEFAULT_IDLE,
|
||||
2,
|
||||
(GSourceFunc)xed_metadata_manager_save,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
if (xed_metadata_manager->timeout_id == 0)
|
||||
{
|
||||
xed_metadata_manager->timeout_id =
|
||||
g_timeout_add_seconds_full (G_PRIORITY_DEFAULT_IDLE,
|
||||
2,
|
||||
(GSourceFunc)xed_metadata_manager_save,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -110,22 +102,22 @@ xed_metadata_manager_arm_timeout (void)
|
|||
void
|
||||
xed_metadata_manager_init (const gchar *metadata_filename)
|
||||
{
|
||||
xed_debug (DEBUG_METADATA);
|
||||
xed_debug (DEBUG_METADATA);
|
||||
|
||||
if (xed_metadata_manager != NULL)
|
||||
return;
|
||||
if (xed_metadata_manager != NULL)
|
||||
return;
|
||||
|
||||
xed_metadata_manager = g_new0 (XedMetadataManager, 1);
|
||||
xed_metadata_manager = g_new0 (XedMetadataManager, 1);
|
||||
|
||||
xed_metadata_manager->values_loaded = FALSE;
|
||||
xed_metadata_manager->values_loaded = FALSE;
|
||||
|
||||
xed_metadata_manager->items =
|
||||
g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
g_free,
|
||||
item_free);
|
||||
xed_metadata_manager->items =
|
||||
g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
g_free,
|
||||
item_free);
|
||||
|
||||
xed_metadata_manager->metadata_filename = g_strdup (metadata_filename);
|
||||
xed_metadata_manager->metadata_filename = g_strdup (metadata_filename);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -139,154 +131,159 @@ xed_metadata_manager_init (const gchar *metadata_filename)
|
|||
void
|
||||
xed_metadata_manager_shutdown (void)
|
||||
{
|
||||
xed_debug (DEBUG_METADATA);
|
||||
xed_debug (DEBUG_METADATA);
|
||||
|
||||
if (xed_metadata_manager == NULL)
|
||||
return;
|
||||
if (xed_metadata_manager == NULL)
|
||||
return;
|
||||
|
||||
if (xed_metadata_manager->timeout_id)
|
||||
{
|
||||
g_source_remove (xed_metadata_manager->timeout_id);
|
||||
xed_metadata_manager->timeout_id = 0;
|
||||
xed_metadata_manager_save (NULL);
|
||||
}
|
||||
if (xed_metadata_manager->timeout_id)
|
||||
{
|
||||
g_source_remove (xed_metadata_manager->timeout_id);
|
||||
xed_metadata_manager->timeout_id = 0;
|
||||
xed_metadata_manager_save (NULL);
|
||||
}
|
||||
|
||||
if (xed_metadata_manager->items != NULL)
|
||||
g_hash_table_destroy (xed_metadata_manager->items);
|
||||
if (xed_metadata_manager->items != NULL)
|
||||
g_hash_table_destroy (xed_metadata_manager->items);
|
||||
|
||||
g_free (gedit_metadata_manager->metadata_filename);
|
||||
g_free (xed_metadata_manager);
|
||||
xed_metadata_manager = NULL;
|
||||
g_free (xed_metadata_manager->metadata_filename);
|
||||
g_free (xed_metadata_manager);
|
||||
xed_metadata_manager = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
parseItem (xmlDocPtr doc, xmlNodePtr cur)
|
||||
{
|
||||
Item *item;
|
||||
Item *item;
|
||||
|
||||
xmlChar *uri;
|
||||
xmlChar *atime;
|
||||
xmlChar *uri;
|
||||
xmlChar *atime;
|
||||
|
||||
#ifdef XED_METADATA_VERBOSE_DEBUG
|
||||
xed_debug (DEBUG_METADATA);
|
||||
xed_debug (DEBUG_METADATA);
|
||||
#endif
|
||||
|
||||
if (xmlStrcmp (cur->name, (const xmlChar *)"document") != 0)
|
||||
return;
|
||||
if (xmlStrcmp (cur->name, (const xmlChar *)"document") != 0)
|
||||
return;
|
||||
|
||||
uri = xmlGetProp (cur, (const xmlChar *)"uri");
|
||||
if (uri == NULL)
|
||||
return;
|
||||
uri = xmlGetProp (cur, (const xmlChar *)"uri");
|
||||
if (uri == NULL)
|
||||
return;
|
||||
|
||||
atime = xmlGetProp (cur, (const xmlChar *)"atime");
|
||||
if (atime == NULL)
|
||||
{
|
||||
xmlFree (uri);
|
||||
return;
|
||||
}
|
||||
atime = xmlGetProp (cur, (const xmlChar *)"atime");
|
||||
if (atime == NULL)
|
||||
{
|
||||
xmlFree (uri);
|
||||
return;
|
||||
}
|
||||
|
||||
item = g_new0 (Item, 1);
|
||||
item = g_new0 (Item, 1);
|
||||
|
||||
item->atime = g_ascii_strtoull ((char *)atime, NULL, 0);
|
||||
item->atime = g_ascii_strtoll ((char *)atime, NULL, 0);
|
||||
|
||||
item->values = g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
g_free,
|
||||
g_free);
|
||||
item->values = g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
g_free,
|
||||
g_free);
|
||||
|
||||
cur = cur->xmlChildrenNode;
|
||||
cur = cur->xmlChildrenNode;
|
||||
|
||||
while (cur != NULL)
|
||||
{
|
||||
if (xmlStrcmp (cur->name, (const xmlChar *)"entry") == 0)
|
||||
{
|
||||
xmlChar *key;
|
||||
xmlChar *value;
|
||||
while (cur != NULL)
|
||||
{
|
||||
if (xmlStrcmp (cur->name, (const xmlChar *)"entry") == 0)
|
||||
{
|
||||
xmlChar *key;
|
||||
xmlChar *value;
|
||||
|
||||
key = xmlGetProp (cur, (const xmlChar *)"key");
|
||||
value = xmlGetProp (cur, (const xmlChar *)"value");
|
||||
key = xmlGetProp (cur, (const xmlChar *)"key");
|
||||
value = xmlGetProp (cur, (const xmlChar *)"value");
|
||||
|
||||
if ((key != NULL) && (value != NULL))
|
||||
g_hash_table_insert (item->values,
|
||||
g_strdup ((gchar *)key),
|
||||
g_strdup ((gchar *)value));
|
||||
if ((key != NULL) && (value != NULL))
|
||||
g_hash_table_insert (item->values,
|
||||
g_strdup ((gchar *)key),
|
||||
g_strdup ((gchar *)value));
|
||||
|
||||
if (key != NULL)
|
||||
xmlFree (key);
|
||||
if (value != NULL)
|
||||
xmlFree (value);
|
||||
}
|
||||
if (key != NULL)
|
||||
xmlFree (key);
|
||||
if (value != NULL)
|
||||
xmlFree (value);
|
||||
}
|
||||
|
||||
cur = cur->next;
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
g_hash_table_insert (xed_metadata_manager->items,
|
||||
g_strdup ((gchar *)uri),
|
||||
item);
|
||||
g_hash_table_insert (xed_metadata_manager->items,
|
||||
g_strdup ((gchar *)uri),
|
||||
item);
|
||||
|
||||
xmlFree (uri);
|
||||
xmlFree (atime);
|
||||
xmlFree (uri);
|
||||
xmlFree (atime);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
load_values (void)
|
||||
{
|
||||
xmlDocPtr doc;
|
||||
xmlNodePtr cur;
|
||||
xmlDocPtr doc;
|
||||
xmlNodePtr cur;
|
||||
|
||||
xed_debug (DEBUG_METADATA);
|
||||
xed_debug (DEBUG_METADATA);
|
||||
|
||||
g_return_val_if_fail (xed_metadata_manager != NULL, FALSE);
|
||||
g_return_val_if_fail (xed_metadata_manager->values_loaded == FALSE, FALSE);
|
||||
g_return_val_if_fail (xed_metadata_manager != NULL, FALSE);
|
||||
g_return_val_if_fail (xed_metadata_manager->values_loaded == FALSE, FALSE);
|
||||
|
||||
xed_metadata_manager->values_loaded = TRUE;
|
||||
xed_metadata_manager->values_loaded = TRUE;
|
||||
|
||||
xmlKeepBlanksDefault (0);
|
||||
xmlKeepBlanksDefault (0);
|
||||
|
||||
/* FIXME: file locking - Paolo */
|
||||
if ((xed_metadata_manager->metadata_filename == NULL) ||
|
||||
(!g_file_test (xed_metadata_manager->metadata_filename, G_FILE_TEST_EXISTS)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
/* FIXME: file locking - Paolo */
|
||||
if (xed_metadata_manager->metadata_filename == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
doc = xmlParseFile (xed_metadata_manager->metadata_filename);
|
||||
/* TODO: avoid races */
|
||||
if (!g_file_test (xed_metadata_manager->metadata_filename, G_FILE_TEST_EXISTS))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (doc == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
doc = xmlParseFile (xed_metadata_manager->metadata_filename);
|
||||
|
||||
cur = xmlDocGetRootElement (doc);
|
||||
if (cur == NULL)
|
||||
{
|
||||
g_message ("The metadata file '%s' is empty", g_path_get_basename (xed_metadata_manager->metadata_filename));
|
||||
xmlFreeDoc (doc);
|
||||
if (doc == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
cur = xmlDocGetRootElement (doc);
|
||||
if (cur == NULL)
|
||||
{
|
||||
g_message ("The metadata file '%s' is empty", g_path_get_basename (xed_metadata_manager->metadata_filename));
|
||||
xmlFreeDoc (doc);
|
||||
|
||||
if (xmlStrcmp (cur->name, (const xmlChar *) "metadata"))
|
||||
{
|
||||
g_message ("File '%s' is of the wrong type", g_path_get_basename (xed_metadata_manager->metadata_filename));
|
||||
xmlFreeDoc (doc);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
if (xmlStrcmp (cur->name, (const xmlChar *) "metadata"))
|
||||
{
|
||||
g_message ("File '%s' is of the wrong type", g_path_get_basename (xed_metadata_manager->metadata_filename));
|
||||
xmlFreeDoc (doc);
|
||||
|
||||
cur = xmlDocGetRootElement (doc);
|
||||
cur = cur->xmlChildrenNode;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while (cur != NULL)
|
||||
{
|
||||
parseItem (doc, cur);
|
||||
cur = xmlDocGetRootElement (doc);
|
||||
cur = cur->xmlChildrenNode;
|
||||
|
||||
cur = cur->next;
|
||||
}
|
||||
while (cur != NULL)
|
||||
{
|
||||
parseItem (doc, cur);
|
||||
|
||||
xmlFreeDoc (doc);
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
xmlFreeDoc (doc);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -298,48 +295,51 @@ load_values (void)
|
|||
*/
|
||||
gchar *
|
||||
xed_metadata_manager_get (GFile *location,
|
||||
const gchar *key)
|
||||
const gchar *key)
|
||||
{
|
||||
Item *item;
|
||||
gchar *value;
|
||||
gchar *uri;
|
||||
Item *item;
|
||||
gchar *value;
|
||||
gchar *uri;
|
||||
|
||||
g_return_val_if_fail (G_IS_FILE (location), NULL);
|
||||
g_return_val_if_fail (key != NULL, NULL);
|
||||
g_return_val_if_fail (G_IS_FILE (location), NULL);
|
||||
g_return_val_if_fail (key != NULL, NULL);
|
||||
|
||||
uri = g_file_get_uri (location);
|
||||
uri = g_file_get_uri (location);
|
||||
|
||||
xed_debug_message (DEBUG_METADATA, "URI: %s --- key: %s", uri, key );
|
||||
xed_debug_message (DEBUG_METADATA, "URI: %s --- key: %s", uri, key );
|
||||
|
||||
if (!xed_metadata_manager->values_loaded)
|
||||
{
|
||||
gboolean res;
|
||||
if (!xed_metadata_manager->values_loaded)
|
||||
{
|
||||
gboolean res;
|
||||
|
||||
res = load_values ();
|
||||
res = load_values ();
|
||||
|
||||
if (!res)
|
||||
return NULL;
|
||||
}
|
||||
if (!res)
|
||||
{
|
||||
g_free (uri);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
item = (Item *)g_hash_table_lookup (xed_metadata_manager->items,
|
||||
uri);
|
||||
item = (Item *)g_hash_table_lookup (xed_metadata_manager->items,
|
||||
uri);
|
||||
|
||||
g_free (uri);
|
||||
g_free (uri);
|
||||
|
||||
if (item == NULL)
|
||||
return NULL;
|
||||
if (item == NULL)
|
||||
return NULL;
|
||||
|
||||
item->atime = time (NULL);
|
||||
item->atime = g_get_real_time () / 1000;
|
||||
|
||||
if (item->values == NULL)
|
||||
return NULL;
|
||||
if (item->values == NULL)
|
||||
return NULL;
|
||||
|
||||
value = g_hash_table_lookup (item->values, key);
|
||||
value = g_hash_table_lookup (item->values, key);
|
||||
|
||||
if (value == NULL)
|
||||
return NULL;
|
||||
else
|
||||
return g_strdup (value);
|
||||
if (value == NULL)
|
||||
return NULL;
|
||||
else
|
||||
return g_strdup (value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -352,219 +352,221 @@ xed_metadata_manager_get (GFile *location,
|
|||
*/
|
||||
void
|
||||
xed_metadata_manager_set (GFile *location,
|
||||
const gchar *key,
|
||||
const gchar *value)
|
||||
const gchar *key,
|
||||
const gchar *value)
|
||||
{
|
||||
Item *item;
|
||||
gchar *uri;
|
||||
Item *item;
|
||||
gchar *uri;
|
||||
|
||||
g_return_if_fail (G_IS_FILE (location));
|
||||
g_return_if_fail (key != NULL);
|
||||
g_return_if_fail (G_IS_FILE (location));
|
||||
g_return_if_fail (key != NULL);
|
||||
|
||||
uri = g_file_get_uri (location);
|
||||
uri = g_file_get_uri (location);
|
||||
|
||||
xed_debug_message (DEBUG_METADATA, "URI: %s --- key: %s --- value: %s", uri, key, value);
|
||||
xed_debug_message (DEBUG_METADATA, "URI: %s --- key: %s --- value: %s", uri, key, value);
|
||||
|
||||
if (!xed_metadata_manager->values_loaded)
|
||||
{
|
||||
gboolean res;
|
||||
if (!xed_metadata_manager->values_loaded)
|
||||
{
|
||||
gboolean ok;
|
||||
|
||||
res = load_values ();
|
||||
ok = load_values ();
|
||||
|
||||
if (!res)
|
||||
return;
|
||||
}
|
||||
if (!ok)
|
||||
{
|
||||
g_free (uri);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item = (Item *)g_hash_table_lookup (xed_metadata_manager->items,
|
||||
uri);
|
||||
item = (Item *)g_hash_table_lookup (xed_metadata_manager->items,
|
||||
uri);
|
||||
|
||||
if (item == NULL)
|
||||
{
|
||||
item = g_new0 (Item, 1);
|
||||
if (item == NULL)
|
||||
{
|
||||
item = g_new0 (Item, 1);
|
||||
|
||||
g_hash_table_insert (xed_metadata_manager->items,
|
||||
g_strdup (uri),
|
||||
item);
|
||||
}
|
||||
g_hash_table_insert (xed_metadata_manager->items,
|
||||
g_strdup (uri),
|
||||
item);
|
||||
}
|
||||
|
||||
if (item->values == NULL)
|
||||
item->values = g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
g_free,
|
||||
g_free);
|
||||
if (value != NULL)
|
||||
g_hash_table_insert (item->values,
|
||||
g_strdup (key),
|
||||
g_strdup (value));
|
||||
else
|
||||
g_hash_table_remove (item->values,
|
||||
key);
|
||||
if (item->values == NULL)
|
||||
item->values = g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
g_free,
|
||||
g_free);
|
||||
if (value != NULL)
|
||||
g_hash_table_insert (item->values,
|
||||
g_strdup (key),
|
||||
g_strdup (value));
|
||||
else
|
||||
g_hash_table_remove (item->values,
|
||||
key);
|
||||
|
||||
item->atime = time (NULL);
|
||||
item->atime = g_get_real_time () / 1000;
|
||||
|
||||
g_free (uri);
|
||||
g_free (uri);
|
||||
|
||||
xed_metadata_manager_arm_timeout ();
|
||||
xed_metadata_manager_arm_timeout ();
|
||||
}
|
||||
|
||||
static void
|
||||
save_values (const gchar *key, const gchar *value, xmlNodePtr parent)
|
||||
{
|
||||
xmlNodePtr xml_node;
|
||||
xmlNodePtr xml_node;
|
||||
|
||||
#ifdef XED_METADATA_VERBOSE_DEBUG
|
||||
xed_debug (DEBUG_METADATA);
|
||||
xed_debug (DEBUG_METADATA);
|
||||
#endif
|
||||
|
||||
g_return_if_fail (key != NULL);
|
||||
g_return_if_fail (key != NULL);
|
||||
|
||||
if (value == NULL)
|
||||
return;
|
||||
if (value == NULL)
|
||||
return;
|
||||
|
||||
xml_node = xmlNewChild (parent,
|
||||
NULL,
|
||||
(const xmlChar *)"entry",
|
||||
NULL);
|
||||
xml_node = xmlNewChild (parent,
|
||||
NULL,
|
||||
(const xmlChar *)"entry",
|
||||
NULL);
|
||||
|
||||
xmlSetProp (xml_node,
|
||||
(const xmlChar *)"key",
|
||||
(const xmlChar *)key);
|
||||
xmlSetProp (xml_node,
|
||||
(const xmlChar *)"value",
|
||||
(const xmlChar *)value);
|
||||
xmlSetProp (xml_node,
|
||||
(const xmlChar *)"key",
|
||||
(const xmlChar *)key);
|
||||
xmlSetProp (xml_node,
|
||||
(const xmlChar *)"value",
|
||||
(const xmlChar *)value);
|
||||
|
||||
#ifdef XED_METADATA_VERBOSE_DEBUG
|
||||
xed_debug_message (DEBUG_METADATA, "entry: %s = %s", key, value);
|
||||
xed_debug_message (DEBUG_METADATA, "entry: %s = %s", key, value);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
save_item (const gchar *key, const gpointer *data, xmlNodePtr parent)
|
||||
{
|
||||
xmlNodePtr xml_node;
|
||||
const Item *item = (const Item *)data;
|
||||
gchar *atime;
|
||||
xmlNodePtr xml_node;
|
||||
const Item *item = (const Item *)data;
|
||||
gchar *atime;
|
||||
|
||||
#ifdef XED_METADATA_VERBOSE_DEBUG
|
||||
xed_debug (DEBUG_METADATA);
|
||||
xed_debug (DEBUG_METADATA);
|
||||
#endif
|
||||
|
||||
g_return_if_fail (key != NULL);
|
||||
g_return_if_fail (key != NULL);
|
||||
|
||||
if (item == NULL)
|
||||
return;
|
||||
if (item == NULL)
|
||||
return;
|
||||
|
||||
xml_node = xmlNewChild (parent, NULL, (const xmlChar *)"document", NULL);
|
||||
xml_node = xmlNewChild (parent, NULL, (const xmlChar *)"document", NULL);
|
||||
|
||||
xmlSetProp (xml_node, (const xmlChar *)"uri", (const xmlChar *)key);
|
||||
xmlSetProp (xml_node, (const xmlChar *)"uri", (const xmlChar *)key);
|
||||
|
||||
#ifdef XED_METADATA_VERBOSE_DEBUG
|
||||
xed_debug_message (DEBUG_METADATA, "uri: %s", key);
|
||||
xed_debug_message (DEBUG_METADATA, "uri: %s", key);
|
||||
#endif
|
||||
|
||||
atime = g_strdup_printf ("%ld", item->atime);
|
||||
xmlSetProp (xml_node, (const xmlChar *)"atime", (const xmlChar *)atime);
|
||||
atime = g_strdup_printf ("%" G_GINT64_FORMAT, item->atime);
|
||||
xmlSetProp (xml_node, (const xmlChar *)"atime", (const xmlChar *)atime);
|
||||
|
||||
#ifdef XED_METADATA_VERBOSE_DEBUG
|
||||
xed_debug_message (DEBUG_METADATA, "atime: %s", atime);
|
||||
xed_debug_message (DEBUG_METADATA, "atime: %s", atime);
|
||||
#endif
|
||||
|
||||
g_free (atime);
|
||||
g_free (atime);
|
||||
|
||||
g_hash_table_foreach (item->values,
|
||||
(GHFunc)save_values,
|
||||
xml_node);
|
||||
g_hash_table_foreach (item->values,
|
||||
(GHFunc)save_values,
|
||||
xml_node);
|
||||
}
|
||||
|
||||
static void
|
||||
get_oldest (const gchar *key, const gpointer value, const gchar ** key_to_remove)
|
||||
{
|
||||
const Item *item = (const Item *)value;
|
||||
const Item *item = (const Item *)value;
|
||||
|
||||
if (*key_to_remove == NULL)
|
||||
{
|
||||
*key_to_remove = key;
|
||||
}
|
||||
else
|
||||
{
|
||||
const Item *item_to_remove =
|
||||
g_hash_table_lookup (xed_metadata_manager->items,
|
||||
*key_to_remove);
|
||||
if (*key_to_remove == NULL)
|
||||
{
|
||||
*key_to_remove = key;
|
||||
}
|
||||
else
|
||||
{
|
||||
const Item *item_to_remove =
|
||||
g_hash_table_lookup (xed_metadata_manager->items,
|
||||
*key_to_remove);
|
||||
|
||||
g_return_if_fail (item_to_remove != NULL);
|
||||
g_return_if_fail (item_to_remove != NULL);
|
||||
|
||||
if (item->atime < item_to_remove->atime)
|
||||
{
|
||||
*key_to_remove = key;
|
||||
}
|
||||
}
|
||||
if (item->atime < item_to_remove->atime)
|
||||
{
|
||||
*key_to_remove = key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
resize_items (void)
|
||||
{
|
||||
while (g_hash_table_size (xed_metadata_manager->items) > MAX_ITEMS)
|
||||
{
|
||||
gpointer key_to_remove = NULL;
|
||||
while (g_hash_table_size (xed_metadata_manager->items) > MAX_ITEMS)
|
||||
{
|
||||
gpointer key_to_remove = NULL;
|
||||
|
||||
g_hash_table_foreach (xed_metadata_manager->items,
|
||||
(GHFunc)get_oldest,
|
||||
&key_to_remove);
|
||||
g_hash_table_foreach (xed_metadata_manager->items,
|
||||
(GHFunc)get_oldest,
|
||||
&key_to_remove);
|
||||
|
||||
g_return_if_fail (key_to_remove != NULL);
|
||||
g_return_if_fail (key_to_remove != NULL);
|
||||
|
||||
g_hash_table_remove (xed_metadata_manager->items,
|
||||
key_to_remove);
|
||||
}
|
||||
g_hash_table_remove (xed_metadata_manager->items,
|
||||
key_to_remove);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
xed_metadata_manager_save (gpointer data)
|
||||
{
|
||||
xmlDocPtr doc;
|
||||
xmlNodePtr root;
|
||||
xmlDocPtr doc;
|
||||
xmlNodePtr root;
|
||||
|
||||
xed_debug (DEBUG_METADATA);
|
||||
xed_debug (DEBUG_METADATA);
|
||||
|
||||
xed_metadata_manager->timeout_id = 0;
|
||||
xed_metadata_manager->timeout_id = 0;
|
||||
|
||||
resize_items ();
|
||||
resize_items ();
|
||||
|
||||
xmlIndentTreeOutput = TRUE;
|
||||
xmlIndentTreeOutput = TRUE;
|
||||
|
||||
doc = xmlNewDoc ((const xmlChar *)"1.0");
|
||||
if (doc == NULL)
|
||||
return TRUE;
|
||||
doc = xmlNewDoc ((const xmlChar *)"1.0");
|
||||
if (doc == NULL)
|
||||
return TRUE;
|
||||
|
||||
/* Create metadata root */
|
||||
root = xmlNewDocNode (doc, NULL, (const xmlChar *)"metadata", NULL);
|
||||
xmlDocSetRootElement (doc, root);
|
||||
/* Create metadata root */
|
||||
root = xmlNewDocNode (doc, NULL, (const xmlChar *)"metadata", NULL);
|
||||
xmlDocSetRootElement (doc, root);
|
||||
|
||||
g_hash_table_foreach (xed_metadata_manager->items,
|
||||
(GHFunc)save_item,
|
||||
root);
|
||||
g_hash_table_foreach (xed_metadata_manager->items,
|
||||
(GHFunc)save_item,
|
||||
root);
|
||||
|
||||
/* FIXME: lock file - Paolo */
|
||||
if (xed_metadata_manager->metadata_filename != NULL)
|
||||
{
|
||||
gchar *cache_dir;
|
||||
int res;
|
||||
/* FIXME: lock file - Paolo */
|
||||
if (xed_metadata_manager->metadata_filename != NULL)
|
||||
{
|
||||
gchar *cache_dir;
|
||||
int res;
|
||||
|
||||
/* make sure the cache dir exists */
|
||||
cache_dir = g_path_get_dirname (xed_metadata_manager->metadata_filename);
|
||||
res = g_mkdir_with_parents (cache_dir, 0755);
|
||||
if (res != -1)
|
||||
{
|
||||
xmlSaveFormatFile (xed_metadata_manager->metadata_filename, doc, 1);
|
||||
}
|
||||
/* make sure the cache dir exists */
|
||||
cache_dir = g_path_get_dirname (xed_metadata_manager->metadata_filename);
|
||||
res = g_mkdir_with_parents (cache_dir, 0755);
|
||||
if (res != -1)
|
||||
{
|
||||
xmlSaveFormatFile (xed_metadata_manager->metadata_filename, doc, 1);
|
||||
}
|
||||
|
||||
g_free (cache_dir);
|
||||
}
|
||||
g_free (cache_dir);
|
||||
}
|
||||
|
||||
xmlFreeDoc (doc);
|
||||
xmlFreeDoc (doc);
|
||||
|
||||
xed_debug_message (DEBUG_METADATA, "DONE");
|
||||
xed_debug_message (DEBUG_METADATA, "DONE");
|
||||
|
||||
return FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#ifndef __XED_METADATA_MANAGER_H__
|
||||
#define __XED_METADATA_MANAGER_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
|
|
@ -543,6 +543,8 @@ button_release_cb (XedNotebook *notebook,
|
|||
GdkEventButton *event,
|
||||
gpointer data)
|
||||
{
|
||||
gboolean ret_val = FALSE;
|
||||
|
||||
if (notebook->priv->drag_in_progress)
|
||||
{
|
||||
gint cur_page_num;
|
||||
|
@ -566,11 +568,23 @@ button_release_cb (XedNotebook *notebook,
|
|||
}
|
||||
gtk_grab_remove (GTK_WIDGET (notebook));
|
||||
}
|
||||
else if ((event->type == GDK_BUTTON_RELEASE) && (event->button == 8))
|
||||
{
|
||||
gtk_notebook_prev_page (GTK_NOTEBOOK (notebook));
|
||||
|
||||
ret_val = TRUE;
|
||||
}
|
||||
else if ((event->type == GDK_BUTTON_RELEASE) && (event->button == 9))
|
||||
{
|
||||
gtk_notebook_next_page (GTK_NOTEBOOK (notebook));
|
||||
|
||||
ret_val = TRUE;
|
||||
}
|
||||
|
||||
/* This must be called even if a drag isn't happening */
|
||||
drag_stop (notebook);
|
||||
|
||||
return FALSE;
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -638,13 +652,13 @@ notebook_scroll_event_cb (XedNotebook *notebook,
|
|||
switch (event->direction)
|
||||
{
|
||||
case GDK_SCROLL_DOWN:
|
||||
case GDK_SCROLL_RIGHT:
|
||||
gtk_notebook_next_page (GTK_NOTEBOOK (notebook));
|
||||
break;
|
||||
case GDK_SCROLL_UP:
|
||||
case GDK_SCROLL_LEFT:
|
||||
gtk_notebook_prev_page (GTK_NOTEBOOK (notebook));
|
||||
break;
|
||||
case GDK_SCROLL_UP:
|
||||
case GDK_SCROLL_RIGHT:
|
||||
gtk_notebook_next_page (GTK_NOTEBOOK (notebook));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -714,11 +728,9 @@ xed_notebook_init (XedNotebook *notebook)
|
|||
notebook->priv->tab_scrolling_enabled = g_settings_get_boolean (notebook->priv->ui_settings, "enable-tab-scrolling");
|
||||
|
||||
gtk_notebook_set_scrollable (GTK_NOTEBOOK (notebook), TRUE);
|
||||
|
||||
#if GTK_CHECK_VERSION (3, 20, 0)
|
||||
gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE);
|
||||
#endif
|
||||
gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE);
|
||||
gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (notebook), 0);
|
||||
|
||||
g_signal_connect (notebook, "button-press-event",
|
||||
(GCallback)button_press_cb, NULL);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3,7 +3,7 @@
|
|||
* xed-preferences-dialog.c
|
||||
* This file is part of xed
|
||||
*
|
||||
* Copyright (C) 2001-2005 Paolo Maggi
|
||||
* Copyright (C) 2001-2005 Paolo Maggi
|
||||
*
|
||||
* 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
|
||||
|
@ -17,14 +17,14 @@
|
|||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the xed Team, 2003. See the AUTHORS file for a
|
||||
* list of people on the xed Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
* Modified by the xed Team, 2003. See the AUTHORS file for a
|
||||
* list of people on the xed Team.
|
||||
* See the ChangeLog files for a list of changes.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
@ -32,54 +32,13 @@
|
|||
#ifndef __XED_PREFERENCES_DIALOG_H__
|
||||
#define __XED_PREFERENCES_DIALOG_H__
|
||||
|
||||
#include <libxapp/xapp-preferences-window.h>
|
||||
|
||||
#include "xed-window.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Type checking and casting macros
|
||||
*/
|
||||
#define XED_TYPE_PREFERENCES_DIALOG (xed_preferences_dialog_get_type())
|
||||
#define XED_PREFERENCES_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XED_TYPE_PREFERENCES_DIALOG, XedPreferencesDialog))
|
||||
#define XED_PREFERENCES_DIALOG_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XED_TYPE_PREFERENCES_DIALOG, XedPreferencesDialog const))
|
||||
#define XED_PREFERENCES_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XED_TYPE_PREFERENCES_DIALOG, XedPreferencesDialogClass))
|
||||
#define XED_IS_PREFERENCES_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XED_TYPE_PREFERENCES_DIALOG))
|
||||
#define XED_IS_PREFERENCES_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_PREFERENCES_DIALOG))
|
||||
#define XED_PREFERENCES_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XED_TYPE_PREFERENCES_DIALOG, XedPreferencesDialogClass))
|
||||
|
||||
|
||||
/* Private structure type */
|
||||
typedef struct _XedPreferencesDialogPrivate XedPreferencesDialogPrivate;
|
||||
|
||||
/*
|
||||
* Main object structure
|
||||
*/
|
||||
typedef struct _XedPreferencesDialog XedPreferencesDialog;
|
||||
|
||||
struct _XedPreferencesDialog
|
||||
{
|
||||
GtkDialog dialog;
|
||||
|
||||
/*< private > */
|
||||
XedPreferencesDialogPrivate *priv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class definition
|
||||
*/
|
||||
typedef struct _XedPreferencesDialogClass XedPreferencesDialogClass;
|
||||
|
||||
struct _XedPreferencesDialogClass
|
||||
{
|
||||
GtkDialogClass parent_class;
|
||||
};
|
||||
|
||||
/*
|
||||
* Public methods
|
||||
*/
|
||||
GType xed_preferences_dialog_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void xed_show_preferences_dialog (XedWindow *parent);
|
||||
void xed_show_preferences_dialog (XedWindow *parent);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
|
@ -659,11 +659,8 @@ xed_searchbar_init (XedSearchbar *searchbar)
|
|||
{
|
||||
GtkWidget *content;
|
||||
GtkSizeGroup *size_group;
|
||||
GtkStyleContext *context;
|
||||
GtkCssProvider *provider;
|
||||
GtkBuilder *builder;
|
||||
gchar *root_objects[] = { "searchbar_content", NULL };
|
||||
const gchar *data = ".button {padding: 0;}";
|
||||
|
||||
searchbar->priv = XED_SEARCHBAR_GET_PRIVATE (searchbar);
|
||||
|
||||
|
@ -709,10 +706,7 @@ xed_searchbar_init (XedSearchbar *searchbar)
|
|||
gtk_label_set_mnemonic_widget (GTK_LABEL (searchbar->priv->search_label), searchbar->priv->search_entry);
|
||||
gtk_label_set_mnemonic_widget (GTK_LABEL (searchbar->priv->replace_label), searchbar->priv->replace_entry);
|
||||
|
||||
provider = gtk_css_provider_new ();
|
||||
context = gtk_widget_get_style_context (searchbar->priv->close_button);
|
||||
gtk_css_provider_load_from_data (provider, data, -1, NULL);
|
||||
gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (searchbar->priv->close_button), "close-button");
|
||||
|
||||
size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
|
||||
gtk_size_group_add_widget (size_group, GTK_WIDGET (searchbar->priv->find_button));
|
||||
|
|
|
@ -282,26 +282,6 @@ on_auto_save_interval_changed (GSettings *settings,
|
|||
g_list_free (docs);
|
||||
}
|
||||
|
||||
static void
|
||||
on_wrap_mode_changed (GSettings *settings,
|
||||
const gchar *key,
|
||||
XedSettings *xs)
|
||||
{
|
||||
GtkWrapMode wrap_mode;
|
||||
GList *views, *l;
|
||||
|
||||
wrap_mode = g_settings_get_enum (settings, key);
|
||||
|
||||
views = xed_app_get_views (XED_APP (g_application_get_default ()));
|
||||
|
||||
for (l = views; l != NULL; l = g_list_next (l))
|
||||
{
|
||||
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (l->data), wrap_mode);
|
||||
}
|
||||
|
||||
g_list_free (views);
|
||||
}
|
||||
|
||||
static void
|
||||
on_syntax_highlighting_changed (GSettings *settings,
|
||||
const gchar *key,
|
||||
|
|
|
@ -141,18 +141,14 @@ xed_status_combo_box_changed (XedStatusComboBox *combo,
|
|||
static void
|
||||
xed_status_combo_box_class_init (XedStatusComboBoxClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
static const gchar style[] =
|
||||
"* {\n"
|
||||
"-GtkButton-default-border : 0;\n"
|
||||
"-GtkButton-default-outside-border : 0;\n"
|
||||
"-GtkButton-inner-border: 0;\n"
|
||||
"-GtkWidget-focus-line-width : 0;\n"
|
||||
"-GtkWidget-focus-padding : 0;\n"
|
||||
"padding: 2px;\n"
|
||||
"}";
|
||||
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->finalize = xed_status_combo_box_finalize;
|
||||
object_class->get_property = xed_status_combo_box_get_property;
|
||||
object_class->set_property = xed_status_combo_box_set_property;
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
#include "xed-print-preview.h"
|
||||
#include "xed-progress-info-bar.h"
|
||||
#include "xed-debug.h"
|
||||
#include "xed-document.h"
|
||||
#include "xed-document-private.h"
|
||||
#include "xed-enum-types.h"
|
||||
#include "xed-settings.h"
|
||||
#include "xed-view-frame.h"
|
||||
|
@ -1112,39 +1114,39 @@ view_focused_in (GtkWidget *widget,
|
|||
XedTab *tab)
|
||||
{
|
||||
XedDocument *doc;
|
||||
GtkSourceFile *file;
|
||||
|
||||
g_return_val_if_fail (XED_IS_TAB (tab), FALSE);
|
||||
|
||||
/* we try to detect file changes only in the normal state */
|
||||
if (tab->priv->state != XED_TAB_STATE_NORMAL)
|
||||
{
|
||||
return FALSE;
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
/* we already asked, don't bug the user again */
|
||||
if (!tab->priv->ask_if_externally_modified)
|
||||
{
|
||||
return FALSE;
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
doc = xed_tab_get_document (tab);
|
||||
file = xed_document_get_file (doc);
|
||||
|
||||
/* If file was never saved or is remote we do not check */
|
||||
if (!xed_document_is_local (doc))
|
||||
if (gtk_source_file_is_local (file))
|
||||
{
|
||||
return FALSE;
|
||||
gtk_source_file_check_file_on_disk (file);
|
||||
|
||||
if (gtk_source_file_is_externally_modified (file))
|
||||
{
|
||||
xed_tab_set_state (tab, XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION);
|
||||
|
||||
display_externally_modified_notification (tab);
|
||||
}
|
||||
}
|
||||
|
||||
if (_xed_document_check_externally_modified (doc))
|
||||
{
|
||||
xed_tab_set_state (tab, XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION);
|
||||
|
||||
display_externally_modified_notification (tab);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -67,6 +67,8 @@ static const GtkActionEntry xed_always_sensitive_menu_entries[] =
|
|||
N_("Open the xed manual"), G_CALLBACK (_xed_cmd_help_contents) },
|
||||
{ "HelpAbout", "help-about-symbolic", N_("_About"), NULL,
|
||||
N_("About this application"), G_CALLBACK (_xed_cmd_help_about) },
|
||||
{ "HelpShortcuts", NULL, N_("_Keyboard Shortcuts"), NULL,
|
||||
N_("Show the keyboard shortcuts dialog"), G_CALLBACK (_xed_cmd_help_keyboard_shortcuts) },
|
||||
|
||||
/* Fullscreen toolbar */
|
||||
{ "LeaveFullscreen", "view-restore-symbolic", NULL,
|
||||
|
|
|
@ -7,7 +7,6 @@ G_DEFINE_TYPE (XedViewGutterRenderer, xed_view_gutter_renderer, GTK_SOURCE_TYPE_
|
|||
static void
|
||||
xed_view_gutter_renderer_class_init (XedViewGutterRendererClass *klass)
|
||||
{
|
||||
GtkSourceGutterRendererClass *renderer_class = GTK_SOURCE_GUTTER_RENDERER_CLASS (klass);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -607,8 +607,36 @@ xed_view_class_init (XedViewClass *klass)
|
|||
|
||||
binding_set = gtk_binding_set_by_class (klass);
|
||||
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_KEY_d, GDK_CONTROL_MASK, "delete_from_cursor", 2, G_TYPE_ENUM,
|
||||
GTK_DELETE_PARAGRAPHS, G_TYPE_INT, 1);
|
||||
gtk_binding_entry_add_signal (binding_set,
|
||||
GDK_KEY_d,
|
||||
GDK_CONTROL_MASK,
|
||||
"delete_from_cursor", 2,
|
||||
G_TYPE_ENUM, GTK_DELETE_PARAGRAPHS,
|
||||
G_TYPE_INT, 1);
|
||||
|
||||
gtk_binding_entry_add_signal (binding_set,
|
||||
GDK_KEY_u,
|
||||
GDK_CONTROL_MASK,
|
||||
"change_case", 1,
|
||||
G_TYPE_ENUM, GTK_SOURCE_CHANGE_CASE_UPPER);
|
||||
|
||||
gtk_binding_entry_add_signal (binding_set,
|
||||
GDK_KEY_l,
|
||||
GDK_CONTROL_MASK,
|
||||
"change_case", 1,
|
||||
G_TYPE_ENUM, GTK_SOURCE_CHANGE_CASE_LOWER);
|
||||
|
||||
gtk_binding_entry_add_signal (binding_set,
|
||||
GDK_KEY_asciitilde,
|
||||
GDK_CONTROL_MASK,
|
||||
"change_case", 1,
|
||||
G_TYPE_ENUM, GTK_SOURCE_CHANGE_CASE_TOGGLE);
|
||||
|
||||
gtk_binding_entry_add_signal (binding_set,
|
||||
GDK_KEY_t,
|
||||
GDK_CONTROL_MASK,
|
||||
"change_case", 1,
|
||||
G_TYPE_ENUM, GTK_SOURCE_CHANGE_CASE_TITLE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -66,9 +66,9 @@ struct _XedWindowPrivate
|
|||
|
||||
/* Widgets for fullscreen mode */
|
||||
GtkWidget *fullscreen_controls;
|
||||
GtkWidget *fullscreen_controls_container;
|
||||
guint fullscreen_animation_timeout_id;
|
||||
gboolean fullscreen_animation_enter;
|
||||
GtkWidget *fullscreen_overlay;
|
||||
GtkWidget *fullscreen_eventbox;
|
||||
GtkWidget *fullscreen_revealer;
|
||||
|
||||
/* statusbar and context ids for statusbar messages */
|
||||
GtkWidget *statusbar;
|
||||
|
|
234
xed/xed-window.c
234
xed/xed-window.c
|
@ -20,6 +20,8 @@
|
|||
#include "xed-utils.h"
|
||||
#include "xed-commands.h"
|
||||
#include "xed-debug.h"
|
||||
#include "xed-document.h"
|
||||
#include "xed-document-private.h"
|
||||
#include "xed-panel.h"
|
||||
#include "xed-documents-panel.h"
|
||||
#include "xed-plugins-engine.h"
|
||||
|
@ -33,8 +35,6 @@
|
|||
#define TAB_WIDTH_DATA "XedWindowTabWidthData"
|
||||
#define LANGUAGE_DATA "XedWindowLanguageData"
|
||||
|
||||
#define FULLSCREEN_ANIMATION_SPEED 4
|
||||
|
||||
#define XED_WINDOW_DEFAULT_WIDTH 650
|
||||
#define XED_WINDOW_DEFAULT_HEIGHT 500
|
||||
|
||||
|
@ -205,18 +205,6 @@ xed_window_dispose (GObject *object)
|
|||
window->priv->dispose_has_run = TRUE;
|
||||
}
|
||||
|
||||
if (window->priv->fullscreen_animation_timeout_id != 0)
|
||||
{
|
||||
g_source_remove (window->priv->fullscreen_animation_timeout_id);
|
||||
window->priv->fullscreen_animation_timeout_id = 0;
|
||||
}
|
||||
|
||||
if (window->priv->fullscreen_controls != NULL)
|
||||
{
|
||||
gtk_widget_destroy (window->priv->fullscreen_controls);
|
||||
window->priv->fullscreen_controls = NULL;
|
||||
}
|
||||
|
||||
if (window->priv->recents_handler_id != 0)
|
||||
{
|
||||
GtkRecentManager *recent_manager;
|
||||
|
@ -1209,7 +1197,6 @@ create_menu_bar_and_toolbar (XedWindow *window,
|
|||
GtkUIManager *manager;
|
||||
GtkRecentManager *recent_manager;
|
||||
GError *error = NULL;
|
||||
gchar *ui_file;
|
||||
GtkWidget *tool_item;
|
||||
GtkWidget *tool_box;
|
||||
GtkWidget *box;
|
||||
|
@ -2182,7 +2169,7 @@ show_overview_map_changed (GObject *object,
|
|||
map_frame = GTK_FRAME (object);
|
||||
action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "ViewOverviewMap");
|
||||
|
||||
if (gtk_widget_get_visible (map_frame))
|
||||
if (gtk_widget_get_visible (GTK_WIDGET (map_frame)))
|
||||
{
|
||||
overveiw_map_visible = TRUE;
|
||||
}
|
||||
|
@ -2235,7 +2222,7 @@ notebook_switch_page (GtkNotebook *book,
|
|||
|
||||
if (window->priv->show_overview_map_id)
|
||||
{
|
||||
g_signal_handler_disconnect (xed_view_frame_get_map_frame (_xed_tab_get_view_frame (window->priv->active_tab)), window->priv->show_overview_map_id);
|
||||
g_signal_handler_disconnect (xed_view_frame_get_map_frame (XED_VIEW_FRAME (_xed_tab_get_view_frame (window->priv->active_tab))), window->priv->show_overview_map_id);
|
||||
window->priv->show_overview_map_id = 0;
|
||||
}
|
||||
}
|
||||
|
@ -2265,7 +2252,7 @@ notebook_switch_page (GtkNotebook *book,
|
|||
update_languages_menu (window);
|
||||
|
||||
view = xed_tab_get_view (tab);
|
||||
map_frame = xed_view_frame_get_map_frame (_xed_tab_get_view_frame (tab));
|
||||
map_frame = xed_view_frame_get_map_frame (XED_VIEW_FRAME (_xed_tab_get_view_frame (tab)));
|
||||
|
||||
/* sync the statusbar */
|
||||
update_cursor_position_statusbar (GTK_TEXT_BUFFER (xed_tab_get_document (tab)), window);
|
||||
|
@ -2372,15 +2359,6 @@ set_sensitivity_according_to_window_state (XedWindow *window)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_tab_autosave (GtkWidget *widget,
|
||||
gpointer data)
|
||||
{
|
||||
XedTab *tab = XED_TAB(widget);
|
||||
gboolean *enabled = (gboolean *) data;
|
||||
xed_tab_set_auto_save_enabled (tab, *enabled);
|
||||
}
|
||||
|
||||
static void
|
||||
analyze_tab_state (XedTab *tab,
|
||||
XedWindow *window)
|
||||
|
@ -2456,7 +2434,7 @@ update_can_close (XedWindow *window)
|
|||
GList *l;
|
||||
gboolean can_close = TRUE;
|
||||
|
||||
tabs = xed_notebook_get_all_tabs (priv->notebook);
|
||||
tabs = xed_notebook_get_all_tabs (XED_NOTEBOOK (priv->notebook));
|
||||
|
||||
for (l = tabs; l != NULL; l = g_list_next (l))
|
||||
{
|
||||
|
@ -2634,143 +2612,22 @@ drop_uris_cb (GtkWidget *widget,
|
|||
load_uris_from_drop (window, uri_list);
|
||||
}
|
||||
|
||||
static void
|
||||
fullscreen_controls_show (XedWindow *window)
|
||||
{
|
||||
GdkScreen *screen;
|
||||
GdkRectangle fs_rect;
|
||||
gint min_h, nat_h;
|
||||
|
||||
screen = gtk_window_get_screen (GTK_WINDOW (window));
|
||||
gdk_screen_get_monitor_geometry (
|
||||
screen, gdk_screen_get_monitor_at_window (screen, gtk_widget_get_window (GTK_WIDGET(window))),
|
||||
&fs_rect);
|
||||
|
||||
gtk_widget_get_preferred_height (window->priv->fullscreen_controls_container, &min_h, &nat_h);
|
||||
gtk_window_resize (GTK_WINDOW (window->priv->fullscreen_controls), fs_rect.width, nat_h);
|
||||
gtk_window_move (GTK_WINDOW (window->priv->fullscreen_controls), fs_rect.x, fs_rect.y - nat_h + 1);
|
||||
|
||||
gtk_widget_show_all (window->priv->fullscreen_controls);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
run_fullscreen_animation (gpointer data)
|
||||
{
|
||||
XedWindow *window = XED_WINDOW(data);
|
||||
GdkScreen *screen;
|
||||
GdkRectangle fs_rect;
|
||||
gint x, y;
|
||||
|
||||
screen = gtk_window_get_screen (GTK_WINDOW(window));
|
||||
gdk_screen_get_monitor_geometry (screen,
|
||||
gdk_screen_get_monitor_at_window (screen, gtk_widget_get_window (GTK_WIDGET(window))),
|
||||
&fs_rect);
|
||||
|
||||
gtk_window_get_position (GTK_WINDOW(window->priv->fullscreen_controls), &x, &y);
|
||||
|
||||
if (window->priv->fullscreen_animation_enter)
|
||||
{
|
||||
if (y == fs_rect.y)
|
||||
{
|
||||
window->priv->fullscreen_animation_timeout_id = 0;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_window_move (GTK_WINDOW(window->priv->fullscreen_controls), x, y + 1);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gint w, h;
|
||||
gtk_window_get_size (GTK_WINDOW(window->priv->fullscreen_controls), &w, &h);
|
||||
if (y == fs_rect.y - h + 1)
|
||||
{
|
||||
window->priv->fullscreen_animation_timeout_id = 0;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_window_move (GTK_WINDOW(window->priv->fullscreen_controls), x, y - 1);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
show_hide_fullscreen_toolbar (XedWindow *window,
|
||||
gboolean show,
|
||||
gint height)
|
||||
{
|
||||
GtkSettings *settings;
|
||||
gboolean enable_animations;
|
||||
|
||||
settings = gtk_widget_get_settings (GTK_WIDGET(window));
|
||||
g_object_get (G_OBJECT(settings), "gtk-enable-animations", &enable_animations, NULL);
|
||||
|
||||
if (enable_animations)
|
||||
{
|
||||
window->priv->fullscreen_animation_enter = show;
|
||||
if (window->priv->fullscreen_animation_timeout_id == 0)
|
||||
{
|
||||
window->priv->fullscreen_animation_timeout_id = g_timeout_add (FULLSCREEN_ANIMATION_SPEED,
|
||||
(GSourceFunc) run_fullscreen_animation, window);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GdkRectangle fs_rect;
|
||||
GdkScreen *screen;
|
||||
screen = gtk_window_get_screen (GTK_WINDOW(window));
|
||||
gdk_screen_get_monitor_geometry (screen,
|
||||
gdk_screen_get_monitor_at_window (screen, gtk_widget_get_window (GTK_WIDGET(window))),
|
||||
&fs_rect);
|
||||
|
||||
if (show)
|
||||
{
|
||||
gtk_window_move (GTK_WINDOW(window->priv->fullscreen_controls), fs_rect.x, fs_rect.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_window_move (GTK_WINDOW(window->priv->fullscreen_controls), fs_rect.x, fs_rect.y - height + 1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_fullscreen_controls_enter_notify_event (GtkWidget *widget,
|
||||
on_fullscreen_controls_enter_notify_event (GtkWidget *widget,
|
||||
GdkEventCrossing *event,
|
||||
XedWindow *window)
|
||||
XedWindow *window)
|
||||
{
|
||||
show_hide_fullscreen_toolbar (window, TRUE, 0);
|
||||
gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->fullscreen_controls), TRUE);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_fullscreen_controls_leave_notify_event (GtkWidget *widget,
|
||||
on_fullscreen_controls_leave_notify_event (GtkWidget *widget,
|
||||
GdkEventCrossing *event,
|
||||
XedWindow *window)
|
||||
XedWindow *window)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
GdkScreen *screen;
|
||||
gint w, h;
|
||||
gint x, y;
|
||||
|
||||
display = gdk_display_get_default ();
|
||||
screen = gtk_window_get_screen (GTK_WINDOW(window));
|
||||
|
||||
gtk_window_get_size (GTK_WINDOW(window->priv->fullscreen_controls), &w, &h);
|
||||
gdk_display_get_pointer (display, &screen, &x, &y, NULL);
|
||||
|
||||
/* gtk seems to emit leave notify when clicking on tool items,
|
||||
* work around it by checking the coordinates
|
||||
*/
|
||||
if (y >= h)
|
||||
{
|
||||
show_hide_fullscreen_toolbar (window, FALSE, h);
|
||||
}
|
||||
gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->fullscreen_controls), FALSE);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -2781,6 +2638,9 @@ fullscreen_controls_build (XedWindow *window)
|
|||
XedWindowPrivate *priv = window->priv;
|
||||
GtkAction *action;
|
||||
GtkWidget *box;
|
||||
GtkWidget *toolbar;
|
||||
GtkWidget *toolitem;
|
||||
GtkWidget *toolbox;
|
||||
GtkWidget *fullscreen_btn;
|
||||
GtkWidget *separator;
|
||||
GtkWidget *button;
|
||||
|
@ -2790,17 +2650,23 @@ fullscreen_controls_build (XedWindow *window)
|
|||
return;
|
||||
}
|
||||
|
||||
priv->fullscreen_controls = gtk_window_new (GTK_WINDOW_POPUP);
|
||||
priv->fullscreen_controls = gtk_revealer_new ();
|
||||
gtk_widget_set_valign (priv->fullscreen_controls, GTK_ALIGN_START);
|
||||
gtk_container_add (GTK_CONTAINER (priv->fullscreen_eventbox), priv->fullscreen_controls);
|
||||
|
||||
gtk_window_set_transient_for (GTK_WINDOW (priv->fullscreen_controls), GTK_WINDOW (&window->window));
|
||||
toolbar = gtk_toolbar_new ();
|
||||
toolitem = gtk_tool_item_new ();
|
||||
gtk_tool_item_set_expand (GTK_TOOL_ITEM (toolitem), TRUE);
|
||||
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (toolitem), 0);
|
||||
|
||||
window->priv->fullscreen_controls_container = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (window->priv->fullscreen_controls_container), 6);
|
||||
gtk_container_add (GTK_CONTAINER (priv->fullscreen_controls), window->priv->fullscreen_controls_container);
|
||||
toolbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (toolbar), "primary-toolbar");
|
||||
gtk_container_add (GTK_CONTAINER (toolitem), toolbox);
|
||||
gtk_container_add (GTK_CONTAINER (priv->fullscreen_controls), toolbar);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_widget_set_vexpand (box, FALSE);
|
||||
gtk_box_pack_start (GTK_BOX (window->priv->fullscreen_controls_container), box, FALSE, FALSE, 0);
|
||||
gtk_box_pack_start (GTK_BOX (toolbox), box, FALSE, FALSE, 0);
|
||||
|
||||
action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "FileNew");
|
||||
button = create_toolbar_button (action);
|
||||
|
@ -2856,13 +2722,15 @@ fullscreen_controls_build (XedWindow *window)
|
|||
fullscreen_btn = create_toolbar_button (action);
|
||||
gtk_box_pack_end (GTK_BOX (box), fullscreen_btn, FALSE, FALSE, 0);
|
||||
|
||||
gtk_widget_show_all (window->priv->fullscreen_controls_container);
|
||||
gtk_widget_show_all (toolbox);
|
||||
|
||||
g_signal_connect(priv->fullscreen_controls, "enter-notify-event",
|
||||
G_CALLBACK (on_fullscreen_controls_enter_notify_event), window);
|
||||
g_signal_connect (priv->fullscreen_eventbox, "enter-notify-event",
|
||||
G_CALLBACK (on_fullscreen_controls_enter_notify_event), window);
|
||||
|
||||
g_signal_connect(priv->fullscreen_controls, "leave-notify-event",
|
||||
G_CALLBACK (on_fullscreen_controls_leave_notify_event), window);
|
||||
g_signal_connect (priv->fullscreen_eventbox, "leave-notify-event",
|
||||
G_CALLBACK (on_fullscreen_controls_leave_notify_event), window);
|
||||
|
||||
gtk_widget_set_size_request (priv->fullscreen_eventbox, -1, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -3069,7 +2937,7 @@ notebook_tab_removed (XedNotebook *notebook,
|
|||
--window->priv->num_tabs;
|
||||
|
||||
view = xed_tab_get_view (tab);
|
||||
frame = _xed_tab_get_view_frame (tab);
|
||||
frame = XED_VIEW_FRAME (_xed_tab_get_view_frame (tab));
|
||||
doc = xed_tab_get_document (tab);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (tab, G_CALLBACK (sync_name), window);
|
||||
|
@ -3272,7 +3140,7 @@ side_panel_size_allocate (GtkWidget *widget,
|
|||
GtkAllocation *allocation,
|
||||
XedWindow *window)
|
||||
{
|
||||
if (!xed_paned_get_is_animating (window->priv->hpaned))
|
||||
if (!xed_paned_get_is_animating (XED_PANED (window->priv->hpaned)))
|
||||
{
|
||||
window->priv->side_panel_size = allocation->width;
|
||||
}
|
||||
|
@ -3283,7 +3151,7 @@ bottom_panel_size_allocate (GtkWidget *widget,
|
|||
GtkAllocation *allocation,
|
||||
XedWindow *window)
|
||||
{
|
||||
if (!xed_paned_get_is_animating (window->priv->vpaned))
|
||||
if (!xed_paned_get_is_animating (XED_PANED (window->priv->vpaned)))
|
||||
{
|
||||
window->priv->bottom_panel_size = allocation->height;
|
||||
}
|
||||
|
@ -3404,7 +3272,7 @@ bottom_panel_item_removed (XedPanel *panel,
|
|||
{
|
||||
GtkAction *action;
|
||||
|
||||
xed_paned_close (window->priv->vpaned, 2);
|
||||
xed_paned_close (XED_PANED (window->priv->vpaned), 2);
|
||||
gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->bottom_pane_button_revealer), FALSE);
|
||||
action = gtk_action_group_get_action (window->priv->panes_action_group, "ViewBottomPane");
|
||||
gtk_action_set_sensitive (action, FALSE);
|
||||
|
@ -3529,14 +3397,7 @@ check_window_is_active (XedWindow *window,
|
|||
{
|
||||
if (window->priv->window_state & GDK_WINDOW_STATE_FULLSCREEN)
|
||||
{
|
||||
if (gtk_window_is_active (GTK_WINDOW(window)))
|
||||
{
|
||||
gtk_widget_show (window->priv->fullscreen_controls);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_hide (window->priv->fullscreen_controls);
|
||||
}
|
||||
gtk_widget_set_visible (window->priv->fullscreen_eventbox, gtk_window_is_active (GTK_WINDOW (window)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3604,7 +3465,6 @@ xed_window_init (XedWindow *window)
|
|||
window->priv->inhibition_cookie = 0;
|
||||
window->priv->dispose_has_run = FALSE;
|
||||
window->priv->fullscreen_controls = NULL;
|
||||
window->priv->fullscreen_animation_timeout_id = 0;
|
||||
window->priv->editor_settings = g_settings_new ("org.x.editor.preferences.editor");
|
||||
window->priv->ui_settings = g_settings_new ("org.x.editor.preferences.ui");
|
||||
|
||||
|
@ -3621,9 +3481,16 @@ xed_window_init (XedWindow *window)
|
|||
gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (window)), "xed-window");
|
||||
|
||||
main_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_container_add (GTK_CONTAINER (window), main_box);
|
||||
window->priv->fullscreen_overlay = gtk_overlay_new ();
|
||||
gtk_container_add (GTK_CONTAINER (window->priv->fullscreen_overlay), main_box);
|
||||
gtk_container_add (GTK_CONTAINER (window), window->priv->fullscreen_overlay);
|
||||
gtk_widget_show (window->priv->fullscreen_overlay);
|
||||
gtk_widget_show (main_box);
|
||||
|
||||
window->priv->fullscreen_eventbox = gtk_event_box_new ();
|
||||
gtk_widget_set_valign (window->priv->fullscreen_eventbox, GTK_ALIGN_START);
|
||||
gtk_overlay_add_overlay (GTK_OVERLAY (window->priv->fullscreen_overlay), window->priv->fullscreen_eventbox);
|
||||
|
||||
/* Add menu bar and toolbar bar */
|
||||
create_menu_bar_and_toolbar (window, main_box);
|
||||
|
||||
|
@ -4322,7 +4189,8 @@ _xed_window_fullscreen (XedWindow *window)
|
|||
gtk_widget_hide (window->priv->statusbar);
|
||||
|
||||
fullscreen_controls_build (window);
|
||||
fullscreen_controls_show (window);
|
||||
|
||||
gtk_widget_show_all (window->priv->fullscreen_eventbox);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -4359,7 +4227,7 @@ _xed_window_unfullscreen (XedWindow *window)
|
|||
}
|
||||
g_signal_handlers_unblock_by_func (window->priv->statusbar, statusbar_visibility_changed, window);
|
||||
|
||||
gtk_widget_hide (window->priv->fullscreen_controls);
|
||||
gtk_widget_hide (window->priv->fullscreen_eventbox);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
Loading…
Reference in New Issue