diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000000000000000000000000000000000000..1ce8223982923e68f47be72ef7bff1927db81e38
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,16 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+
+[*.[ch]]
+indent_size = 8
+indent_style = tab
+insert_final_newline = true
+max_line_length = 80
+tab_width = 8
+
+[meson.build]
+indent_size = 2
+indent_style = space
diff --git a/HACKING b/HACKING
index a481180726b75cbf3ea853ed4d61aae0bacd0f9d..f499c9228edcd1eb5c62794fa770db1f5f2b2adc 100644
--- a/HACKING
+++ b/HACKING
@@ -25,13 +25,11 @@ C code conventions
You may encounter old code that doesn't follow all the following code
conventions, but for new code it is better to follow them, for consistency.
-In the scripts/ directory there is an uncrustify config file with a script to
-apply the coding style to a certain *.c file. The script has not (yet) been run
-on all the GtkSourceView source code, but it can serve as a guideline.
-
- Avoid trailing whitespace.
- Indent the C code with tabulations with a width of eight characters.
+ However, alignment after matching the current scope should be done
+ with spaces.
- All blocks should be surrounded by curly braces, even one-line blocks. The
curly braces must be placed on their own lines. Like this:
@@ -49,9 +47,12 @@ on all the GtkSourceView source code, but it can serve as a guideline.
modifying a block of code, if it switches between one and two lines, we
don't need to add/remove the curly braces all the time.
- - Follow the C89 standard. In particular, no "//"-style comments.
+ - Follow the C99 standard but without "//"-style comments. Some restrictions
+ apply but relatively should match GTK and GLib.
- - The files should have a modeline for the indentation style.
+ - The files should not have modelines included. A .editorconfig file is
+ provided for configuration indentation and many editors have support for
+ using them.
- Do not be cheap about blank lines, spacing the code vertically helps
readability. However never use two consecutive blank lines, there is really
@@ -61,9 +62,10 @@ on all the GtkSourceView source code, but it can serve as a guideline.
code.
See also:
-https://developer.gnome.org/programming-guidelines/stable/
-https://wiki.gnome.org/Projects/GTK%2B/BestPractices
-https://wiki.gnome.org/Projects/GLib/CompilerRequirements
+
+ - https://developer.gnome.org/programming-guidelines/stable/
+ - https://wiki.gnome.org/Projects/GTK%2B/BestPractices
+ - https://wiki.gnome.org/Projects/GLib/CompilerRequirements
Programming best-practices
--------------------------
@@ -75,9 +77,9 @@ old. So when editing the code, we should try to make it better, not worse.
Here are some general advices:
- Simplicity: the simpler code the better. Any trick that seem smart when you
- write it is going to bite your ass later when reading the code. In fact, a
+ write it is going to bite you later when reading the code. In fact, the
code is read far more often than it is written: for fixing a bug, adding a
- feature, or simply see how it is implemented. So making the code harder to
+ feature, or simply see how it is implemented. Making the code harder to
read is a net loss.
- Avoid code duplication, make an effort to refactor common code into utility
@@ -132,6 +134,17 @@ Here are some general advices:
writing hacks or heuristics to work around a bug or a lack of feature in an
underlying library.
+ - Public API should have precondition guards using g_return_if_fail() or
+ g_return_val_if_fail(). Optionally, you may do this before returnin values
+ from the function to help catch bugs earlier in the development cycle.
+
+ Private functions (such as those with static) should use g_assert() to
+ validate invariants. These are used in debug builds but can be compiled
+ out of production/release builds.
+
+ - When transfering ownership of an object or struct, use g_steal_pointer()
+ to make it clear when reading that ownership was transfered.
+
See also:
https://blogs.gnome.org/swilmet/2012/08/01/about-code-quality-and-maintainability/
diff --git a/README.md b/README.md
index ba6edee82b0d01bdb7f254253b8ffbf5f549e1f4..b6d0213989829d9b16ec6903d7b6f7b41cb649a3 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,8 @@
GtkSourceView
=============
+This is a development branch progressing towards GTK 4 support.
+
GtkSourceView is a GNOME library that extends GtkTextView, the standard GTK+
widget for multiline text editing. GtkSourceView adds support for syntax
highlighting, undo/redo, file loading and saving, search and replace, a
@@ -14,8 +16,8 @@ The official web site is https://wiki.gnome.org/Projects/GtkSourceView.
Dependencies
------------
-* GLib >= 2.48
-* GTK+ >= 3.24
+* GLib >= 2.62
+* GTK+ >= 3.96
* libxml2 >= 2.6
* freebidi >= 0.19.7
diff --git a/data/fonts/BuilderBlocks.ttf b/data/fonts/BuilderBlocks.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..8fe8942068f15a7f415be980c68e614c3f7c5ff8
Binary files /dev/null and b/data/fonts/BuilderBlocks.ttf differ
diff --git a/data/fonts/BuilderBlocks.ttx b/data/fonts/BuilderBlocks.ttx
new file mode 100644
index 0000000000000000000000000000000000000000..23c47c402538a233c102a006cd2b544e1902b8a1
--- /dev/null
+++ b/data/fonts/BuilderBlocks.ttx
@@ -0,0 +1,137 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ BuilderBlocks
+
+
+
+
+
+
+ 0000 0001
+ 0003 000A
+ 0000000C
+ 000D 0000
+ 00000040
+ 00000000
+ 00000004
+ 00000001
+ 00000020
+ 00000002
+ 00000021
+ 00000060
+ 00000001
+ 00000061
+ 0000007A
+ 00000003
+ 0000007B
+ 0010FFFE
+ 00000001
+
+
+
+
diff --git a/data/glade/gtksourceview.xml.in b/data/glade/gtksourceview.xml.in
deleted file mode 100644
index 4b2c298454e1514794f1ca4db28a2839629b9883..0000000000000000000000000000000000000000
--- a/data/glade/gtksourceview.xml.in
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/data/glade/meson.build b/data/glade/meson.build
deleted file mode 100644
index 3148632b4c96aaedab06d34867a9bd101d3d170b..0000000000000000000000000000000000000000
--- a/data/glade/meson.build
+++ /dev/null
@@ -1,37 +0,0 @@
-# Note that we do not install in the detected GLADE_CATALOG_DIR
-# since we may not have permissions to do it, for instance if
-# compiling with a prefix while glade is installed in /usr.
-# We use the variable only to find the dtd file.
-# If you install gtksourceview and glade in different prefixes
-# and want to use the catalog in glade, you will need to set
-# the GLADE_CATALOG_SEARCH_PATH environment variable.
-
-catalog_in = configuration_data()
-catalog_in.set('GSV_API_VERSION', api_version)
-
-catalog_xml = configure_file(
- input: 'gtksourceview.xml.in',
- output: 'gtksourceview.xml',
- configuration: catalog_in,
- install_dir: join_paths(datadir, 'glade', 'catalogs')
-)
-
-# Currently DTD validation does not work with glade's DTD.
-# This does not appear to be limited to GtkSourceView.
-#if xmllint_prg.found()
-# catalog_dtd = join_paths(
-# gladeui_dep.get_pkgconfig_variable('catalogdir'),
-# 'glade-catalog.dtd'
-# )
-#
-# test(
-# 'Validate Glade catalogue',
-# xmllint_prg,
-# args: [
-# '--dtdvalid',
-# catalog_dtd,
-# catalog_xml,
-# '--noout',
-# ]
-# )
-#endif
diff --git a/data/icons/COPYING b/data/icons/COPYING
new file mode 100644
index 0000000000000000000000000000000000000000..2f789c3b148d9ba3e5c4e9af0e9912b477b3cfd4
--- /dev/null
+++ b/data/icons/COPYING
@@ -0,0 +1,6 @@
+The icons here are licensed under the CC-by-SA 3. You can find the full text of
+the license at:
+
+ http://creativecommons.org/licenses/by-sa/3.0/
+
+See git commit's for authors and contributors to individual icons.
diff --git a/data/icons/hicolor/scalable/actions/completion-snippet-symbolic.svg b/data/icons/hicolor/scalable/actions/completion-snippet-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..4ddad984fb695581032e329f4620ba25856d1423
--- /dev/null
+++ b/data/icons/hicolor/scalable/actions/completion-snippet-symbolic.svg
@@ -0,0 +1,10 @@
+
diff --git a/data/icons/hicolor/scalable/actions/completion-word-symbolic.svg b/data/icons/hicolor/scalable/actions/completion-word-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..140a4e4b9f278d76fdb9e23cea14f6b759efdee1
--- /dev/null
+++ b/data/icons/hicolor/scalable/actions/completion-word-symbolic.svg
@@ -0,0 +1,3 @@
+
diff --git a/data/icons/hicolor/scalable/actions/lang-class-symbolic.svg b/data/icons/hicolor/scalable/actions/lang-class-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..337e29f1aa08bee5889e46bfb6e606d65c589dd0
--- /dev/null
+++ b/data/icons/hicolor/scalable/actions/lang-class-symbolic.svg
@@ -0,0 +1,5 @@
+
diff --git a/data/icons/hicolor/scalable/actions/lang-define-symbolic.svg b/data/icons/hicolor/scalable/actions/lang-define-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..1caef0f445ce35f09c81616e533e4b4c1f52e369
--- /dev/null
+++ b/data/icons/hicolor/scalable/actions/lang-define-symbolic.svg
@@ -0,0 +1,3 @@
+
diff --git a/data/icons/hicolor/scalable/actions/lang-enum-symbolic.svg b/data/icons/hicolor/scalable/actions/lang-enum-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..cb0b2917154cc6c068cc230901130ca212e86783
--- /dev/null
+++ b/data/icons/hicolor/scalable/actions/lang-enum-symbolic.svg
@@ -0,0 +1,3 @@
+
diff --git a/data/icons/hicolor/scalable/actions/lang-enum-value-symbolic.svg b/data/icons/hicolor/scalable/actions/lang-enum-value-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..8e47e29a478adea64c7f01e9f9d50e353a7bfb12
--- /dev/null
+++ b/data/icons/hicolor/scalable/actions/lang-enum-value-symbolic.svg
@@ -0,0 +1,3 @@
+
diff --git a/data/icons/hicolor/scalable/actions/lang-function-symbolic.svg b/data/icons/hicolor/scalable/actions/lang-function-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e29109e4f59ceaccc5f6592584a33c2a6eff55a1
--- /dev/null
+++ b/data/icons/hicolor/scalable/actions/lang-function-symbolic.svg
@@ -0,0 +1,6 @@
+
diff --git a/data/icons/hicolor/scalable/actions/lang-include-symbolic.svg b/data/icons/hicolor/scalable/actions/lang-include-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..73b4d0f78c71779627c19d4787446f1fea11c3aa
--- /dev/null
+++ b/data/icons/hicolor/scalable/actions/lang-include-symbolic.svg
@@ -0,0 +1,3 @@
+
diff --git a/data/icons/hicolor/scalable/actions/lang-method-symbolic.svg b/data/icons/hicolor/scalable/actions/lang-method-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..f8b16afa63d56407fa146097067e374f91e68557
--- /dev/null
+++ b/data/icons/hicolor/scalable/actions/lang-method-symbolic.svg
@@ -0,0 +1,6 @@
+
diff --git a/data/icons/hicolor/scalable/actions/lang-namespace-symbolic.svg b/data/icons/hicolor/scalable/actions/lang-namespace-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..241c78e02fe9e0f155d2546252aff595c37ab497
--- /dev/null
+++ b/data/icons/hicolor/scalable/actions/lang-namespace-symbolic.svg
@@ -0,0 +1,6 @@
+
diff --git a/data/icons/hicolor/scalable/actions/lang-struct-field-symbolic.svg b/data/icons/hicolor/scalable/actions/lang-struct-field-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..7729007129dbd90c25c3e0f0750147d0ca359768
--- /dev/null
+++ b/data/icons/hicolor/scalable/actions/lang-struct-field-symbolic.svg
@@ -0,0 +1,3 @@
+
diff --git a/data/icons/hicolor/scalable/actions/lang-struct-symbolic.svg b/data/icons/hicolor/scalable/actions/lang-struct-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..b2daa4fbe59f990dc71e24968627ac0faf9d83ce
--- /dev/null
+++ b/data/icons/hicolor/scalable/actions/lang-struct-symbolic.svg
@@ -0,0 +1,3 @@
+
diff --git a/data/icons/hicolor/scalable/actions/lang-typedef-symbolic.svg b/data/icons/hicolor/scalable/actions/lang-typedef-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e5174b2d81b74093a5a1b863b5446aa1ca048bac
--- /dev/null
+++ b/data/icons/hicolor/scalable/actions/lang-typedef-symbolic.svg
@@ -0,0 +1,3 @@
+
diff --git a/data/icons/hicolor/scalable/actions/lang-union-symbolic.svg b/data/icons/hicolor/scalable/actions/lang-union-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..1db71e0cd8984e5f016fb3a6e6d4595629c001f1
--- /dev/null
+++ b/data/icons/hicolor/scalable/actions/lang-union-symbolic.svg
@@ -0,0 +1,3 @@
+
diff --git a/data/icons/hicolor/scalable/actions/lang-variable-symbolic.svg b/data/icons/hicolor/scalable/actions/lang-variable-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e74c0b153a675d79fc0b4793d135d2883e9fc4af
--- /dev/null
+++ b/data/icons/hicolor/scalable/actions/lang-variable-symbolic.svg
@@ -0,0 +1,3 @@
+
diff --git a/data/icons/meson.build b/data/icons/meson.build
new file mode 100644
index 0000000000000000000000000000000000000000..b7a96d967c01a7663dd048db4ae31d274a78fdb6
--- /dev/null
+++ b/data/icons/meson.build
@@ -0,0 +1,3 @@
+iconsdir = join_paths(get_option('datadir'), 'icons')
+
+install_subdir('hicolor', install_dir: iconsdir)
diff --git a/data/meson.build b/data/meson.build
index 2ca97a5f4ba82fbe86970bcb6fa3ac0b0bdfcc4d..e92067b9afbdd1f17a35f2a7a89e9fb18b9c0d49 100644
--- a/data/meson.build
+++ b/data/meson.build
@@ -1,7 +1,3 @@
-if install_glade_catalog
- subdir('glade')
-endif
-
install_subdir('language-specs',
install_dir: pkgdatadir,
exclude_files: [ 'Makefile.am',
@@ -23,3 +19,15 @@ install_subdir('styles',
'testdark.xml',
'update-pot.sh' ]
)
+
+install_subdir('fonts',
+ install_dir: pkgdatadir,
+ exclude_files: [ 'BuilderBlocks.ttx' ]
+)
+
+install_subdir('snippets',
+ install_dir: pkgdatadir,
+ exclude_files: [],
+)
+
+subdir('icons')
diff --git a/data/snippets/licenses.snippets b/data/snippets/licenses.snippets
new file mode 100644
index 0000000000000000000000000000000000000000..d764c68f7c15fee44be542fae1b0768d1b872b9a
--- /dev/null
+++ b/data/snippets/licenses.snippets
@@ -0,0 +1,357 @@
+
+
+
+
+
+
+
+
+#
+# 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 3 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, see .
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+$0]]>
+
+ *
+ * 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 3 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, see .
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+$0]]>
+
+//
+// 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 3 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, see .
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+$0]]>
+
+
+
+
+
+
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or (at
+# your option) any later version.
+#
+# This file 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 Lesser General Public
+# License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see .
+#
+# SPDX-License-Identifier: LGPL-3.0-or-later
+$0]]>
+
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This file 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ *
+ * SPDX-License-Identifier: LGPL-3.0-or-later
+ */
+$0]]>
+
+//
+// This file is free software; you can redistribute it and/or modify it
+// under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or (at
+// your option) any later version.
+//
+// This file 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 Lesser General Public
+// License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+$0]]>
+
+
+
+
+
+
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this library; if not, see .
+#
+# SPDX-License-Identifier: LGPL-2.1-or-later
+$0]]>
+
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+$0]]>
+
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, see .
+//
+// SPDX-License-Identifier: LGPL-2.1-or-later
+$0]]>
+
+
+
+
+
+
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+$0]]>
+
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+$0]]>
+
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: Apache-2.0
+$0]]>
+
+
+
+
+
+
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+# SPDX-License-Identifier: MIT
+$0]]>
+
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * SPDX-License-Identifier: MIT
+ */
+$0]]>
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//
+// SPDX-License-Identifier: MIT
+$0]]>
+
+
diff --git a/data/snippets/snippets.rng b/data/snippets/snippets.rng
new file mode 100644
index 0000000000000000000000000000000000000000..fff388edf1470a2853ef3da80d5c9a272d008a16
--- /dev/null
+++ b/data/snippets/snippets.rng
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+ 1.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/styles/classic.xml b/data/styles/classic.xml
index 183f5881e28dbfa7d2ea91910bd151c8b22970ac..ad75bbcc037c2015463eae841bda247dc5cb9793 100644
--- a/data/styles/classic.xml
+++ b/data/styles/classic.xml
@@ -47,6 +47,7 @@
+
diff --git a/data/styles/cobalt.xml b/data/styles/cobalt.xml
index 4405156795528824d2ae8bc15a4ce8bc6bd461c8..6d6159eeb1595b0a0152258be1b59eb76baf6a03 100644
--- a/data/styles/cobalt.xml
+++ b/data/styles/cobalt.xml
@@ -60,6 +60,7 @@
+
diff --git a/data/styles/kate.xml b/data/styles/kate.xml
index 617ba58390f35df9a006e8db9e90a514e0a11ccf..5c786d2d9e9c32bb52ada491e3a4600309d7f29c 100644
--- a/data/styles/kate.xml
+++ b/data/styles/kate.xml
@@ -45,6 +45,7 @@
+
diff --git a/data/styles/oblivion.xml b/data/styles/oblivion.xml
index 4b0a8cec13175b5f4bf5279b66cbd3b4a70a55e1..f69f9196b233368a778dc92193051d45f29f2101 100644
--- a/data/styles/oblivion.xml
+++ b/data/styles/oblivion.xml
@@ -69,6 +69,7 @@
+
diff --git a/data/styles/solarized-dark.xml b/data/styles/solarized-dark.xml
index 16cf7c7fb6893c19f3865d4edbc355d92de83ac6..0a67d9e85e8fafe1f5c460ff77723ef253593d97 100644
--- a/data/styles/solarized-dark.xml
+++ b/data/styles/solarized-dark.xml
@@ -51,6 +51,7 @@
+
diff --git a/data/styles/solarized-light.xml b/data/styles/solarized-light.xml
index 33d2bad63007410f9a7992d33b6fb3c257e163f9..ae2c84806d37774849b821ddb31a89998dc4aec7 100644
--- a/data/styles/solarized-light.xml
+++ b/data/styles/solarized-light.xml
@@ -51,6 +51,7 @@
+
diff --git a/data/styles/tango.xml b/data/styles/tango.xml
index 6b2721760854b3f9ad46de341de92ea26d9ced8b..cd6f97da325496e6be14bba4f0b7156dcfa9e43c 100644
--- a/data/styles/tango.xml
+++ b/data/styles/tango.xml
@@ -59,6 +59,7 @@
+
diff --git a/docs/reference/gtksourceview-4.0-sections.txt b/docs/reference/gtksourceview-5.0-sections.txt
similarity index 84%
rename from docs/reference/gtksourceview-4.0-sections.txt
rename to docs/reference/gtksourceview-5.0-sections.txt
index fa191e936ec1505aa885be3d73ceac6829714ddc..bacb98da231ea680fb3a7698b0059cc34d690047 100644
--- a/docs/reference/gtksourceview-4.0-sections.txt
+++ b/docs/reference/gtksourceview-5.0-sections.txt
@@ -19,17 +19,6 @@ gtk_source_buffer_get_highlight_syntax
gtk_source_buffer_set_highlight_matching_brackets
gtk_source_buffer_get_highlight_matching_brackets
gtk_source_buffer_ensure_highlight
-
-gtk_source_buffer_undo
-gtk_source_buffer_redo
-gtk_source_buffer_can_undo
-gtk_source_buffer_can_redo
-gtk_source_buffer_begin_not_undoable_action
-gtk_source_buffer_end_not_undoable_action
-gtk_source_buffer_get_max_undo_levels
-gtk_source_buffer_set_max_undo_levels
-gtk_source_buffer_get_undo_manager
-gtk_source_buffer_set_undo_manager
gtk_source_buffer_iter_has_context_class
gtk_source_buffer_get_context_classes_at_iter
@@ -56,7 +45,6 @@ GTK_SOURCE_BUFFER
GTK_SOURCE_BUFFER_CLASS
GTK_SOURCE_BUFFER_GET_CLASS
GTK_SOURCE_TYPE_BUFFER
-GtkSourceBufferPrivate
gtk_source_buffer_get_type
GTK_SOURCE_TYPE_BRACKET_MATCH_TYPE
gtk_source_bracket_match_type_get_type
@@ -89,7 +77,6 @@ GTK_SOURCE_COMPLETION
GTK_SOURCE_COMPLETION_CLASS
GTK_SOURCE_COMPLETION_GET_CLASS
GTK_SOURCE_TYPE_COMPLETION
-GtkSourceCompletionPrivate
GtkSourceCompletionClass
gtk_source_completion_get_type
gtk_source_completion_error_quark
@@ -111,7 +98,6 @@ GTK_SOURCE_COMPLETION_CONTEXT
GTK_SOURCE_COMPLETION_CONTEXT_CLASS
GTK_SOURCE_COMPLETION_CONTEXT_GET_CLASS
GTK_SOURCE_TYPE_COMPLETION_CONTEXT
-GtkSourceCompletionContextPrivate
gtk_source_completion_context_get_type
GtkSourceCompletionContextClass
GTK_SOURCE_TYPE_COMPLETION_ACTIVATION
@@ -130,7 +116,6 @@ GTK_SOURCE_COMPLETION_INFO
GTK_SOURCE_COMPLETION_INFO_CLASS
GTK_SOURCE_COMPLETION_INFO_GET_CLASS
GTK_SOURCE_TYPE_COMPLETION_INFO
-GtkSourceCompletionInfoPrivate
gtk_source_completion_info_get_type
GtkSourceCompletionInfoClass
@@ -155,13 +140,12 @@ GTK_SOURCE_COMPLETION_ITEM_GET_CLASS
GTK_SOURCE_TYPE_COMPLETION_ITEM
gtk_source_completion_item_get_type
GtkSourceCompletionItemClass
-GtkSourceCompletionItemPrivate
completionproposal
GtkSourceCompletionProposal
-GtkSourceCompletionProposalIface
+GtkSourceCompletionProposalInterface
gtk_source_completion_proposal_get_label
gtk_source_completion_proposal_get_markup
gtk_source_completion_proposal_get_text
@@ -175,7 +159,7 @@ gtk_source_completion_proposal_equal
GTK_SOURCE_IS_COMPLETION_PROPOSAL
GTK_SOURCE_COMPLETION_PROPOSAL
-GTK_SOURCE_COMPLETION_PROPOSAL_GET_INTERFACE
+GTK_SOURCE_COMPLETION_PROPOSAL_GET_IFACE
GTK_SOURCE_TYPE_COMPLETION_PROPOSAL
gtk_source_completion_proposal_get_type
@@ -183,7 +167,7 @@ gtk_source_completion_proposal_get_type
completionprovider
GtkSourceCompletionProvider
-GtkSourceCompletionProviderIface
+GtkSourceCompletionProviderInterface
gtk_source_completion_provider_get_name
gtk_source_completion_provider_get_icon
gtk_source_completion_provider_get_icon_name
@@ -200,7 +184,7 @@ gtk_source_completion_provider_get_priority
GTK_SOURCE_IS_COMPLETION_PROVIDER
GTK_SOURCE_COMPLETION_PROVIDER
-GTK_SOURCE_COMPLETION_PROVIDER_GET_INTERFACE
+GTK_SOURCE_COMPLETION_PROVIDER_GET_IFACE
GTK_SOURCE_TYPE_COMPLETION_PROVIDER
gtk_source_completion_provider_get_type
@@ -219,10 +203,24 @@ GTK_SOURCE_IS_COMPLETION_WORDS
GTK_SOURCE_IS_COMPLETION_WORDS_CLASS
GTK_SOURCE_TYPE_COMPLETION_WORDS
GtkSourceCompletionWordsClass
-GtkSourceCompletionWordsPrivate
gtk_source_completion_words_get_type
+
+completionsnippets
+GtkSourceCompletionSnippets
+gtk_source_completion_snippets_new
+
+GTK_SOURCE_COMPLETION_SNIPPETS
+GTK_SOURCE_COMPLETION_SNIPPETS_CLASS
+GTK_SOURCE_COMPLETION_SNIPPETS_GET_CLASS
+GTK_SOURCE_IS_COMPLETION_SNIPPETS
+GTK_SOURCE_IS_COMPLETION_SNIPPETS_CLASS
+GTK_SOURCE_TYPE_COMPLETION_SNIPPETS
+GtkSourceCompletionSnippetsClass
+gtk_source_completion_snippets_get_type
+
+
encoding
GtkSourceEncoding
@@ -270,7 +268,6 @@ GTK_SOURCE_IS_FILE
GTK_SOURCE_IS_FILE_CLASS
GTK_SOURCE_TYPE_FILE
GtkSourceFileClass
-GtkSourceFilePrivate
gtk_source_file_get_type
GTK_SOURCE_TYPE_COMPRESSION_TYPE
gtk_source_compression_type_get_type
@@ -304,7 +301,6 @@ GTK_SOURCE_IS_FILE_LOADER
GTK_SOURCE_IS_FILE_LOADER_CLASS
GTK_SOURCE_TYPE_FILE_LOADER
GtkSourceFileLoaderClass
-GtkSourceFileLoaderPrivate
gtk_source_file_loader_get_type
gtk_source_file_loader_error_quark
GTK_SOURCE_TYPE_FILE_LOADER_ERROR
@@ -341,7 +337,6 @@ GTK_SOURCE_IS_FILE_SAVER
GTK_SOURCE_IS_FILE_SAVER_CLASS
GTK_SOURCE_TYPE_FILE_SAVER
GtkSourceFileSaverClass
-GtkSourceFileSaverPrivate
gtk_source_file_saver_get_type
gtk_source_file_saver_error_quark
GTK_SOURCE_TYPE_FILE_SAVER_ERROR
@@ -354,12 +349,8 @@ gtk_source_file_saver_flags_get_type
gutter
GtkSourceGutter
gtk_source_gutter_get_view
-gtk_source_gutter_get_window_type
gtk_source_gutter_insert
gtk_source_gutter_reorder
-gtk_source_gutter_remove
-gtk_source_gutter_queue_draw
-gtk_source_gutter_get_renderer_at_pos
GtkSourceGutterClass
GTK_SOURCE_IS_GUTTER
@@ -368,37 +359,58 @@ GTK_SOURCE_GUTTER
GTK_SOURCE_GUTTER_CLASS
GTK_SOURCE_GUTTER_GET_CLASS
GTK_SOURCE_TYPE_GUTTER
-GtkSourceGutterPrivate
gtk_source_gutter_get_type
+
+gutterlines
+GtkSourceGutterLines
+gtk_source_gutter_lines_add_class
+gtk_source_gutter_lines_add_qclass
+gtk_source_gutter_lines_get_buffer
+gtk_source_gutter_lines_get_first
+gtk_source_gutter_lines_get_iter_at_line
+gtk_source_gutter_lines_get_last
+gtk_source_gutter_lines_get_line_yrange
+gtk_source_gutter_lines_get_view
+gtk_source_gutter_lines_get_yrange
+gtk_source_gutter_lines_has_class
+gtk_source_gutter_lines_has_qclass
+gtk_source_gutter_lines_is_cursor
+gtk_source_gutter_lines_is_prelit
+gtk_source_gutter_lines_is_selected
+gtk_source_gutter_lines_remove_class
+gtk_source_gutter_lines_remove_qclass
+
+GtkSourceGutterLinesClass
+GTK_SOURCE_IS_GUTTER_LINES
+GTK_SOURCE_IS_GUTTER_LINES_CLASS
+GTK_SOURCE_GUTTER_LINES
+GTK_SOURCE_GUTTER_LINES_CLASS
+GTK_SOURCE_GUTTER_LINES_GET_CLASS
+GTK_SOURCE_TYPE_GUTTER_LINES
+gtk_source_gutter_lines_get_type
+
+
gutterrenderer
GtkSourceGutterRenderer
-GtkSourceGutterRendererState
GtkSourceGutterRendererAlignmentMode
-gtk_source_gutter_renderer_begin
-gtk_source_gutter_renderer_draw
-gtk_source_gutter_renderer_end
+gtk_source_gutter_renderer_get_buffer
gtk_source_gutter_renderer_get_view
-gtk_source_gutter_renderer_get_window_type
-gtk_source_gutter_renderer_get_visible
-gtk_source_gutter_renderer_set_visible
-gtk_source_gutter_renderer_get_size
-gtk_source_gutter_renderer_set_size
-gtk_source_gutter_renderer_get_padding
-gtk_source_gutter_renderer_set_padding
-gtk_source_gutter_renderer_get_alignment
-gtk_source_gutter_renderer_set_alignment
gtk_source_gutter_renderer_get_alignment_mode
gtk_source_gutter_renderer_set_alignment_mode
-gtk_source_gutter_renderer_get_background
-gtk_source_gutter_renderer_set_background
+gtk_source_gutter_renderer_get_xalign
+gtk_source_gutter_renderer_set_xalign
+gtk_source_gutter_renderer_get_xpad
+gtk_source_gutter_renderer_set_xpad
+gtk_source_gutter_renderer_get_yalign
+gtk_source_gutter_renderer_set_yalign
+gtk_source_gutter_renderer_get_ypad
+gtk_source_gutter_renderer_set_ypad
+gtk_source_gutter_renderer_align_cell
gtk_source_gutter_renderer_activate
gtk_source_gutter_renderer_query_activatable
-gtk_source_gutter_renderer_query_data
-gtk_source_gutter_renderer_query_tooltip
-gtk_source_gutter_renderer_queue_draw
GtkSourceGutterRendererClass
GTK_SOURCE_IS_GUTTER_RENDERER
@@ -408,7 +420,6 @@ GTK_SOURCE_GUTTER_RENDERER_CONST
GTK_SOURCE_GUTTER_RENDERER_CLASS
GTK_SOURCE_GUTTER_RENDERER_GET_CLASS
GTK_SOURCE_TYPE_GUTTER_RENDERER
-GtkSourceGutterRendererPrivate
gtk_source_gutter_renderer_get_type
GTK_SOURCE_TYPE_GUTTER_RENDERER_ALIGNMENT_MODE
gtk_source_gutter_renderer_alignment_mode_get_type
@@ -426,6 +437,9 @@ gtk_source_gutter_renderer_pixbuf_set_gicon
gtk_source_gutter_renderer_pixbuf_get_gicon
gtk_source_gutter_renderer_pixbuf_set_icon_name
gtk_source_gutter_renderer_pixbuf_get_icon_name
+gtk_source_gutter_renderer_pixbuf_get_paintable
+gtk_source_gutter_renderer_pixbuf_set_paintable
+gtk_source_gutter_renderer_pixbuf_overlay_paintable
GtkSourceGutterRendererPixbufClass
GTK_SOURCE_IS_GUTTER_RENDERER_PIXBUF
@@ -435,7 +449,6 @@ GTK_SOURCE_GUTTER_RENDERER_PIXBUF_CONST
GTK_SOURCE_GUTTER_RENDERER_PIXBUF_CLASS
GTK_SOURCE_GUTTER_RENDERER_PIXBUF_GET_CLASS
GTK_SOURCE_TYPE_GUTTER_RENDERER_PIXBUF
-GtkSourceGutterRendererPixbufPrivate
gtk_source_gutter_renderer_pixbuf_get_type
@@ -456,7 +469,6 @@ GTK_SOURCE_GUTTER_RENDERER_TEXT_CONST
GTK_SOURCE_GUTTER_RENDERER_TEXT_CLASS
GTK_SOURCE_GUTTER_RENDERER_TEXT_GET_CLASS
GTK_SOURCE_TYPE_GUTTER_RENDERER_TEXT
-GtkSourceGutterRendererTextPrivate
gtk_source_gutter_renderer_text_get_type
@@ -488,7 +500,6 @@ GTK_SOURCE_LANGUAGE
GTK_SOURCE_LANGUAGE_CLASS
GTK_SOURCE_LANGUAGE_GET_CLASS
GTK_SOURCE_TYPE_LANGUAGE
-GtkSourceLanguagePrivate
gtk_source_language_get_type
@@ -510,7 +521,6 @@ GTK_SOURCE_LANGUAGE_MANAGER
GTK_SOURCE_LANGUAGE_MANAGER_CLASS
GTK_SOURCE_LANGUAGE_MANAGER_GET_CLASS
GTK_SOURCE_TYPE_LANGUAGE_MANAGER
-GtkSourceLanguageManagerPrivate
gtk_source_language_manager_get_type
@@ -541,7 +551,6 @@ gtk_source_mark_next
gtk_source_mark_prev
GtkSourceMarkClass
-GtkSourceMarkPrivate
GTK_SOURCE_IS_MARK
GTK_SOURCE_IS_MARK_CLASS
GTK_SOURCE_MARK
@@ -574,7 +583,6 @@ GTK_SOURCE_MARK_ATTRIBUTES
GTK_SOURCE_MARK_ATTRIBUTES_CLASS
GTK_SOURCE_MARK_ATTRIBUTES_GET_CLASS
GTK_SOURCE_TYPE_MARK_ATTRIBUTES
-GtkSourceMarkAttributesPrivate
gtk_source_mark_attributes_get_type
@@ -626,7 +634,6 @@ gtk_source_print_compositor_get_type
GTK_SOURCE_PRINT_COMPOSITOR_CLASS
GTK_SOURCE_IS_PRINT_COMPOSITOR_CLASS
GTK_SOURCE_PRINT_COMPOSITOR_GET_CLASS
-GtkSourcePrintCompositorPrivate
GtkSourcePrintCompositorClass
@@ -683,7 +690,6 @@ GTK_SOURCE_SEARCH_CONTEXT_CLASS
GTK_SOURCE_SEARCH_CONTEXT_GET_CLASS
GTK_SOURCE_TYPE_SEARCH_CONTEXT
GtkSourceSearchContextClass
-GtkSourceSearchContextPrivate
gtk_source_search_context_get_type
@@ -709,10 +715,104 @@ GTK_SOURCE_SEARCH_SETTINGS_CLASS
GTK_SOURCE_SEARCH_SETTINGS_GET_CLASS
GTK_SOURCE_TYPE_SEARCH_SETTINGS
GtkSourceSearchSettingsClass
-GtkSourceSearchSettingsPrivate
gtk_source_search_settings_get_type
+
+snippet
+GtkSourceSnippet
+gtk_source_snippet_add_chunk
+gtk_source_snippet_copy
+gtk_source_snippet_get_context
+gtk_source_snippet_get_description
+gtk_source_snippet_get_focus_position
+gtk_source_snippet_get_language_id
+gtk_source_snippet_get_name
+gtk_source_snippet_get_n_chunks
+gtk_source_snippet_get_nth_chunk
+gtk_source_snippet_get_trigger
+gtk_source_snippet_new
+gtk_source_snippet_set_description
+gtk_source_snippet_set_language_id
+gtk_source_snippet_set_name
+gtk_source_snippet_set_trigger
+
+GTK_SOURCE_IS_SNIPPET
+GTK_SOURCE_IS_SNIPPET_CLASS
+GTK_SOURCE_SNIPPET
+GTK_SOURCE_SNIPPET_CLASS
+GTK_SOURCE_SNIPPET_GET_CLASS
+GTK_SOURCE_TYPE_SNIPPET
+GtkSourceSnippetClass
+
+
+
+snippetchunk
+GtkSourceSnippetChunk
+gtk_source_snippet_chunk_copy
+gtk_source_snippet_chunk_get_context
+gtk_source_snippet_chunk_get_focus_position
+gtk_source_snippet_chunk_get_spec
+gtk_source_snippet_chunk_get_text
+gtk_source_snippet_chunk_get_text_set
+gtk_source_snippet_chunk_new
+gtk_source_snippet_chunk_set_context
+gtk_source_snippet_chunk_set_focus_position
+gtk_source_snippet_chunk_set_spec
+gtk_source_snippet_chunk_set_text
+gtk_source_snippet_chunk_set_text_set
+
+GTK_SOURCE_IS_SNIPPET_CHUNK
+GTK_SOURCE_IS_SNIPPET_CHUNK_CLASS
+GTK_SOURCE_SNIPPET_CHUNK
+GTK_SOURCE_SNIPPET_CHUNK_CLASS
+GTK_SOURCE_SNIPPET_CHUNK_GET_CLASS
+GTK_SOURCE_TYPE_SNIPPET_CHUNK
+GtkSourceSnippetChunkClass
+
+
+
+snippetcontext
+GtkSourceSnippetContext
+gtk_source_snippet_context_clear_variables
+gtk_source_snippet_context_expand
+gtk_source_snippet_context_get_variable
+gtk_source_snippet_context_new
+gtk_source_snippet_context_set_constant
+gtk_source_snippet_context_set_line_prefix
+gtk_source_snippet_context_set_tab_width
+gtk_source_snippet_context_set_use_spaces
+gtk_source_snippet_context_set_variable
+
+GTK_SOURCE_IS_SNIPPET_CONTEXT
+GTK_SOURCE_IS_SNIPPET_CONTEXT_CLASS
+GTK_SOURCE_SNIPPET_CONTEXT
+GTK_SOURCE_SNIPPET_CONTEXT_CLASS
+GTK_SOURCE_SNIPPET_CONTEXT_GET_CLASS
+GTK_SOURCE_TYPE_SNIPPET_CONTEXT
+GtkSourceSnippetContextClass
+
+
+
+snippetmanager
+GtkSourceSnippetManager
+gtk_source_snippet_manager_get_default
+gtk_source_snippet_manager_get_search_path
+gtk_source_snippet_manager_get_snippet
+gtk_source_snippet_manager_list_groups
+gtk_source_snippet_manager_list_matching
+gtk_source_snippet_manager_set_search_path
+
+GTK_SOURCE_IS_SNIPPET_MANAGER
+GTK_SOURCE_IS_SNIPPET_MANAGER_CLASS
+GTK_SOURCE_SNIPPET_MANAGER
+GTK_SOURCE_SNIPPET_MANAGER_CLASS
+GTK_SOURCE_SNIPPET_MANAGER_GET_CLASS
+GTK_SOURCE_TYPE_SNIPPET_MANAGER
+GtkSourceSnippetManagerClass
+
+
+
spacedrawer
GtkSourceSpaceDrawer
@@ -734,7 +834,6 @@ GTK_SOURCE_SPACE_DRAWER_CLASS
GTK_SOURCE_SPACE_DRAWER_GET_CLASS
GTK_SOURCE_TYPE_SPACE_DRAWER
GtkSourceSpaceDrawerClass
-GtkSourceSpaceDrawerPrivate
gtk_source_space_drawer_get_type
GTK_SOURCE_TYPE_SPACE_LOCATION_FLAGS
GTK_SOURCE_TYPE_SPACE_TYPE_FLAGS
@@ -775,7 +874,6 @@ GTK_SOURCE_STYLE_SCHEME
GTK_SOURCE_STYLE_SCHEME_CLASS
GTK_SOURCE_STYLE_SCHEME_GET_CLASS
GTK_SOURCE_TYPE_STYLE_SCHEME
-GtkSourceStyleSchemePrivate
gtk_source_style_scheme_get_type
@@ -846,7 +944,6 @@ GTK_SOURCE_STYLE_SCHEME_MANAGER_CLASS
GTK_SOURCE_STYLE_SCHEME_MANAGER_GET_CLASS
GTK_SOURCE_TYPE_STYLE_SCHEME_MANAGER
gtk_source_style_scheme_manager_get_type
-GtkSourceStyleSchemeManagerPrivate
@@ -858,26 +955,6 @@ GTK_SOURCE_TYPE_TAG
GtkSourceTagClass
-
-undomanager
-GtkSourceUndoManager
-gtk_source_undo_manager_can_undo
-gtk_source_undo_manager_can_redo
-gtk_source_undo_manager_undo
-gtk_source_undo_manager_redo
-gtk_source_undo_manager_begin_not_undoable_action
-gtk_source_undo_manager_end_not_undoable_action
-gtk_source_undo_manager_can_undo_changed
-gtk_source_undo_manager_can_redo_changed
-
-GtkSourceUndoManagerIface
-GTK_SOURCE_UNDO_MANAGER
-GTK_SOURCE_IS_UNDO_MANAGER
-GTK_SOURCE_TYPE_UNDO_MANAGER
-GTK_SOURCE_UNDO_MANAGER_GET_INTERFACE
-gtk_source_undo_manager_get_type
-
-
utils
gtk_source_utils_unescape_search_text
@@ -910,6 +987,7 @@ GTK_SOURCE_VERSION_3_20
GTK_SOURCE_VERSION_3_22
GTK_SOURCE_VERSION_3_24
GTK_SOURCE_VERSION_4_0
+GTK_SOURCE_VERSION_5_0
GTK_SOURCE_VERSION_MIN_REQUIRED
GTK_SOURCE_VERSION_MAX_ALLOWED
@@ -956,6 +1034,9 @@ gtk_source_view_set_show_line_marks
gtk_source_view_get_show_line_marks
gtk_source_view_set_background_pattern
gtk_source_view_get_background_pattern
+gtk_source_view_get_enable_snippets
+gtk_source_view_set_enable_snippets
+gtk_source_view_push_snippet
GtkSourceViewClass
GTK_SOURCE_IS_VIEW
@@ -964,7 +1045,6 @@ GTK_SOURCE_VIEW
GTK_SOURCE_VIEW_CLASS
GTK_SOURCE_VIEW_GET_CLASS
GTK_SOURCE_TYPE_VIEW
-GtkSourceViewPrivate
gtk_source_view_get_type
GTK_SOURCE_TYPE_BACKGROUND_PATTERN_TYPE
gtk_source_background_pattern_type_get_type
diff --git a/docs/reference/gtksourceview-docs.xml.in b/docs/reference/gtksourceview-docs.xml.in
index c2f3ec7e913bbc9a1b2a318b18e7ac9deecb6e75..89e3bd498cd4e40e57ef8fe2bdd56a0fc2d77867 100644
--- a/docs/reference/gtksourceview-docs.xml.in
+++ b/docs/reference/gtksourceview-docs.xml.in
@@ -3,13 +3,11 @@
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
[
-
- %gtkdocentities;
]>
GtkSourceView @GSV_API_VERSION@ Reference Manual
- for GtkSourceView &package_version;
+ for GtkSourceView @PACKAGE_VERSION@
@@ -52,6 +50,7 @@
+
@@ -66,6 +65,7 @@
Gutter and Marks
+
@@ -84,13 +84,21 @@
+
+ Snippets
+
+
+
+
+
+
+
Misc
-
@@ -194,5 +202,9 @@
Index of new symbols in 4.0
+
+ Index of new symbols in 5.0
+
+
diff --git a/docs/reference/intro.xml.in b/docs/reference/intro.xml.in
index e861a0d61d1a3cdee6f876437656d81877a6ad37..5e936b11528129faa9277623399f5488a5cd0dff 100644
--- a/docs/reference/intro.xml.in
+++ b/docs/reference/intro.xml.in
@@ -3,8 +3,6 @@
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
[
-
- %gtkdocentities;
]>
diff --git a/docs/reference/lang-reference.xml.in b/docs/reference/lang-reference.xml.in
index e4e48a9d9380112b24e08d52599d86b4a8f815ee..1b52a9036de053364446ec70a06e3ba4bf3e2f07 100644
--- a/docs/reference/lang-reference.xml.in
+++ b/docs/reference/lang-reference.xml.in
@@ -3,8 +3,6 @@
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
[
-
- %gtkdocentities;
]>
diff --git a/docs/reference/lang-tutorial.xml b/docs/reference/lang-tutorial.xml
index ad9b58d0be60bdde971a1fffe91366ff36954a6b..0fb4bb157e4fa6ba15c91ff1cfff639c1eb1c892 100644
--- a/docs/reference/lang-tutorial.xml
+++ b/docs/reference/lang-tutorial.xml
@@ -3,8 +3,6 @@
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
[
-
- %gtkdocentities;
]>
diff --git a/docs/reference/meson.build b/docs/reference/meson.build
index 4f3a361907b662327513005d3e8d5c857592c263..8fe0ecf3eddc48009bf3673195099fc207395d58 100644
--- a/docs/reference/meson.build
+++ b/docs/reference/meson.build
@@ -8,32 +8,44 @@ reference_private_h = [
'config.h',
'gtksource.h',
'gtksourcebuffer-private.h',
- 'gtksourcebufferinputstream.h',
- 'gtksourcebufferinternal.h',
- 'gtksourcebufferoutputstream.h',
- 'gtksourcecompletioncontainer.h',
- 'gtksourcecompletionmodel.h',
+ 'gtksourcebufferinputstream-private.h',
+ 'gtksourcebufferinternal-private.h',
+ 'gtksourcebufferoutputstream-private.h',
'gtksourcecompletion-private.h',
- 'gtksourcecompletionwordsbuffer.h',
- 'gtksourcecompletionwordslibrary.h',
- 'gtksourcecompletionwordsproposal.h',
- 'gtksourcecompletionwordsutils.h',
- 'gtksourcecontextengine.h',
+ 'gtksourcecompletioncontainer-private.h',
+ 'gtksourcecompletioncontext-private.h',
+ 'gtksourcecompletioninfo-private.h',
+ 'gtksourcecompletionmodel-private.h',
+ 'gtksourcecompletionsnippetsproposal-private.h',
+ 'gtksourcecompletionwordsbuffer-private.h',
+ 'gtksourcecompletionwordslibrary-private.h',
+ 'gtksourcecompletionwordsproposal-private.h',
+ 'gtksourcecompletionwordsutils-private.h',
+ 'gtksourcecontextengine-private.h',
'gtksourceencoding-private.h',
- 'gtksourceengine.h',
+ 'gtksourceengine-private.h',
+ 'gtksourcefile-private.h',
'gtksourcegutter-private.h',
- 'gtksourcegutterrendererlines.h',
- 'gtksourcegutterrenderermarks.h',
'gtksourcegutterrenderer-private.h',
- 'gtksourceiter.h',
+ 'gtksourcegutterrendererlines-private.h',
+ 'gtksourcegutterrenderermarks-private.h',
+ 'gtksourceiter-private.h',
'gtksourcelanguage-private.h',
- 'gtksourcemarkssequence.h',
- 'gtksourcepixbufhelper.h',
- 'gtksourceregex.h',
+ 'gtksourcelanguagemanager-private.h',
+ 'gtksourcemarkssequence-private.h',
+ 'gtksourcepixbufhelper-private.h',
+ 'gtksourceregex-private.h',
+ 'gtksourcesearchcontext-private.h',
+ 'gtksourcesnippet-private.h',
+ 'gtksourcesnippetbundle-private.h',
+ 'gtksourcesnippetcontext-private.h',
+ 'gtksourcesnippetmanager-private.h',
'gtksourcestyle-private.h',
+ 'gtksourcestylescheme-private.h',
+ 'gtksourcestyleschememanager-private.h',
'gtksourcetypes-private.h',
- 'gtksourceundomanagerdefault.h',
'gtksourceutils-private.h',
+ 'quarkset-inline.h',
]
reference_content_files = files([
@@ -58,6 +70,12 @@ lang_reference_xml = configure_file(
configuration: config_h
)
+snippet_reference_xml = configure_file(
+ input: 'snippet-reference.xml.in',
+ output: 'snippet-reference.xml',
+ configuration: config_h
+)
+
style_reference_xml = configure_file(
input: 'style-reference.xml.in',
output: 'style-reference.xml',
@@ -93,7 +111,7 @@ reference_fixxref_args = [
gnome.gtkdoc('@0@.0'.format(package_string),
main_xml: join_paths(builddir, '@0@'.format(gtksourceview_docs_xml)),
- gobject_typesfile: 'gtksourceview-4.0.types',
+ gobject_typesfile: 'gtksourceview-5.0.types',
src_dir: reference_sources,
dependencies: gtksource_dep,
content_files: reference_content_files,
diff --git a/docs/reference/porting-guide-3-to-4.xml b/docs/reference/porting-guide-3-to-4.xml
index b540b586f4717dcf62688e35b52ea76da6e5c4dc..e7591bba1d843c3225072c5da30f7aa2fbb9fcd8 100644
--- a/docs/reference/porting-guide-3-to-4.xml
+++ b/docs/reference/porting-guide-3-to-4.xml
@@ -3,8 +3,6 @@
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
[
-
- %gtkdocentities;
]>
diff --git a/docs/reference/snippet-reference.xml.in b/docs/reference/snippet-reference.xml.in
new file mode 100644
index 0000000000000000000000000000000000000000..0d10c907498e6762e0c62ab707a4cb25d994ef4e
--- /dev/null
+++ b/docs/reference/snippet-reference.xml.in
@@ -0,0 +1,207 @@
+
+
+]>
+
+
+Snippet Definition Reference
+
+
+
+Snippet Definition Reference
+
+Reference to the GtkSourceView snippet definition file format
+
+
+
+
+Overview
+
+This is an overview of the Snippet Definition XML format, describing the
+meaning and usage of every element and attribute. The formal definition is
+stored in the RelaxNG schema file snippets.rng which
+should be installed on your system in the directory
+${PREFIX}/share/gtksourceview-@GSV_API_VERSION@/ (where
+${PREFIX} can be /usr/ or
+/usr/local/ if you have installed from source).
+
+
+
+
+The toplevel tag in a snippet file is <snippets>
.
+It has the following attributes:
+
+
+_group
+
+The group for the snippet. This is purely used to group snippets together
+in user-interfaces.
+
+
+
+
+
+
+Within the snippets tag is one or more <snippets>
elements.
+It has the following attributes:
+
+
+_name
+
+The name of the snippet. This may be displayed in the user interface such as
+in a snippet editor or completion providers. An attempt will be made to translate
+it by GtkSourceView.
+
+
+
+trigger
+
+The word trigger of the snippet. If the user types this word and hits Tab,
+the snippet will be inserted.
+
+
+
+_description
+
+The description of the snippet. This may be displayed in the user interface
+such as in a snippet editor or completion providers. An attempt will be made
+to translate it by GtkSourceView.
+
+
+
+
+
+
+Within the snippet tag is one or more <text>
elements.
+It has the following attributes:
+
+
+languages
+
+A semicolon separated list of GtkSourceView language identifiers for which this
+text should be used when inserting the snippet. Defining this on the
+<text>
tag allows a snippet to have multiple variants based
+on the programming language.
+
+
+
+CDATA
+
+Within the <text>
tag should be a single
+<![CDATA[]]>
tag containing the text for the snippet
+between the []. You do not need to use CDATA if the text does not have any
+embedded characters that will conflict with XML.
+
+
+
+
+
+
+Snippet Text Format
+
+GtkSourceView's snippet text format is largely based upon other snippet
+implementations that have gained popularity. Since there are so many, it likely
+differs in some small ways from what you may have used previously.
+
+
+
+Focus Positions
+Focus positions allow the user to move through chunks within the snippet
+that are meant to be edited by the user. Each subsequent "Tab" by the user will
+advance them to the next focus position until all have been exhausted.
+To set a focus position in your snippet, use a dollar sign followed by
+curly braces with the focus position number inside like ${1}
or
+${2}
. The user can also use Shift+Tab to move to a previous tab
+stop.
+The special $0
tab stop is used to place the cursor after
+all focus positions have been exhausted. If no focus position was provided, the
+cursor will be placed there automatically.
+You can also set a default value for a focus position by appending a colon
+and the initial value such as ${2:default_value}
. You can even
+reference other chunks such as ${3:$2_$1}
to join the contents of
+$2
, an underbar _
, and $1
.
+
+
+
+Variable Expansion
+When a snippet is expanded into the #GtkSourceView, chunks may reference
+a number of built-in or application provided variables. Applications may
+add additional variables with either gtk_source_snippet_context_set_constant()
+(for things that do not change) or gtk_source_snippet_context_set_variable()
+for values that may change.
+Snippet chunks can reference a variable anywhere by using a dollar sign
+followed by the variable name such as $variable
.
+You can also reference another focus position's value by usin their focus
+position number as the variable such as $1
.
+To post-process a variables value, enclose the variable in curly-brackets
+and use the pipe operator to denote the post-processing function such as
+${$1|capitalize}
.
+
+
+
+Predefined Variables
+A number of predefined variables are provided by GtkSourceView which can be extended by applications.
+
+$CURRENT_YEAR
The current 4-digit year
+$CURRENT_YEAR_SHORT
The last 2 digits of the current year
+$CURRENT_MONTH
The current month as a number from 01-12
+$CURRENT_MONTH_NAME
The full month name such as "August" in the current locale
+$CURRENT_MONTH_NAME_SHORT
The short month name such as "Aug" in the current locale
+$CURRENT_DATE
The current day of the month from 1-31
+$CURRENT_DAY_NAME
The current day such as "Friday" in the current locale
+$CURRENT_DAY_NAME_SHORT
The current day using the shortened name such as "Fri" in the current locale
+$CURRENT_HOUR
The current hour in 24-hour format
+$CURRENT_MINUTE
The current minute within the hour
+$CURRENT_SECOND
The current second within the minute
+$CURRENT_SECONDS_UNIX
The number of seconds since the UNIX epoch
+$NAME_SHORT
The users login user name (See g_get_user_name())
+$NAME
The users full name, if known (See g_get_full_name())
+$TM_CURRENT_LINE
The contents of the current line
+$TM_LINE_INDEX
The zero-index based line number
+$TM_LINE_NUMBER
The one-index based line number
+
+
+
+
+
+Post-Processing
+
+By appending a pipe to a variable within curly braces, you can post-process
+the variable. A number of built-in functions are available for processing.
+For example ${$1|stripsuffix|functify}
.
+
+
+lower
+upper
+captialize
+uncapitalize
+html
+camelize
+functify
+namespace
+class
+instance
+space
+stripsuffix
+slash_to_dots
+descend_path
+
+
+
+
+
+
+
+
+Default snippets
+
+The GtkSourceView team prefers to just keep a small number of snippets
+distributed with the library. To add a new snippet in GtkSourceView itself,
+the snippet must be very popular, and ideally a GtkSourceView-based application
+must use it by default.
+
+
+
+
diff --git a/docs/reference/style-reference.xml.in b/docs/reference/style-reference.xml.in
index dcf29765a917de43a743e60ba5b27e96d4fcb9cd..17c6cc67a9a5cca02d144478d094cfb643e530ee 100644
--- a/docs/reference/style-reference.xml.in
+++ b/docs/reference/style-reference.xml.in
@@ -3,8 +3,6 @@
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
[
-
- %gtkdocentities;
]>
diff --git a/gtksourceview/GtkSourceView.css b/gtksourceview/GtkSourceView.css
new file mode 100644
index 0000000000000000000000000000000000000000..67d18c51b27fab2a7e26b9201232a43eed13da05
--- /dev/null
+++ b/gtksourceview/GtkSourceView.css
@@ -0,0 +1,149 @@
+@define-color selected_border_color shade(@theme_selected_bg_color, 0.9);
+
+GtkSourceAssistant {
+ background-color: @theme_bg_color;
+ border-radius: 7px;
+ font: initial;
+ margin: 10px 10px 10px 10px;
+ box-shadow: 0 3px 5px 1px @wm_shadow,
+ 0 0 0 1px alpha(@wm_border, 1);
+ outline: 1px solid alpha(@wm_highlight, 0.25);
+ background: @theme_bg_color;
+}
+
+GtkSourceAssistant.completion {
+ background-color: @content_view_bg;
+ border: none;
+ min-width: 150px;
+}
+GtkSourceAssistant.completion scrollbar.vertical slider {
+ min-height: 10px;
+}
+GtkSourceAssistant.completion scrollbar.vertical {
+ border-top-right-radius: 5px;
+}
+GtkSourceAssistant.completion scrolledwindow:last-child scrollbar.vertical {
+ border-bottom-right-radius: 5px;
+}
+GtkSourceAssistant.completion list {
+ border-top-left-radius: 5px;
+ border-top-right-radius: 5px;
+ margin: 0px;
+}
+GtkSourceAssistant.completion list,
+GtkSourceAssistant.completion list row:not(:selected):not(:hover),
+GtkSourceAssistant.completion list row cell {
+ background: transparent;
+}
+GtkSourceAssistant.completion list row {
+ transition: none;
+ box-shadow: none;
+}
+GtkSourceAssistant.completion list row:first-child {
+ border-top-left-radius: 5px;
+ border-top-right-radius: 5px;
+}
+GtkSourceAssistant.completion scrolledwindow:last-child list row:last-child {
+ border-bottom-left-radius: 5px;
+ border-bottom-right-radius: 5px;
+}
+GtkSourceAssistant.completion list row cell.icon {
+ padding: 6px;
+ min-width: 16px;
+ min-height: 16px;
+}
+GtkSourceAssistant.completion list row cell.typed-text {
+ margin-left: 6px;
+ margin-right: 6px;
+ min-height: 28px;
+}
+GtkSourceAssistant.completion list row cell.after {
+ margin-right: 6px;
+}
+GtkSourceAssistant.completion list row cell.before {
+ opacity: 0.65;
+}
+GtkSourceAssistant.completion list row box.more button {
+ margin: 0px;
+ padding: 0px;
+}
+GtkSourceAssistant.completion list row box.more button image {
+ margin: 0px;
+ padding: 0px;
+}
+GtkSourceAssistant.completion box.details {
+ border-top: 1px solid @borders;
+ border-bottom-left-radius: 5px;
+ border-bottom-right-radius: 5px;
+ background-color: @theme_bg_color;
+ padding-left: 6px;
+ padding-right: 3px;
+}
+GtkSourceAssistant.completion box.details cell {
+ margin-left: 24px;
+ margin-bottom: 8px;
+}
+GtkSourceAssistant.completion box.details button.flat {
+ min-height: 8px;
+ margin: 3px 0px;
+ padding: 3px 6px;
+}
+
+GtkSourceAssistant.completion-info {
+ padding: 6px;
+}
+
+GtkSourceAssistant.informative label {
+ padding-right: 10px;
+}
+GtkSourceAssistant.informative image {
+ margin: 0 6px 0 0;
+ padding: 6px 10px 6px 9px;
+ min-width: 16px;
+ min-height: 16px;
+ border-top-left-radius: 7px;
+ border-bottom-left-radius: 7px;
+ background-color: @borders;
+}
+
+GtkSourceAssistant.informative.warning {
+ background-color: @warning_color;
+ color: @theme_selected_fg_color;
+ border-color: shade(@warning_color, 0.8);
+ text-shadow: 0 1px shade(@warning_color, 0.8);
+ -gtk-icon-shadow: 0 1px shade(@warning_color, 0.8);
+}
+GtkSourceAssistant.informative.warning image {
+ background-color: shade(@warning_color, 0.8);
+}
+
+GtkSourceAssistant.informative.error {
+ background-color: @error_color;
+ color: @theme_selected_fg_color;
+ border-color: shade(@error_color, 0.8);
+ text-shadow: 0 1px shade(@error_color, 0.8);
+ -gtk-icon-shadow: 0 1px shade(@error_color, 0.8);
+}
+GtkSourceAssistant.informative.error image {
+ background-color: shade(@error_color, 0.8);
+}
+
+GtkSourceAssistant.informative.other {
+ background-color: @success_color;
+ color: @theme_selected_fg_color;
+ border-color: shade(@success_color, 0.8);
+ text-shadow: 0 1px shade(@success_color, 0.8);
+ -gtk-icon-shadow: 0 1px shade(@success_color, 0.8);
+}
+GtkSourceAssistant.informative.other image {
+ background-color: shade(@success_color, 0.8);
+}
+
+GtkSourceAssistant.informative.question {
+ background-color: @theme_bg_color;
+ color: @theme_fg_color;
+ border-color: @borders;
+}
+GtkSourceAssistant.informative.question image {
+ background-color: @borders;
+}
diff --git a/gtksourceview/completion-providers/meson.build b/gtksourceview/completion-providers/meson.build
index f2613a3144fbbaa9410d11d962b05dc0a1414626..d2f81801a505b61762996e2894529f34a8fb25fc 100644
--- a/gtksourceview/completion-providers/meson.build
+++ b/gtksourceview/completion-providers/meson.build
@@ -1 +1,2 @@
+subdir('snippets')
subdir('words')
diff --git a/gtksourceview/completion-providers/snippets/gtksourcecompletionsnippets.c b/gtksourceview/completion-providers/snippets/gtksourcecompletionsnippets.c
new file mode 100644
index 0000000000000000000000000000000000000000..345d2a7380d58090dc61befa6336a5fffbd7398f
--- /dev/null
+++ b/gtksourceview/completion-providers/snippets/gtksourcecompletionsnippets.c
@@ -0,0 +1,463 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2020 Christian Hergert
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ */
+
+#include "config.h"
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "gtksourcecompletionsnippets.h"
+#include "gtksourcecompletionsnippetsproposal-private.h"
+
+/**
+ * SECTION:completionsnippets
+ * @title: GtkSourceCompletionSnippets
+ * @short_description: A GtkSourceCompletionProvider for the completion of snippets
+ *
+ * The #GtkSourceCompletionSnippets is an example of an implementation of
+ * the #GtkSourceCompletionProvider interface. The proposals are snippets
+ * registered with the #GtkSourceSnippetManager.
+ *
+ * Since: 5.0
+ */
+
+struct _GtkSourceSnippetResults
+{
+ GObject parent_instance;
+ GListModel *snippets;
+};
+
+static void list_model_iface_init (GListModelInterface *iface);
+
+#define GTK_SOURCE_TYPE_SNIPPET_RESULTS (gtk_source_snippet_results_get_type())
+G_DECLARE_FINAL_TYPE (GtkSourceSnippetResults, gtk_source_snippet_results, GTK_SOURCE, SNIPPET_RESULTS, GObject)
+G_DEFINE_TYPE_WITH_CODE (GtkSourceSnippetResults, gtk_source_snippet_results, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, list_model_iface_init))
+
+static GType
+gtk_source_snippet_results_get_item_type (GListModel *model)
+{
+ return GTK_SOURCE_TYPE_COMPLETION_PROPOSAL;
+}
+
+static guint
+gtk_source_snippet_results_get_n_items (GListModel *model)
+{
+ GtkSourceSnippetResults *self = (GtkSourceSnippetResults *)model;
+ return g_list_model_get_n_items (self->snippets);
+}
+
+static gpointer
+gtk_source_snippet_results_get_item (GListModel *model,
+ guint position)
+{
+ GtkSourceSnippetResults *self = (GtkSourceSnippetResults *)model;
+ GtkSourceSnippet *snippet = g_list_model_get_item (self->snippets, position);
+ return gtk_source_completion_snippets_proposal_new (snippet);
+}
+
+static void
+list_model_iface_init (GListModelInterface *iface)
+{
+ iface->get_item_type = gtk_source_snippet_results_get_item_type;
+ iface->get_n_items = gtk_source_snippet_results_get_n_items;
+ iface->get_item = gtk_source_snippet_results_get_item;
+}
+
+static GListModel *
+gtk_source_snippet_results_new (GListModel *base_model)
+{
+ GtkSourceSnippetResults *self = g_object_new (GTK_SOURCE_TYPE_SNIPPET_RESULTS, NULL);
+ self->snippets = g_object_ref (base_model);
+ return G_LIST_MODEL (self);
+}
+
+static void
+gtk_source_snippet_results_finalize (GObject *object)
+{
+ GtkSourceSnippetResults *self = (GtkSourceSnippetResults *)object;
+
+ g_clear_object (&self->snippets);
+
+ G_OBJECT_CLASS (gtk_source_snippet_results_parent_class)->finalize (object);
+}
+
+static void
+gtk_source_snippet_results_class_init (GtkSourceSnippetResultsClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gtk_source_snippet_results_finalize;
+}
+
+static void
+gtk_source_snippet_results_init (GtkSourceSnippetResults *self)
+{
+}
+
+typedef struct
+{
+ char *title;
+ int priority;
+ int minimum_word_size;
+} GtkSourceCompletionSnippetsPrivate;
+
+static void completion_provider_iface_init (GtkSourceCompletionProviderInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GtkSourceCompletionSnippets, gtk_source_completion_snippets, G_TYPE_OBJECT,
+ G_ADD_PRIVATE (GtkSourceCompletionSnippets)
+ G_IMPLEMENT_INTERFACE (GTK_SOURCE_TYPE_COMPLETION_PROVIDER,
+ completion_provider_iface_init))
+
+enum {
+ PROP_0,
+ PROP_TITLE,
+ PROP_PRIORITY,
+ N_PROPS
+};
+
+static GParamSpec *properties[N_PROPS];
+
+static GListModel *
+gtk_source_completion_snippets_populate (GtkSourceCompletionProvider *provider,
+ GtkSourceCompletionContext *context,
+ GError **error)
+{
+ GtkSourceCompletionSnippets *snippets = GTK_SOURCE_COMPLETION_SNIPPETS (provider);
+ GtkSourceCompletionSnippetsPrivate *priv = gtk_source_completion_snippets_get_instance_private (snippets);
+ GtkSourceCompletionActivation activation;
+ GtkSourceSnippetManager *manager;
+ GtkSourceLanguage *language;
+ GtkSourceBuffer *buffer;
+ const gchar *language_id = "";
+ GtkTextIter begin, end;
+ GListModel *matches;
+ GListModel *results = NULL;
+ gchar *word;
+
+ if (!gtk_source_completion_context_get_bounds (context, &begin, &end))
+ {
+ return NULL;
+ }
+
+ buffer = gtk_source_completion_context_get_buffer (context);
+ word = gtk_source_completion_context_get_word (context);
+ activation = gtk_source_completion_context_get_activation (context);
+ manager = gtk_source_snippet_manager_get_default ();
+ language = gtk_source_buffer_get_language (buffer);
+
+ if (word == NULL ||
+ (activation == GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE &&
+ g_utf8_strlen (word, -1) < (glong)priv->minimum_word_size))
+ {
+ g_free (word);
+ return NULL;
+ }
+
+ if (language != NULL)
+ {
+ language_id = gtk_source_language_get_id (language);
+ }
+
+ matches = gtk_source_snippet_manager_list_matching (manager, NULL, language_id, word);
+
+ if (matches != NULL)
+ {
+ results = gtk_source_snippet_results_new (matches);
+ }
+
+ g_clear_object (&matches);
+ g_free (word);
+
+ if (results == NULL)
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ "No results");
+ }
+
+ return results;
+}
+
+static gchar *
+gtk_source_completion_snippets_get_title (GtkSourceCompletionProvider *self)
+{
+ GtkSourceCompletionSnippets *snippets = GTK_SOURCE_COMPLETION_SNIPPETS (self);
+ GtkSourceCompletionSnippetsPrivate *priv = gtk_source_completion_snippets_get_instance_private (snippets);
+
+ return g_strdup (priv->title);
+}
+
+static gint
+gtk_source_completion_snippets_get_priority (GtkSourceCompletionProvider *provider,
+ GtkSourceCompletionContext *context)
+{
+ GtkSourceCompletionSnippets *snippets = GTK_SOURCE_COMPLETION_SNIPPETS (provider);
+ GtkSourceCompletionSnippetsPrivate *priv = gtk_source_completion_snippets_get_instance_private (snippets);
+
+ return priv->priority;
+}
+
+static void
+gtk_source_completion_snippets_activate (GtkSourceCompletionProvider *provider,
+ GtkSourceCompletionContext *context,
+ GtkSourceCompletionProposal *proposal)
+{
+ GtkSourceCompletionSnippetsProposal *p = (GtkSourceCompletionSnippetsProposal *)proposal;
+ GtkTextIter begin, end;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_SNIPPETS (provider));
+ g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (context));
+ g_assert (GTK_SOURCE_IS_COMPLETION_SNIPPETS_PROPOSAL (p));
+
+ if (gtk_source_completion_context_get_bounds (context, &begin, &end))
+ {
+ GtkTextBuffer *buffer = gtk_text_iter_get_buffer (&begin);
+ GtkSourceView *view = gtk_source_completion_context_get_view (context);
+ GtkSourceSnippet *snippet, *copy;
+
+ snippet = gtk_source_completion_snippets_proposal_get_snippet (GTK_SOURCE_COMPLETION_SNIPPETS_PROPOSAL (proposal));
+ copy = gtk_source_snippet_copy (snippet);
+
+ gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (buffer));
+ gtk_text_buffer_delete (GTK_TEXT_BUFFER (buffer), &begin, &end);
+ gtk_source_view_push_snippet (view, copy, &begin);
+ gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (buffer));
+
+ g_object_unref (copy);
+ }
+}
+
+static void
+gtk_source_completion_snippets_display (GtkSourceCompletionProvider *provider,
+ GtkSourceCompletionContext *context,
+ GtkSourceCompletionProposal *proposal,
+ GtkSourceCompletionCell *cell)
+{
+ GtkSourceCompletionSnippetsProposal *p = (GtkSourceCompletionSnippetsProposal *)proposal;
+ GtkSourceCompletionColumn column;
+ GtkSourceSnippet *snippet;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_SNIPPETS (provider));
+ g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (context));
+ g_assert (GTK_SOURCE_IS_COMPLETION_SNIPPETS_PROPOSAL (p));
+ g_assert (GTK_SOURCE_IS_COMPLETION_CELL (cell));
+
+ snippet = gtk_source_completion_snippets_proposal_get_snippet (p);
+ column = gtk_source_completion_cell_get_column (cell);
+
+ if (column == GTK_SOURCE_COMPLETION_COLUMN_TYPED_TEXT)
+ {
+ const char *trigger = gtk_source_snippet_get_trigger (snippet);
+ char *word = gtk_source_completion_context_get_word (context);
+ PangoAttrList *highlight = gtk_source_completion_fuzzy_highlight (trigger, word);
+
+ gtk_source_completion_cell_set_text_with_attributes (cell, trigger, highlight);
+
+ pango_attr_list_unref (highlight);
+ g_free (word);
+ }
+ else if (column == GTK_SOURCE_COMPLETION_COLUMN_ICON)
+ {
+ gtk_source_completion_cell_set_icon_name (cell,
+ "completion-snippet-symbolic");
+ }
+ else if (column == GTK_SOURCE_COMPLETION_COLUMN_COMMENT)
+ {
+ gtk_source_completion_cell_set_text (cell,
+ gtk_source_snippet_get_trigger (snippet));
+ }
+ else if (column == GTK_SOURCE_COMPLETION_COLUMN_DETAILS)
+ {
+ gtk_source_completion_cell_set_text (cell,
+ gtk_source_snippet_get_description (snippet));
+ }
+}
+
+static void
+gtk_source_completion_snippets_refilter (GtkSourceCompletionProvider *provider,
+ GtkSourceCompletionContext *context,
+ GListModel *model)
+{
+ GtkFilterListModel *filter_model;
+ GtkExpression *expression;
+ GtkStringFilter *filter;
+ gchar *word;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_PROVIDER (provider));
+ g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (context));
+ g_assert (G_IS_LIST_MODEL (model));
+
+ word = gtk_source_completion_context_get_word (context);
+
+ if (GTK_IS_FILTER_LIST_MODEL (model))
+ {
+ model = gtk_filter_list_model_get_model (GTK_FILTER_LIST_MODEL (model));
+ }
+
+ if (!word || !word[0])
+ {
+ gtk_source_completion_context_set_proposals_for_provider (context, provider, model);
+ g_free (word);
+ return;
+ }
+
+ expression = gtk_property_expression_new (GTK_SOURCE_TYPE_COMPLETION_SNIPPETS_PROPOSAL, NULL, "trigger");
+ filter = gtk_string_filter_new (g_steal_pointer (&expression));
+ gtk_string_filter_set_search (GTK_STRING_FILTER (filter), word);
+ filter_model = gtk_filter_list_model_new (g_object_ref (model),
+ GTK_FILTER (g_steal_pointer (&filter)));
+ gtk_filter_list_model_set_incremental (filter_model, TRUE);
+ gtk_source_completion_context_set_proposals_for_provider (context, provider, G_LIST_MODEL (filter_model));
+
+ g_clear_object (&filter_model);
+ g_free (word);
+}
+
+
+static void
+completion_provider_iface_init (GtkSourceCompletionProviderInterface *iface)
+{
+ iface->get_title = gtk_source_completion_snippets_get_title;
+ iface->get_priority = gtk_source_completion_snippets_get_priority;
+ iface->populate = gtk_source_completion_snippets_populate;
+ iface->activate = gtk_source_completion_snippets_activate;
+ iface->display = gtk_source_completion_snippets_display;
+ iface->refilter = gtk_source_completion_snippets_refilter;
+}
+
+static void
+gtk_source_completion_snippets_finalize (GObject *object)
+{
+ GtkSourceCompletionSnippets *provider = GTK_SOURCE_COMPLETION_SNIPPETS (object);
+ GtkSourceCompletionSnippetsPrivate *priv = gtk_source_completion_snippets_get_instance_private (provider);
+
+ g_clear_pointer (&priv->title, g_free);
+
+ G_OBJECT_CLASS (gtk_source_completion_snippets_parent_class)->finalize (object);
+}
+
+static void
+gtk_source_completion_snippets_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceCompletionSnippets *self = GTK_SOURCE_COMPLETION_SNIPPETS (object);
+ GtkSourceCompletionSnippetsPrivate *priv = gtk_source_completion_snippets_get_instance_private (self);
+
+ switch (prop_id)
+ {
+ case PROP_TITLE:
+ g_value_set_string (value, priv->title);
+ break;
+
+ case PROP_PRIORITY:
+ g_value_set_int (value, priv->priority);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_source_completion_snippets_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceCompletionSnippets *self = GTK_SOURCE_COMPLETION_SNIPPETS (object);
+ GtkSourceCompletionSnippetsPrivate *priv = gtk_source_completion_snippets_get_instance_private (self);
+
+ switch (prop_id)
+ {
+ case PROP_TITLE:
+ g_free (priv->title);
+ priv->title = g_value_dup_string (value);
+
+ if (priv->title == NULL)
+ {
+ priv->title = g_strdup (_("Snippets"));
+ }
+ break;
+
+ case PROP_PRIORITY:
+ priv->priority = g_value_get_int (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_source_completion_snippets_class_init (GtkSourceCompletionSnippetsClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gtk_source_completion_snippets_finalize;
+ object_class->get_property = gtk_source_completion_snippets_get_property;
+ object_class->set_property = gtk_source_completion_snippets_set_property;
+
+ properties[PROP_TITLE] =
+ g_param_spec_string ("title",
+ "Title",
+ "The provider title",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_PRIORITY] =
+ g_param_spec_int ("priority",
+ "Priority",
+ "Provider priority",
+ G_MININT,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+gtk_source_completion_snippets_init (GtkSourceCompletionSnippets *self)
+{
+ GtkSourceCompletionSnippetsPrivate *priv = gtk_source_completion_snippets_get_instance_private (self);
+
+ priv->minimum_word_size = 2;
+}
+
+GtkSourceCompletionSnippets *
+gtk_source_completion_snippets_new (void)
+{
+ return g_object_new (GTK_SOURCE_TYPE_COMPLETION_SNIPPETS, NULL);
+}
diff --git a/gtksourceview/completion-providers/snippets/gtksourcecompletionsnippets.h b/gtksourceview/completion-providers/snippets/gtksourcecompletionsnippets.h
new file mode 100644
index 0000000000000000000000000000000000000000..592da7a40314f6eef908e01588ba00eb9cb50dfc
--- /dev/null
+++ b/gtksourceview/completion-providers/snippets/gtksourcecompletionsnippets.h
@@ -0,0 +1,49 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2020 Christian Hergert
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ */
+
+#pragma once
+
+#if !defined (GTK_SOURCE_H_INSIDE) && !defined (GTK_SOURCE_COMPILATION)
+#error "Only can be included directly."
+#endif
+
+#include
+
+#include
+#include
+
+G_BEGIN_DECLS
+
+#define GTK_SOURCE_TYPE_COMPLETION_SNIPPETS (gtk_source_completion_snippets_get_type())
+
+GTK_SOURCE_AVAILABLE_IN_5_0
+G_DECLARE_DERIVABLE_TYPE (GtkSourceCompletionSnippets, gtk_source_completion_snippets, GTK_SOURCE, COMPLETION_SNIPPETS, GObject)
+
+struct _GtkSourceCompletionSnippetsClass
+{
+ GObjectClass parent_class;
+
+ /*< private >*/
+ gpointer _reserved[10];
+};
+
+GTK_SOURCE_AVAILABLE_IN_5_0
+GtkSourceCompletionSnippets *gtk_source_completion_snippets_new (void);
+
+G_END_DECLS
diff --git a/gtksourceview/completion-providers/snippets/gtksourcecompletionsnippetsproposal-private.h b/gtksourceview/completion-providers/snippets/gtksourcecompletionsnippetsproposal-private.h
new file mode 100644
index 0000000000000000000000000000000000000000..3469fbf51e6cb3553754865045ceda686c2c45dd
--- /dev/null
+++ b/gtksourceview/completion-providers/snippets/gtksourcecompletionsnippetsproposal-private.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2020 Christian Hergert
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ */
+
+#pragma once
+
+#include
+#include
+
+G_BEGIN_DECLS
+
+#define GTK_SOURCE_TYPE_COMPLETION_SNIPPETS_PROPOSAL (gtk_source_completion_snippets_proposal_get_type())
+
+G_DECLARE_FINAL_TYPE (GtkSourceCompletionSnippetsProposal, gtk_source_completion_snippets_proposal, GTK_SOURCE, COMPLETION_SNIPPETS_PROPOSAL, GObject)
+
+GtkSourceCompletionProposal *gtk_source_completion_snippets_proposal_new (GtkSourceSnippet *snippet);
+GtkSourceSnippet *gtk_source_completion_snippets_proposal_get_snippet (GtkSourceCompletionSnippetsProposal *self);
+
+G_END_DECLS
diff --git a/gtksourceview/completion-providers/snippets/gtksourcecompletionsnippetsproposal.c b/gtksourceview/completion-providers/snippets/gtksourcecompletionsnippetsproposal.c
new file mode 100644
index 0000000000000000000000000000000000000000..1bf69bbd8da136e7f4520497473a2baa4d5d1e9c
--- /dev/null
+++ b/gtksourceview/completion-providers/snippets/gtksourcecompletionsnippetsproposal.c
@@ -0,0 +1,157 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2020 Christian Hergert
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ */
+
+#include "config.h"
+
+#include
+
+#include "gtksourcecompletionsnippetsproposal-private.h"
+
+struct _GtkSourceCompletionSnippetsProposal
+{
+ GObject parent_instance;
+ GtkSourceSnippet *snippet;
+};
+
+G_DEFINE_TYPE_WITH_CODE (GtkSourceCompletionSnippetsProposal,
+ gtk_source_completion_snippets_proposal,
+ G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GTK_SOURCE_TYPE_COMPLETION_PROPOSAL, NULL))
+
+enum {
+ PROP_0,
+ PROP_SNIPPET,
+ PROP_TRIGGER,
+ N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+gtk_source_completion_snippets_proposal_finalize (GObject *object)
+{
+ GtkSourceCompletionSnippetsProposal *self = GTK_SOURCE_COMPLETION_SNIPPETS_PROPOSAL (object);
+
+ g_clear_object (&self->snippet);
+
+ G_OBJECT_CLASS (gtk_source_completion_snippets_proposal_parent_class)->finalize (object);
+}
+
+static void
+gtk_source_completion_snippets_proposal_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceCompletionSnippetsProposal *self = GTK_SOURCE_COMPLETION_SNIPPETS_PROPOSAL (object);
+
+ switch (prop_id)
+ {
+ case PROP_SNIPPET:
+ g_value_set_object (value, self->snippet);
+ break;
+
+ case PROP_TRIGGER:
+ if (self->snippet != NULL)
+ {
+ g_value_set_string (value, gtk_source_snippet_get_trigger (self->snippet));
+ }
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_source_completion_snippets_proposal_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceCompletionSnippetsProposal *self = GTK_SOURCE_COMPLETION_SNIPPETS_PROPOSAL (object);
+
+ switch (prop_id)
+ {
+ case PROP_SNIPPET:
+ self->snippet = g_value_dup_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_source_completion_snippets_proposal_class_init (GtkSourceCompletionSnippetsProposalClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gtk_source_completion_snippets_proposal_finalize;
+ object_class->get_property = gtk_source_completion_snippets_proposal_get_property;
+ object_class->set_property = gtk_source_completion_snippets_proposal_set_property;
+
+ properties [PROP_SNIPPET] =
+ g_param_spec_object ("snippet",
+ "snippet",
+ "The snippet to expand",
+ GTK_SOURCE_TYPE_SNIPPET,
+ (G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_TRIGGER] =
+ g_param_spec_string ("trigger",
+ "Trigger",
+ "The trigger for the snippet",
+ NULL,
+ (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+gtk_source_completion_snippets_proposal_init (GtkSourceCompletionSnippetsProposal *self)
+{
+}
+
+GtkSourceCompletionProposal *
+gtk_source_completion_snippets_proposal_new (GtkSourceSnippet *snippet)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_SNIPPET (snippet), NULL);
+
+ return g_object_new (GTK_SOURCE_TYPE_COMPLETION_SNIPPETS_PROPOSAL,
+ "snippet", snippet,
+ NULL);
+}
+
+/**
+ * gtk_source_completion_snippets_proposal_get_snippet:
+ *
+ * Returns: (transfer none): a #GtkSourceSnippet
+ */
+GtkSourceSnippet *
+gtk_source_completion_snippets_proposal_get_snippet (GtkSourceCompletionSnippetsProposal *self)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_SNIPPETS_PROPOSAL (self), NULL);
+
+ return self->snippet;
+}
diff --git a/gtksourceview/completion-providers/snippets/meson.build b/gtksourceview/completion-providers/snippets/meson.build
new file mode 100644
index 0000000000000000000000000000000000000000..f9d3199dc052bba456c4ee02248c3bd5f422d1c5
--- /dev/null
+++ b/gtksourceview/completion-providers/snippets/meson.build
@@ -0,0 +1,49 @@
+completionsnippets_c_args = [
+ '-DGTK_SOURCE_COMPILATION',
+ '-DG_LOG_DOMAIN="GtkSourceView"',
+]
+
+completionsnippets_public_h = [
+ 'gtksourcecompletionsnippets.h',
+]
+
+completionsnippets_sources = [
+ 'gtksourcecompletionsnippets.c',
+ 'gtksourcecompletionsnippetsproposal.c',
+]
+
+install_headers(
+ completionsnippets_public_h,
+ install_dir: join_paths(
+ pkgincludedir,
+ 'gtksourceview',
+ 'completion-providers',
+ 'snippets'
+ )
+)
+
+completionsnippets_lib = static_library(
+ package_string + 'completionsnippets',
+ completionsnippets_sources,
+ include_directories: rootdir,
+ dependencies: core_dep,
+ c_args: completionsnippets_c_args,
+ install: false,
+)
+
+gtksource_libs += [
+ completionsnippets_lib
+]
+
+completionsnippets_dep = declare_dependency(
+ link_with: completionsnippets_lib,
+ include_directories: rootdir,
+ dependencies: core_dep,
+)
+
+gtksource_deps += completionsnippets_dep
+
+extra_public_sources += files([
+ 'gtksourcecompletionsnippets.c',
+ 'gtksourcecompletionsnippets.h',
+])
diff --git a/gtksourceview/completion-providers/words/gtksourcecompletionwords.c b/gtksourceview/completion-providers/words/gtksourcecompletionwords.c
index a6a2e53b1d1e747ee7b3ebe87bfd7153e9e1987f..79d23b2b4c962aa1a5bf22447e21907992a9e9a3 100644
--- a/gtksourceview/completion-providers/words/gtksourcecompletionwords.c
+++ b/gtksourceview/completion-providers/words/gtksourcecompletionwords.c
@@ -29,39 +29,35 @@
* appearing in the registered #GtkTextBuffers.
*/
-#ifdef HAVE_CONFIG_H
-#include
-#endif
+#include "config.h"
-#include "gtksourcecompletionwords.h"
#include
#include
-#include "gtksourcecompletionwordslibrary.h"
-#include "gtksourcecompletionwordsbuffer.h"
-#include "gtksourcecompletionwordsutils.h"
+
#include "gtksourceview/gtksource.h"
#include "gtksourceview/gtksource-enumtypes.h"
+#include "gtksourcecompletionwords.h"
+#include "gtksourcecompletionwordslibrary-private.h"
+#include "gtksourcecompletionwordsbuffer-private.h"
+#include "gtksourcecompletionwordsutils-private.h"
+
#define BUFFER_KEY "GtkSourceCompletionWordsBufferKey"
enum
{
PROP_0,
- PROP_NAME,
- PROP_ICON,
+ PROP_TITLE,
PROP_PROPOSALS_BATCH_SIZE,
PROP_SCAN_BATCH_SIZE,
PROP_MINIMUM_WORD_SIZE,
- PROP_INTERACTIVE_DELAY,
PROP_PRIORITY,
- PROP_ACTIVATION,
N_PROPERTIES
};
-struct _GtkSourceCompletionWordsPrivate
+typedef struct
{
- gchar *name;
- GdkPixbuf *icon;
+ gchar *title;
gchar *word;
gint word_len;
@@ -70,8 +66,6 @@ struct _GtkSourceCompletionWordsPrivate
GtkSourceCompletionContext *context;
GSequenceIter *populate_iter;
- guint cancel_id;
-
guint proposals_batch_size;
guint scan_batch_size;
guint minimum_word_size;
@@ -79,10 +73,8 @@ struct _GtkSourceCompletionWordsPrivate
GtkSourceCompletionWordsLibrary *library;
GList *buffers;
- gint interactive_delay;
gint priority;
- GtkSourceCompletionActivation activation;
-};
+} GtkSourceCompletionWordsPrivate;
typedef struct
{
@@ -90,9 +82,19 @@ typedef struct
GtkSourceCompletionWordsBuffer *buffer;
} BufferBinding;
+typedef struct
+{
+ GtkSourceCompletionContext *context;
+ GtkSourceCompletionActivation activation;
+ GSequenceIter *populate_iter;
+ GListStore *ret;
+ char *word;
+ guint word_len;
+} Populate;
+
static GParamSpec *properties[N_PROPERTIES];
-static void gtk_source_completion_words_iface_init (GtkSourceCompletionProviderIface *iface);
+static void gtk_source_completion_words_iface_init (GtkSourceCompletionProviderInterface *iface);
G_DEFINE_TYPE_WITH_CODE (GtkSourceCompletionWords,
gtk_source_completion_words,
@@ -101,188 +103,168 @@ G_DEFINE_TYPE_WITH_CODE (GtkSourceCompletionWords,
G_IMPLEMENT_INTERFACE (GTK_SOURCE_TYPE_COMPLETION_PROVIDER,
gtk_source_completion_words_iface_init))
-static gchar *
-gtk_source_completion_words_get_name (GtkSourceCompletionProvider *self)
-{
- return g_strdup (GTK_SOURCE_COMPLETION_WORDS (self)->priv->name);
-}
-
-static GdkPixbuf *
-gtk_source_completion_words_get_icon (GtkSourceCompletionProvider *self)
+static void
+populate_free (Populate *p)
{
- return GTK_SOURCE_COMPLETION_WORDS (self)->priv->icon;
+ g_clear_object (&p->context);
+ g_clear_object (&p->ret);
+ g_clear_pointer (&p->word, g_free);
+ g_slice_free (Populate, p);
}
-static void
-population_finished (GtkSourceCompletionWords *words)
+static gchar *
+gtk_source_completion_words_get_title (GtkSourceCompletionProvider *self)
{
- if (words->priv->idle_id != 0)
- {
- g_source_remove (words->priv->idle_id);
- words->priv->idle_id = 0;
- }
-
- g_free (words->priv->word);
- words->priv->word = NULL;
-
- if (words->priv->context != NULL)
- {
- if (words->priv->cancel_id)
- {
- g_signal_handler_disconnect (words->priv->context,
- words->priv->cancel_id);
- words->priv->cancel_id = 0;
- }
+ GtkSourceCompletionWords *words = GTK_SOURCE_COMPLETION_WORDS (self);
+ GtkSourceCompletionWordsPrivate *priv = gtk_source_completion_words_get_instance_private (words);
- g_clear_object (&words->priv->context);
- }
+ return g_strdup (priv->title);
}
static gboolean
-add_in_idle (GtkSourceCompletionWords *words)
+add_in_idle (GTask *task)
{
+ GtkSourceCompletionWords *words = g_task_get_source_object (task);
+ GtkSourceCompletionWordsPrivate *priv = gtk_source_completion_words_get_instance_private (words);
+ Populate *p = g_task_get_task_data (task);
guint idx = 0;
- GList *ret = NULL;
- gboolean finished;
- if (words->priv->populate_iter == NULL)
+ if (g_task_return_error_if_cancelled (task))
+ {
+ g_clear_object (&task);
+ goto cleanup;
+ }
+
+ if (p->populate_iter == NULL)
{
- words->priv->populate_iter =
- gtk_source_completion_words_library_find_first (words->priv->library,
- words->priv->word,
- words->priv->word_len);
+ p->populate_iter = gtk_source_completion_words_library_find_first (priv->library,
+ p->word,
+ p->word_len);
}
- while (idx < words->priv->proposals_batch_size &&
- words->priv->populate_iter)
+ while (idx < priv->proposals_batch_size && p->populate_iter)
{
GtkSourceCompletionWordsProposal *proposal =
- gtk_source_completion_words_library_get_proposal (words->priv->populate_iter);
+ gtk_source_completion_words_library_get_proposal (p->populate_iter);
/* Only add non-exact matches */
- if (strcmp (gtk_source_completion_words_proposal_get_word (proposal),
- words->priv->word) != 0)
+ if (strcmp (gtk_source_completion_words_proposal_get_word (proposal), p->word) != 0)
{
- ret = g_list_prepend (ret, proposal);
+ g_list_store_append (p->ret, proposal);
}
- words->priv->populate_iter =
- gtk_source_completion_words_library_find_next (words->priv->populate_iter,
- words->priv->word,
- words->priv->word_len);
+ p->populate_iter = gtk_source_completion_words_library_find_next (p->populate_iter,
+ p->word,
+ p->word_len);
++idx;
}
- ret = g_list_reverse (ret);
- finished = words->priv->populate_iter == NULL;
-
- gtk_source_completion_context_add_proposals (words->priv->context,
- GTK_SOURCE_COMPLETION_PROVIDER (words),
- ret,
- finished);
-
- g_list_free (ret);
-
- if (finished)
+ if (p->populate_iter != NULL)
{
- gtk_source_completion_words_library_unlock (words->priv->library);
- population_finished (words);
+ return G_SOURCE_CONTINUE;
}
- return !finished;
-}
-
-static gchar *
-get_word_at_iter (GtkTextIter *iter)
-{
- GtkTextBuffer *buffer;
- GtkTextIter start_line;
- gchar *line_text;
- gchar *word;
-
- buffer = gtk_text_iter_get_buffer (iter);
- start_line = *iter;
- gtk_text_iter_set_line_offset (&start_line, 0);
-
- line_text = gtk_text_buffer_get_text (buffer, &start_line, iter, FALSE);
+cleanup:
+ g_task_return_pointer (task, g_steal_pointer (&p->ret), g_object_unref);
+ gtk_source_completion_words_library_unlock (priv->library);
+ g_clear_object (&task);
- word = _gtk_source_completion_words_utils_get_end_word (line_text);
-
- g_free (line_text);
- return word;
+ return G_SOURCE_REMOVE;
}
static void
-gtk_source_completion_words_populate (GtkSourceCompletionProvider *provider,
- GtkSourceCompletionContext *context)
+gtk_source_completion_words_populate_async (GtkSourceCompletionProvider *provider,
+ GtkSourceCompletionContext *context,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
GtkSourceCompletionWords *words = GTK_SOURCE_COMPLETION_WORDS (provider);
+ GtkSourceCompletionWordsPrivate *priv = gtk_source_completion_words_get_instance_private (words);
GtkSourceCompletionActivation activation;
- GtkTextIter iter;
+ Populate *populate;
+ GtkTextIter begin, end;
gchar *word;
+ GTask *task = NULL;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_WORDS (words));
+ g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (context));
+
+ task = g_task_new (words, cancellable, callback, user_data);
+ g_task_set_source_tag (task, gtk_source_completion_words_populate_async);
+ g_task_set_priority (task, priv->priority);
- if (!gtk_source_completion_context_get_iter (context, &iter))
+ if (!gtk_source_completion_context_get_bounds (context, &begin, &end))
{
- gtk_source_completion_context_add_proposals (context, provider, NULL, TRUE);
+ g_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ "No word to complete");
+ g_clear_object (&task);
return;
}
- g_free (words->priv->word);
- words->priv->word = NULL;
+ g_clear_pointer (&priv->word, g_free);
- word = get_word_at_iter (&iter);
+ word = gtk_text_iter_get_slice (&begin, &end);
+
+ g_assert (word != NULL);
activation = gtk_source_completion_context_get_activation (context);
- if (word == NULL ||
- (activation == GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE &&
- g_utf8_strlen (word, -1) < (glong)words->priv->minimum_word_size))
+ if (activation == GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE &&
+ g_utf8_strlen (word, -1) < (glong)priv->minimum_word_size)
{
g_free (word);
- gtk_source_completion_context_add_proposals (context, provider, NULL, TRUE);
+ g_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ "Word is too short to complete");
return;
}
- words->priv->cancel_id =
- g_signal_connect_swapped (context,
- "cancelled",
- G_CALLBACK (population_finished),
- provider);
+ populate = g_slice_new0 (Populate);
+ populate->context = g_object_ref (context);
+ populate->activation = activation;
+ populate->word = g_steal_pointer (&word);
+ populate->word_len = g_utf8_strlen (populate->word, -1);
+ populate->ret = g_list_store_new (GTK_SOURCE_TYPE_COMPLETION_PROPOSAL);
- words->priv->context = g_object_ref (context);
+ g_task_set_task_data (task, populate, (GDestroyNotify)populate_free);
- words->priv->word = word;
- words->priv->word_len = strlen (word);
+ gtk_source_completion_words_library_lock (priv->library);
/* Do first right now */
- if (add_in_idle (words))
+ if (add_in_idle (task))
{
- gtk_source_completion_words_library_lock (words->priv->library);
- words->priv->idle_id = gdk_threads_add_idle ((GSourceFunc)add_in_idle,
- words);
+ priv->idle_id = g_idle_add ((GSourceFunc)add_in_idle, task);
}
}
+static GListModel *
+gtk_source_completion_words_populate_finish (GtkSourceCompletionProvider *provider,
+ GAsyncResult *result,
+ GError **error)
+{
+ return g_task_propagate_pointer (G_TASK (result), error);
+}
+
static void
gtk_source_completion_words_dispose (GObject *object)
{
GtkSourceCompletionWords *provider = GTK_SOURCE_COMPLETION_WORDS (object);
+ GtkSourceCompletionWordsPrivate *priv = gtk_source_completion_words_get_instance_private (provider);
- population_finished (provider);
-
- while (provider->priv->buffers != NULL)
+ while (priv->buffers != NULL)
{
- BufferBinding *binding = provider->priv->buffers->data;
+ BufferBinding *binding = priv->buffers->data;
GtkTextBuffer *buffer = gtk_source_completion_words_buffer_get_buffer (binding->buffer);
gtk_source_completion_words_unregister (provider, buffer);
}
- g_free (provider->priv->name);
- provider->priv->name = NULL;
-
- g_clear_object (&provider->priv->icon);
- g_clear_object (&provider->priv->library);
+ g_clear_pointer (&priv->title, g_free);
+ g_clear_object (&priv->library);
G_OBJECT_CLASS (gtk_source_completion_words_parent_class)->dispose (object);
}
@@ -290,26 +272,28 @@ gtk_source_completion_words_dispose (GObject *object)
static void
update_buffers_batch_size (GtkSourceCompletionWords *words)
{
+ GtkSourceCompletionWordsPrivate *priv = gtk_source_completion_words_get_instance_private (words);
GList *item;
- for (item = words->priv->buffers; item != NULL; item = g_list_next (item))
+ for (item = priv->buffers; item != NULL; item = g_list_next (item))
{
BufferBinding *binding = item->data;
gtk_source_completion_words_buffer_set_scan_batch_size (binding->buffer,
- words->priv->scan_batch_size);
+ priv->scan_batch_size);
}
}
static void
update_buffers_minimum_word_size (GtkSourceCompletionWords *words)
{
+ GtkSourceCompletionWordsPrivate *priv = gtk_source_completion_words_get_instance_private (words);
GList *item;
- for (item = words->priv->buffers; item != NULL; item = g_list_next (item))
+ for (item = priv->buffers; item != NULL; item = g_list_next (item))
{
BufferBinding *binding = (BufferBinding *)item->data;
gtk_source_completion_words_buffer_set_minimum_word_size (binding->buffer,
- words->priv->minimum_word_size);
+ priv->minimum_word_size);
}
}
@@ -320,48 +304,36 @@ gtk_source_completion_words_set_property (GObject *object,
GParamSpec *pspec)
{
GtkSourceCompletionWords *self = GTK_SOURCE_COMPLETION_WORDS (object);
+ GtkSourceCompletionWordsPrivate *priv = gtk_source_completion_words_get_instance_private (self);
switch (prop_id)
{
- case PROP_NAME:
- g_free (self->priv->name);
- self->priv->name = g_value_dup_string (value);
+ case PROP_TITLE:
+ g_free (priv->title);
+ priv->title = g_value_dup_string (value);
- if (self->priv->name == NULL)
+ if (priv->title == NULL)
{
- self->priv->name = g_strdup (_("Document Words"));
+ priv->title = g_strdup (_("Document Words"));
}
break;
- case PROP_ICON:
- g_clear_object (&self->priv->icon);
- self->priv->icon = g_value_dup_object (value);
- break;
-
case PROP_PROPOSALS_BATCH_SIZE:
- self->priv->proposals_batch_size = g_value_get_uint (value);
+ priv->proposals_batch_size = g_value_get_uint (value);
break;
case PROP_SCAN_BATCH_SIZE:
- self->priv->scan_batch_size = g_value_get_uint (value);
+ priv->scan_batch_size = g_value_get_uint (value);
update_buffers_batch_size (self);
break;
case PROP_MINIMUM_WORD_SIZE:
- self->priv->minimum_word_size = g_value_get_uint (value);
+ priv->minimum_word_size = g_value_get_uint (value);
update_buffers_minimum_word_size (self);
break;
- case PROP_INTERACTIVE_DELAY:
- self->priv->interactive_delay = g_value_get_int (value);
- break;
-
case PROP_PRIORITY:
- self->priv->priority = g_value_get_int (value);
- break;
-
- case PROP_ACTIVATION:
- self->priv->activation = g_value_get_flags (value);
+ priv->priority = g_value_get_int (value);
break;
default:
@@ -377,39 +349,28 @@ gtk_source_completion_words_get_property (GObject *object,
GParamSpec *pspec)
{
GtkSourceCompletionWords *self = GTK_SOURCE_COMPLETION_WORDS (object);
+ GtkSourceCompletionWordsPrivate *priv = gtk_source_completion_words_get_instance_private (self);
switch (prop_id)
{
- case PROP_NAME:
- g_value_set_string (value, self->priv->name);
- break;
-
- case PROP_ICON:
- g_value_set_object (value, self->priv->icon);
+ case PROP_TITLE:
+ g_value_set_string (value, priv->title);
break;
case PROP_PROPOSALS_BATCH_SIZE:
- g_value_set_uint (value, self->priv->proposals_batch_size);
+ g_value_set_uint (value, priv->proposals_batch_size);
break;
case PROP_SCAN_BATCH_SIZE:
- g_value_set_uint (value, self->priv->scan_batch_size);
+ g_value_set_uint (value, priv->scan_batch_size);
break;
case PROP_MINIMUM_WORD_SIZE:
- g_value_set_uint (value, self->priv->minimum_word_size);
- break;
-
- case PROP_INTERACTIVE_DELAY:
- g_value_set_int (value, self->priv->interactive_delay);
+ g_value_set_uint (value, priv->minimum_word_size);
break;
case PROP_PRIORITY:
- g_value_set_int (value, self->priv->priority);
- break;
-
- case PROP_ACTIVATION:
- g_value_set_flags (value, self->priv->activation);
+ g_value_set_int (value, priv->priority);
break;
default:
@@ -427,20 +388,13 @@ gtk_source_completion_words_class_init (GtkSourceCompletionWordsClass *klass)
object_class->set_property = gtk_source_completion_words_set_property;
object_class->dispose = gtk_source_completion_words_dispose;
- properties[PROP_NAME] =
- g_param_spec_string ("name",
- "Name",
- "The provider name",
+ properties[PROP_TITLE] =
+ g_param_spec_string ("title",
+ "Title",
+ "The provider title",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
- properties[PROP_ICON] =
- g_param_spec_object ("icon",
- "Icon",
- "The provider icon",
- GDK_TYPE_PIXBUF,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
-
properties[PROP_PROPOSALS_BATCH_SIZE] =
g_param_spec_uint ("proposals-batch-size",
"Proposals Batch Size",
@@ -468,15 +422,6 @@ gtk_source_completion_words_class_init (GtkSourceCompletionWordsClass *klass)
2,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
- properties[PROP_INTERACTIVE_DELAY] =
- g_param_spec_int ("interactive-delay",
- "Interactive Delay",
- "The delay before initiating interactive completion",
- -1,
- G_MAXINT,
- 50,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
-
properties[PROP_PRIORITY] =
g_param_spec_int ("priority",
"Priority",
@@ -486,109 +431,150 @@ gtk_source_completion_words_class_init (GtkSourceCompletionWordsClass *klass)
0,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
- /**
- * GtkSourceCompletionWords:activation:
- *
- * The type of activation.
- *
- * Since: 3.10
- */
- properties[PROP_ACTIVATION] =
- g_param_spec_flags ("activation",
- "Activation",
- "The type of activation",
- GTK_SOURCE_TYPE_COMPLETION_ACTIVATION,
- GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE |
- GTK_SOURCE_COMPLETION_ACTIVATION_USER_REQUESTED,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
-
g_object_class_install_properties (object_class, N_PROPERTIES, properties);
}
-static gboolean
-gtk_source_completion_words_get_start_iter (GtkSourceCompletionProvider *provider,
- GtkSourceCompletionContext *context,
- GtkSourceCompletionProposal *proposal,
- GtkTextIter *iter)
+static gint
+gtk_source_completion_words_get_priority (GtkSourceCompletionProvider *provider,
+ GtkSourceCompletionContext *context)
{
- gchar *word;
- glong nb_chars;
+ GtkSourceCompletionWords *words = GTK_SOURCE_COMPLETION_WORDS (provider);
+ GtkSourceCompletionWordsPrivate *priv = gtk_source_completion_words_get_instance_private (words);
- if (!gtk_source_completion_context_get_iter (context, iter))
- {
- return FALSE;
- }
+ return priv->priority;
+}
- word = get_word_at_iter (iter);
- g_return_val_if_fail (word != NULL, FALSE);
+static void
+gtk_source_completion_words_display (GtkSourceCompletionProvider *provider,
+ GtkSourceCompletionContext *context,
+ GtkSourceCompletionProposal *proposal,
+ GtkSourceCompletionCell *cell)
+{
+ GtkSourceCompletionWordsProposal *p = (GtkSourceCompletionWordsProposal *)proposal;
+ GtkSourceCompletionColumn column;
- nb_chars = g_utf8_strlen (word, -1);
- gtk_text_iter_backward_chars (iter, nb_chars);
+ g_assert (GTK_SOURCE_IS_COMPLETION_WORDS (provider));
+ g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (context));
+ g_assert (GTK_SOURCE_IS_COMPLETION_WORDS_PROPOSAL (p));
+ g_assert (GTK_SOURCE_IS_COMPLETION_CELL (cell));
- g_free (word);
- return TRUE;
-}
+ column = gtk_source_completion_cell_get_column (cell);
-static gint
-gtk_source_completion_words_get_interactive_delay (GtkSourceCompletionProvider *provider)
-{
- return GTK_SOURCE_COMPLETION_WORDS (provider)->priv->interactive_delay;
+ if (column == GTK_SOURCE_COMPLETION_COLUMN_TYPED_TEXT)
+ {
+ const char *word = gtk_source_completion_words_proposal_get_word (p);
+ gtk_source_completion_cell_set_text (cell, word);
+ }
+ else if (column == GTK_SOURCE_COMPLETION_COLUMN_ICON)
+ {
+ gtk_source_completion_cell_set_icon_name (cell, "completion-word-symbolic");
+ }
}
-static gint
-gtk_source_completion_words_get_priority (GtkSourceCompletionProvider *provider)
+static void
+gtk_source_completion_words_activate (GtkSourceCompletionProvider *provider,
+ GtkSourceCompletionContext *context,
+ GtkSourceCompletionProposal *proposal)
{
- return GTK_SOURCE_COMPLETION_WORDS (provider)->priv->priority;
+ GtkSourceCompletionWordsProposal *p = (GtkSourceCompletionWordsProposal *)proposal;
+ GtkTextIter begin, end;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_WORDS (provider));
+ g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (context));
+ g_assert (GTK_SOURCE_IS_COMPLETION_WORDS_PROPOSAL (p));
+
+ if (gtk_source_completion_context_get_bounds (context, &begin, &end))
+ {
+ GtkTextBuffer *buffer = gtk_text_iter_get_buffer (&begin);
+ const char *word = gtk_source_completion_words_proposal_get_word (p);
+
+ gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (buffer));
+ gtk_text_buffer_delete (GTK_TEXT_BUFFER (buffer), &begin, &end);
+ gtk_text_buffer_insert (GTK_TEXT_BUFFER (buffer), &begin, word, -1);
+ gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (buffer));
+ }
}
-static GtkSourceCompletionActivation
-gtk_source_completion_words_get_activation (GtkSourceCompletionProvider *provider)
+static void
+gtk_source_completion_words_refilter (GtkSourceCompletionProvider *provider,
+ GtkSourceCompletionContext *context,
+ GListModel *model)
{
- return GTK_SOURCE_COMPLETION_WORDS (provider)->priv->activation;
+ GtkFilterListModel *filter_model;
+ GtkExpression *expression;
+ GtkStringFilter *filter;
+ gchar *word;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_PROVIDER (provider));
+ g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (context));
+ g_assert (G_IS_LIST_MODEL (model));
+
+ word = gtk_source_completion_context_get_word (context);
+
+ if (GTK_IS_FILTER_LIST_MODEL (model))
+ {
+ model = gtk_filter_list_model_get_model (GTK_FILTER_LIST_MODEL (model));
+ }
+
+ if (!word || !word[0])
+ {
+ gtk_source_completion_context_set_proposals_for_provider (context, provider, model);
+ g_free (word);
+ return;
+ }
+
+ expression = gtk_property_expression_new (GTK_SOURCE_TYPE_COMPLETION_WORDS_PROPOSAL, NULL, "word");
+ filter = gtk_string_filter_new (g_steal_pointer (&expression));
+ gtk_string_filter_set_search (GTK_STRING_FILTER (filter), word);
+ filter_model = gtk_filter_list_model_new (g_object_ref (model),
+ GTK_FILTER (g_steal_pointer (&filter)));
+ gtk_filter_list_model_set_incremental (filter_model, TRUE);
+ gtk_source_completion_context_set_proposals_for_provider (context, provider, G_LIST_MODEL (filter_model));
+
+ g_clear_object (&filter_model);
+ g_free (word);
}
static void
-gtk_source_completion_words_iface_init (GtkSourceCompletionProviderIface *iface)
+gtk_source_completion_words_iface_init (GtkSourceCompletionProviderInterface *iface)
{
- iface->get_name = gtk_source_completion_words_get_name;
- iface->get_icon = gtk_source_completion_words_get_icon;
- iface->populate = gtk_source_completion_words_populate;
- iface->get_start_iter = gtk_source_completion_words_get_start_iter;
- iface->get_interactive_delay = gtk_source_completion_words_get_interactive_delay;
+ iface->get_title = gtk_source_completion_words_get_title;
+ iface->populate_async = gtk_source_completion_words_populate_async;
+ iface->populate_finish = gtk_source_completion_words_populate_finish;
iface->get_priority = gtk_source_completion_words_get_priority;
- iface->get_activation = gtk_source_completion_words_get_activation;
+ iface->display = gtk_source_completion_words_display;
+ iface->activate = gtk_source_completion_words_activate;
+ iface->refilter = gtk_source_completion_words_refilter;
}
static void
gtk_source_completion_words_init (GtkSourceCompletionWords *self)
{
- self->priv = gtk_source_completion_words_get_instance_private (self);
+ GtkSourceCompletionWordsPrivate *priv = gtk_source_completion_words_get_instance_private (self);
- self->priv->library = gtk_source_completion_words_library_new ();
+ priv->library = gtk_source_completion_words_library_new ();
}
/**
* gtk_source_completion_words_new:
- * @name: (nullable): The name for the provider, or %NULL.
- * @icon: (nullable): A specific icon for the provider, or %NULL.
+ * @title: (nullable): The title for the provider, or %NULL.
*
* Returns: a new #GtkSourceCompletionWords provider
*/
GtkSourceCompletionWords *
-gtk_source_completion_words_new (const gchar *name,
- GdkPixbuf *icon)
+gtk_source_completion_words_new (const gchar *title)
{
return g_object_new (GTK_SOURCE_TYPE_COMPLETION_WORDS,
- "name", name,
- "icon", icon,
+ "title", title,
NULL);
}
static void
buffer_destroyed (BufferBinding *binding)
{
- binding->words->priv->buffers = g_list_remove (binding->words->priv->buffers,
- binding);
+ GtkSourceCompletionWordsPrivate *priv = gtk_source_completion_words_get_instance_private (binding->words);
+
+ priv->buffers = g_list_remove (priv->buffers, binding);
g_object_unref (binding->buffer);
g_slice_free (BufferBinding, binding);
}
@@ -604,6 +590,7 @@ void
gtk_source_completion_words_register (GtkSourceCompletionWords *words,
GtkTextBuffer *buffer)
{
+ GtkSourceCompletionWordsPrivate *priv = gtk_source_completion_words_get_instance_private (words);
GtkSourceCompletionWordsBuffer *buf;
BufferBinding *binding;
@@ -617,14 +604,14 @@ gtk_source_completion_words_register (GtkSourceCompletionWords *words,
return;
}
- buf = gtk_source_completion_words_buffer_new (words->priv->library,
+ buf = gtk_source_completion_words_buffer_new (priv->library,
buffer);
gtk_source_completion_words_buffer_set_scan_batch_size (buf,
- words->priv->scan_batch_size);
+ priv->scan_batch_size);
gtk_source_completion_words_buffer_set_minimum_word_size (buf,
- words->priv->minimum_word_size);
+ priv->minimum_word_size);
binding = g_slice_new (BufferBinding);
binding->words = words;
@@ -635,8 +622,7 @@ gtk_source_completion_words_register (GtkSourceCompletionWords *words,
binding,
(GDestroyNotify)buffer_destroyed);
- words->priv->buffers = g_list_prepend (words->priv->buffers,
- binding);
+ priv->buffers = g_list_prepend (priv->buffers, binding);
}
/**
diff --git a/gtksourceview/completion-providers/words/gtksourcecompletionwords.h b/gtksourceview/completion-providers/words/gtksourcecompletionwords.h
index 499cd1e306a3ae245fcc5694601d043d3e4689f9..5c01c36e65bb6b6fa1f4a584f5be5a7bfcfc55d1 100644
--- a/gtksourceview/completion-providers/words/gtksourcecompletionwords.h
+++ b/gtksourceview/completion-providers/words/gtksourcecompletionwords.h
@@ -18,55 +18,38 @@
* along with this library; if not, see .
*/
-#ifndef GTK_SOURCE_COMPLETION_WORDS_H
-#define GTK_SOURCE_COMPLETION_WORDS_H
+#pragma once
#if !defined (GTK_SOURCE_H_INSIDE) && !defined (GTK_SOURCE_COMPILATION)
#error "Only can be included directly."
#endif
-#include
#include
-G_BEGIN_DECLS
-
-#define GTK_SOURCE_TYPE_COMPLETION_WORDS (gtk_source_completion_words_get_type ())
-#define GTK_SOURCE_COMPLETION_WORDS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_SOURCE_TYPE_COMPLETION_WORDS, GtkSourceCompletionWords))
-#define GTK_SOURCE_COMPLETION_WORDS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_SOURCE_TYPE_COMPLETION_WORDS, GtkSourceCompletionWordsClass))
-#define GTK_SOURCE_IS_COMPLETION_WORDS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_SOURCE_TYPE_COMPLETION_WORDS))
-#define GTK_SOURCE_IS_COMPLETION_WORDS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_SOURCE_TYPE_COMPLETION_WORDS))
-#define GTK_SOURCE_COMPLETION_WORDS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_SOURCE_TYPE_COMPLETION_WORDS, GtkSourceCompletionWordsClass))
-
-typedef struct _GtkSourceCompletionWords GtkSourceCompletionWords;
-typedef struct _GtkSourceCompletionWordsClass GtkSourceCompletionWordsClass;
-typedef struct _GtkSourceCompletionWordsPrivate GtkSourceCompletionWordsPrivate;
+#include "../../gtksourcecompletionprovider.h"
-struct _GtkSourceCompletionWords {
- GObject parent;
+G_BEGIN_DECLS
- GtkSourceCompletionWordsPrivate *priv;
-};
+#define GTK_SOURCE_TYPE_COMPLETION_WORDS (gtk_source_completion_words_get_type())
-struct _GtkSourceCompletionWordsClass {
+struct _GtkSourceCompletionWordsClass
+{
GObjectClass parent_class;
+
+ /*< private >*/
+ gpointer _reserved[10];
};
GTK_SOURCE_AVAILABLE_IN_ALL
-GType gtk_source_completion_words_get_type (void) G_GNUC_CONST;
+G_DECLARE_DERIVABLE_TYPE (GtkSourceCompletionWords, gtk_source_completion_words, GTK_SOURCE, COMPLETION_WORDS, GObject)
GTK_SOURCE_AVAILABLE_IN_ALL
-GtkSourceCompletionWords *
- gtk_source_completion_words_new (const gchar *name,
- GdkPixbuf *icon);
-
+GtkSourceCompletionWords *gtk_source_completion_words_new (const gchar *title);
GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_completion_words_register (GtkSourceCompletionWords *words,
- GtkTextBuffer *buffer);
-
+void gtk_source_completion_words_register (GtkSourceCompletionWords *words,
+ GtkTextBuffer *buffer);
GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_completion_words_unregister (GtkSourceCompletionWords *words,
- GtkTextBuffer *buffer);
+void gtk_source_completion_words_unregister (GtkSourceCompletionWords *words,
+ GtkTextBuffer *buffer);
G_END_DECLS
-
-#endif /* GTK_SOURCE_COMPLETION_WORDS_H */
diff --git a/gtksourceview/completion-providers/words/gtksourcecompletionwordsbuffer-private.h b/gtksourceview/completion-providers/words/gtksourcecompletionwordsbuffer-private.h
new file mode 100644
index 0000000000000000000000000000000000000000..770bfe16fc60e06f1680d75ca2062715725ab937
--- /dev/null
+++ b/gtksourceview/completion-providers/words/gtksourcecompletionwordsbuffer-private.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ *
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2009 - Jesse van den Kieboom
+ *
+ * gtksourceview is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * gtksourceview 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ */
+
+#pragma once
+
+#include
+
+#include "gtksourcecompletionwordslibrary-private.h"
+
+G_BEGIN_DECLS
+
+#define GTK_SOURCE_TYPE_COMPLETION_WORDS_BUFFER (gtk_source_completion_words_buffer_get_type())
+
+G_GNUC_INTERNAL
+G_DECLARE_FINAL_TYPE (GtkSourceCompletionWordsBuffer, gtk_source_completion_words_buffer, GTK_SOURCE, COMPLETION_WORDS_BUFFER, GObject)
+
+G_GNUC_INTERNAL
+GtkSourceCompletionWordsBuffer *gtk_source_completion_words_buffer_new (GtkSourceCompletionWordsLibrary *library,
+ GtkTextBuffer *buffer);
+G_GNUC_INTERNAL
+GtkTextBuffer *gtk_source_completion_words_buffer_get_buffer (GtkSourceCompletionWordsBuffer *buffer);
+G_GNUC_INTERNAL
+void gtk_source_completion_words_buffer_set_scan_batch_size (GtkSourceCompletionWordsBuffer *buffer,
+ guint size);
+G_GNUC_INTERNAL
+void gtk_source_completion_words_buffer_set_minimum_word_size (GtkSourceCompletionWordsBuffer *buffer,
+ guint size);
+
+G_END_DECLS
diff --git a/gtksourceview/completion-providers/words/gtksourcecompletionwordsbuffer.c b/gtksourceview/completion-providers/words/gtksourcecompletionwordsbuffer.c
index 693daa2c9a72fe8204468495aed1bc18f04b54be..f9a5824d332bb42aa49f892259926c5fcbf22072 100644
--- a/gtksourceview/completion-providers/words/gtksourcecompletionwordsbuffer.c
+++ b/gtksourceview/completion-providers/words/gtksourcecompletionwordsbuffer.c
@@ -19,12 +19,10 @@
* along with this library; if not, see .
*/
-#ifdef HAVE_CONFIG_H
-#include
-#endif
+#include "config.h"
-#include "gtksourcecompletionwordsbuffer.h"
-#include "gtksourcecompletionwordsutils.h"
+#include "gtksourcecompletionwordsbuffer-private.h"
+#include "gtksourcecompletionwordsutils-private.h"
#include "gtksourceview/gtksourceregion.h"
/* Timeout in seconds */
@@ -39,8 +37,10 @@ typedef struct
guint use_count;
} ProposalCache;
-struct _GtkSourceCompletionWordsBufferPrivate
+struct _GtkSourceCompletionWordsBuffer
{
+ GObject parent_instance;
+
GtkSourceCompletionWordsLibrary *library;
GtkTextBuffer *buffer;
@@ -54,7 +54,7 @@ struct _GtkSourceCompletionWordsBufferPrivate
GHashTable *words;
};
-G_DEFINE_TYPE_WITH_PRIVATE (GtkSourceCompletionWordsBuffer, gtk_source_completion_words_buffer, G_TYPE_OBJECT)
+G_DEFINE_TYPE (GtkSourceCompletionWordsBuffer, gtk_source_completion_words_buffer, G_TYPE_OBJECT)
static ProposalCache *
proposal_cache_new (GtkSourceCompletionWordsProposal *proposal)
@@ -82,7 +82,7 @@ remove_proposal_cache (const gchar *key,
for (i = 0; i < cache->use_count; ++i)
{
- gtk_source_completion_words_library_remove_word (buffer->priv->library,
+ gtk_source_completion_words_library_remove_word (buffer->library,
cache->proposal);
}
}
@@ -90,11 +90,11 @@ remove_proposal_cache (const gchar *key,
static void
remove_all_words (GtkSourceCompletionWordsBuffer *buffer)
{
- g_hash_table_foreach (buffer->priv->words,
+ g_hash_table_foreach (buffer->words,
(GHFunc)remove_proposal_cache,
buffer);
- g_hash_table_remove_all (buffer->priv->words);
+ g_hash_table_remove_all (buffer->words);
}
static void
@@ -103,29 +103,29 @@ gtk_source_completion_words_buffer_dispose (GObject *object)
GtkSourceCompletionWordsBuffer *buffer =
GTK_SOURCE_COMPLETION_WORDS_BUFFER (object);
- if (buffer->priv->words != NULL)
+ if (buffer->words != NULL)
{
remove_all_words (buffer);
- g_hash_table_destroy (buffer->priv->words);
- buffer->priv->words = NULL;
+ g_hash_table_destroy (buffer->words);
+ buffer->words = NULL;
}
- if (buffer->priv->batch_scan_id != 0)
+ if (buffer->batch_scan_id != 0)
{
- g_source_remove (buffer->priv->batch_scan_id);
- buffer->priv->batch_scan_id = 0;
+ g_source_remove (buffer->batch_scan_id);
+ buffer->batch_scan_id = 0;
}
- if (buffer->priv->initiate_scan_id != 0)
+ if (buffer->initiate_scan_id != 0)
{
- g_source_remove (buffer->priv->initiate_scan_id);
- buffer->priv->initiate_scan_id = 0;
+ g_source_remove (buffer->initiate_scan_id);
+ buffer->initiate_scan_id = 0;
}
- g_clear_object (&buffer->priv->scan_region);
- g_clear_object (&buffer->priv->buffer);
- g_clear_object (&buffer->priv->library);
+ g_clear_object (&buffer->scan_region);
+ g_clear_object (&buffer->buffer);
+ g_clear_object (&buffer->library);
G_OBJECT_CLASS (gtk_source_completion_words_buffer_parent_class)->dispose (object);
}
@@ -141,15 +141,13 @@ gtk_source_completion_words_buffer_class_init (GtkSourceCompletionWordsBufferCla
static void
gtk_source_completion_words_buffer_init (GtkSourceCompletionWordsBuffer *self)
{
- self->priv = gtk_source_completion_words_buffer_get_instance_private (self);
-
- self->priv->scan_batch_size = 20;
- self->priv->minimum_word_size = 3;
+ self->scan_batch_size = 20;
+ self->minimum_word_size = 3;
- self->priv->words = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- (GDestroyNotify)g_free,
- (GDestroyNotify)proposal_cache_free);
+ self->words = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ (GDestroyNotify)g_free,
+ (GDestroyNotify)proposal_cache_free);
}
/* Starts the scanning at @start, and ends at the line end or @end. So at most
@@ -185,12 +183,12 @@ scan_line (GtkSourceCompletionWordsBuffer *buffer,
_gtk_source_completion_words_utils_check_scan_region (start, &text_end);
- text = gtk_text_buffer_get_text (buffer->priv->buffer,
+ text = gtk_text_buffer_get_text (buffer->buffer,
start,
&text_end,
FALSE);
- words = _gtk_source_completion_words_utils_scan_words (text, buffer->priv->minimum_word_size);
+ words = _gtk_source_completion_words_utils_scan_words (text, buffer->minimum_word_size);
g_free (text);
return words;
@@ -200,7 +198,7 @@ static void
remove_word (GtkSourceCompletionWordsBuffer *buffer,
const gchar *word)
{
- ProposalCache *cache = g_hash_table_lookup (buffer->priv->words, word);
+ ProposalCache *cache = g_hash_table_lookup (buffer->words, word);
if (cache == NULL)
{
@@ -209,14 +207,14 @@ remove_word (GtkSourceCompletionWordsBuffer *buffer,
return;
}
- gtk_source_completion_words_library_remove_word (buffer->priv->library,
+ gtk_source_completion_words_library_remove_word (buffer->library,
cache->proposal);
--cache->use_count;
if (cache->use_count == 0)
{
- g_hash_table_remove (buffer->priv->words, word);
+ g_hash_table_remove (buffer->words, word);
}
}
@@ -231,10 +229,10 @@ add_words (GtkSourceCompletionWordsBuffer *buffer,
GtkSourceCompletionWordsProposal *proposal;
ProposalCache *cache;
- proposal = gtk_source_completion_words_library_add_word (buffer->priv->library,
+ proposal = gtk_source_completion_words_library_add_word (buffer->library,
item->data);
- cache = g_hash_table_lookup (buffer->priv->words,
+ cache = g_hash_table_lookup (buffer->words,
item->data);
if (cache != NULL)
@@ -246,7 +244,7 @@ add_words (GtkSourceCompletionWordsBuffer *buffer,
{
/* Hash table takes over ownership of the word string */
cache = proposal_cache_new (proposal);
- g_hash_table_insert (buffer->priv->words,
+ g_hash_table_insert (buffer->words,
item->data,
cache);
}
@@ -303,15 +301,15 @@ scan_region (GtkSourceCompletionWordsBuffer *buffer,
static gboolean
idle_scan_regions (GtkSourceCompletionWordsBuffer *buffer)
{
- guint nb_remaining_lines = buffer->priv->scan_batch_size;
+ guint nb_remaining_lines = buffer->scan_batch_size;
GtkSourceRegionIter region_iter;
GtkTextIter start;
GtkTextIter stop;
- gtk_text_buffer_get_start_iter (buffer->priv->buffer, &start);
+ gtk_text_buffer_get_start_iter (buffer->buffer, &start);
stop = start;
- gtk_source_region_get_start_region_iter (buffer->priv->scan_region, ®ion_iter);
+ gtk_source_region_get_start_region_iter (buffer->scan_region, ®ion_iter);
while (nb_remaining_lines > 0 &&
!gtk_source_region_iter_is_end (®ion_iter))
@@ -332,13 +330,13 @@ idle_scan_regions (GtkSourceCompletionWordsBuffer *buffer)
gtk_source_region_iter_next (®ion_iter);
}
- gtk_source_region_subtract_subregion (buffer->priv->scan_region,
+ gtk_source_region_subtract_subregion (buffer->scan_region,
&start,
&stop);
- if (gtk_source_region_is_empty (buffer->priv->scan_region))
+ if (gtk_source_region_is_empty (buffer->scan_region))
{
- buffer->priv->batch_scan_id = 0;
+ buffer->batch_scan_id = 0;
return G_SOURCE_REMOVE;
}
@@ -348,10 +346,10 @@ idle_scan_regions (GtkSourceCompletionWordsBuffer *buffer)
static gboolean
initiate_scan (GtkSourceCompletionWordsBuffer *buffer)
{
- buffer->priv->initiate_scan_id = 0;
+ buffer->initiate_scan_id = 0;
/* Add the batch scanner */
- buffer->priv->batch_scan_id =
+ buffer->batch_scan_id =
g_timeout_add_full (G_PRIORITY_LOW,
BATCH_SCAN_TIMEOUT,
(GSourceFunc)idle_scan_regions,
@@ -364,10 +362,10 @@ initiate_scan (GtkSourceCompletionWordsBuffer *buffer)
static void
install_initiate_scan (GtkSourceCompletionWordsBuffer *buffer)
{
- if (buffer->priv->batch_scan_id == 0 &&
- buffer->priv->initiate_scan_id == 0)
+ if (buffer->batch_scan_id == 0 &&
+ buffer->initiate_scan_id == 0)
{
- buffer->priv->initiate_scan_id =
+ buffer->initiate_scan_id =
g_timeout_add_seconds_full (G_PRIORITY_LOW,
INITIATE_SCAN_TIMEOUT,
(GSourceFunc)initiate_scan,
@@ -429,12 +427,12 @@ compute_remove_region (GtkSourceCompletionWordsBuffer *buffer,
const GtkTextIter *start,
const GtkTextIter *end)
{
- GtkSourceRegion *remove_region = gtk_source_region_new (buffer->priv->buffer);
+ GtkSourceRegion *remove_region = gtk_source_region_new (buffer->buffer);
GtkSourceRegionIter region_iter;
gtk_source_region_add_subregion (remove_region, start, end);
- gtk_source_region_get_start_region_iter (buffer->priv->scan_region, ®ion_iter);
+ gtk_source_region_get_start_region_iter (buffer->scan_region, ®ion_iter);
while (!gtk_source_region_iter_is_end (®ion_iter))
{
@@ -486,7 +484,7 @@ add_to_scan_region (GtkSourceCompletionWordsBuffer *buffer,
_gtk_source_completion_words_utils_adjust_region (&start_iter, &end_iter);
- gtk_source_region_add_subregion (buffer->priv->scan_region,
+ gtk_source_region_add_subregion (buffer->scan_region,
&start_iter,
&end_iter);
@@ -540,8 +538,8 @@ on_delete_range_before_cb (GtkTextBuffer *text_buffer,
{
remove_all_words (buffer);
- g_clear_object (&buffer->priv->scan_region);
- buffer->priv->scan_region = gtk_source_region_new (text_buffer);
+ g_clear_object (&buffer->scan_region);
+ buffer->scan_region = gtk_source_region_new (text_buffer);
}
else
{
@@ -573,11 +571,11 @@ scan_all_buffer (GtkSourceCompletionWordsBuffer *buffer)
GtkTextIter start;
GtkTextIter end;
- gtk_text_buffer_get_bounds (buffer->priv->buffer,
+ gtk_text_buffer_get_bounds (buffer->buffer,
&start,
&end);
- gtk_source_region_add_subregion (buffer->priv->scan_region,
+ gtk_source_region_add_subregion (buffer->scan_region,
&start,
&end);
@@ -587,25 +585,25 @@ scan_all_buffer (GtkSourceCompletionWordsBuffer *buffer)
static void
connect_buffer (GtkSourceCompletionWordsBuffer *buffer)
{
- g_signal_connect_object (buffer->priv->buffer,
+ g_signal_connect_object (buffer->buffer,
"insert-text",
G_CALLBACK (on_insert_text_before_cb),
buffer,
0);
- g_signal_connect_object (buffer->priv->buffer,
+ g_signal_connect_object (buffer->buffer,
"insert-text",
G_CALLBACK (on_insert_text_after_cb),
buffer,
G_CONNECT_AFTER);
- g_signal_connect_object (buffer->priv->buffer,
+ g_signal_connect_object (buffer->buffer,
"delete-range",
G_CALLBACK (on_delete_range_before_cb),
buffer,
0);
- g_signal_connect_object (buffer->priv->buffer,
+ g_signal_connect_object (buffer->buffer,
"delete-range",
G_CALLBACK (on_delete_range_after_cb),
buffer,
@@ -617,23 +615,23 @@ connect_buffer (GtkSourceCompletionWordsBuffer *buffer)
static void
on_library_lock (GtkSourceCompletionWordsBuffer *buffer)
{
- if (buffer->priv->batch_scan_id != 0)
+ if (buffer->batch_scan_id != 0)
{
- g_source_remove (buffer->priv->batch_scan_id);
- buffer->priv->batch_scan_id = 0;
+ g_source_remove (buffer->batch_scan_id);
+ buffer->batch_scan_id = 0;
}
- if (buffer->priv->initiate_scan_id != 0)
+ if (buffer->initiate_scan_id != 0)
{
- g_source_remove (buffer->priv->initiate_scan_id);
- buffer->priv->initiate_scan_id = 0;
+ g_source_remove (buffer->initiate_scan_id);
+ buffer->initiate_scan_id = 0;
}
}
static void
on_library_unlock (GtkSourceCompletionWordsBuffer *buffer)
{
- if (!gtk_source_region_is_empty (buffer->priv->scan_region))
+ if (!gtk_source_region_is_empty (buffer->scan_region))
{
install_initiate_scan (buffer);
}
@@ -650,18 +648,18 @@ gtk_source_completion_words_buffer_new (GtkSourceCompletionWordsLibrary *library
ret = g_object_new (GTK_SOURCE_TYPE_COMPLETION_WORDS_BUFFER, NULL);
- ret->priv->library = g_object_ref (library);
- ret->priv->buffer = g_object_ref (buffer);
+ ret->library = g_object_ref (library);
+ ret->buffer = g_object_ref (buffer);
- ret->priv->scan_region = gtk_source_region_new (buffer);
+ ret->scan_region = gtk_source_region_new (buffer);
- g_signal_connect_object (ret->priv->library,
+ g_signal_connect_object (ret->library,
"lock",
G_CALLBACK (on_library_lock),
ret,
G_CONNECT_SWAPPED);
- g_signal_connect_object (ret->priv->library,
+ g_signal_connect_object (ret->library,
"unlock",
G_CALLBACK (on_library_unlock),
ret,
@@ -677,7 +675,7 @@ gtk_source_completion_words_buffer_get_buffer (GtkSourceCompletionWordsBuffer *b
{
g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_WORDS_BUFFER (buffer), NULL);
- return buffer->priv->buffer;
+ return buffer->buffer;
}
void
@@ -687,7 +685,7 @@ gtk_source_completion_words_buffer_set_scan_batch_size (GtkSourceCompletionWords
g_return_if_fail (GTK_SOURCE_IS_COMPLETION_WORDS_BUFFER (buffer));
g_return_if_fail (size != 0);
- buffer->priv->scan_batch_size = size;
+ buffer->scan_batch_size = size;
}
void
@@ -697,9 +695,9 @@ gtk_source_completion_words_buffer_set_minimum_word_size (GtkSourceCompletionWor
g_return_if_fail (GTK_SOURCE_IS_COMPLETION_WORDS_BUFFER (buffer));
g_return_if_fail (size != 0);
- if (buffer->priv->minimum_word_size != size)
+ if (buffer->minimum_word_size != size)
{
- buffer->priv->minimum_word_size = size;
+ buffer->minimum_word_size = size;
remove_all_words (buffer);
scan_all_buffer (buffer);
}
diff --git a/gtksourceview/completion-providers/words/gtksourcecompletionwordsbuffer.h b/gtksourceview/completion-providers/words/gtksourcecompletionwordsbuffer.h
deleted file mode 100644
index 3d350e0acad232dc8005cd4f9cf30538e89b2dff..0000000000000000000000000000000000000000
--- a/gtksourceview/completion-providers/words/gtksourcecompletionwordsbuffer.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
- *
- * This file is part of GtkSourceView
- *
- * Copyright (C) 2009 - Jesse van den Kieboom
- *
- * gtksourceview is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * gtksourceview 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, see .
- */
-
-#ifndef GTK_SOURCE_COMPLETION_WORDS_BUFFER_H
-#define GTK_SOURCE_COMPLETION_WORDS_BUFFER_H
-
-#include
-
-#include "gtksourcecompletionwordslibrary.h"
-
-G_BEGIN_DECLS
-
-#define GTK_SOURCE_TYPE_COMPLETION_WORDS_BUFFER (gtk_source_completion_words_buffer_get_type ())
-#define GTK_SOURCE_COMPLETION_WORDS_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_SOURCE_TYPE_COMPLETION_WORDS_BUFFER, GtkSourceCompletionWordsBuffer))
-#define GTK_SOURCE_COMPLETION_WORDS_BUFFER_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_SOURCE_TYPE_COMPLETION_WORDS_BUFFER, GtkSourceCompletionWordsBuffer const))
-#define GTK_SOURCE_COMPLETION_WORDS_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_SOURCE_TYPE_COMPLETION_WORDS_BUFFER, GtkSourceCompletionWordsBufferClass))
-#define GTK_SOURCE_IS_COMPLETION_WORDS_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_SOURCE_TYPE_COMPLETION_WORDS_BUFFER))
-#define GTK_SOURCE_IS_COMPLETION_WORDS_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_SOURCE_TYPE_COMPLETION_WORDS_BUFFER))
-#define GTK_SOURCE_COMPLETION_WORDS_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_SOURCE_TYPE_COMPLETION_WORDS_BUFFER, GtkSourceCompletionWordsBufferClass))
-
-typedef struct _GtkSourceCompletionWordsBuffer GtkSourceCompletionWordsBuffer;
-typedef struct _GtkSourceCompletionWordsBufferClass GtkSourceCompletionWordsBufferClass;
-typedef struct _GtkSourceCompletionWordsBufferPrivate GtkSourceCompletionWordsBufferPrivate;
-
-struct _GtkSourceCompletionWordsBuffer {
- GObject parent;
-
- GtkSourceCompletionWordsBufferPrivate *priv;
-};
-
-struct _GtkSourceCompletionWordsBufferClass {
- GObjectClass parent_class;
-};
-
-G_GNUC_INTERNAL
-GType gtk_source_completion_words_buffer_get_type (void) G_GNUC_CONST;
-
-G_GNUC_INTERNAL
-GtkSourceCompletionWordsBuffer *
- gtk_source_completion_words_buffer_new (GtkSourceCompletionWordsLibrary *library,
- GtkTextBuffer *buffer);
-
-G_GNUC_INTERNAL
-GtkTextBuffer *gtk_source_completion_words_buffer_get_buffer (GtkSourceCompletionWordsBuffer *buffer);
-
-G_GNUC_INTERNAL
-void gtk_source_completion_words_buffer_set_scan_batch_size (GtkSourceCompletionWordsBuffer *buffer,
- guint size);
-
-G_GNUC_INTERNAL
-void gtk_source_completion_words_buffer_set_minimum_word_size (GtkSourceCompletionWordsBuffer *buffer,
- guint size);
-
-G_END_DECLS
-
-#endif /* GTK_SOURCE_COMPLETION_WORDS_BUFFER_H */
diff --git a/gtksourceview/completion-providers/words/gtksourcecompletionwordslibrary-private.h b/gtksourceview/completion-providers/words/gtksourcecompletionwordslibrary-private.h
new file mode 100644
index 0000000000000000000000000000000000000000..398e53188a5a2c6497d5a6b2c03a2f6fbdf76c3d
--- /dev/null
+++ b/gtksourceview/completion-providers/words/gtksourcecompletionwordslibrary-private.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ *
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2009 - Jesse van den Kieboom
+ *
+ * gtksourceview is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * gtksourceview 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ */
+
+#pragma once
+
+#include
+
+#include "gtksourcecompletionwordsproposal-private.h"
+
+G_BEGIN_DECLS
+
+#define GTK_SOURCE_TYPE_COMPLETION_WORDS_LIBRARY (gtk_source_completion_words_library_get_type())
+
+struct _GtkSourceCompletionWordsLibraryClass
+{
+ GObjectClass parent_class;
+};
+
+GTK_SOURCE_INTERNAL
+G_DECLARE_FINAL_TYPE (GtkSourceCompletionWordsLibrary, gtk_source_completion_words_library, GTK_SOURCE, COMPLETION_WORDS_LIBRARY, GObject)
+
+GTK_SOURCE_INTERNAL
+GtkSourceCompletionWordsLibrary *gtk_source_completion_words_library_new (void);
+GTK_SOURCE_INTERNAL
+GSequenceIter *gtk_source_completion_words_library_find (GtkSourceCompletionWordsLibrary *library,
+ GtkSourceCompletionWordsProposal *proposal);
+GTK_SOURCE_INTERNAL
+GSequenceIter *gtk_source_completion_words_library_find_first (GtkSourceCompletionWordsLibrary *library,
+ const gchar *word,
+ gint len);
+GTK_SOURCE_INTERNAL
+GSequenceIter *gtk_source_completion_words_library_find_next (GSequenceIter *iter,
+ const gchar *word,
+ gint len);
+GTK_SOURCE_INTERNAL
+GtkSourceCompletionWordsProposal *gtk_source_completion_words_library_get_proposal (GSequenceIter *iter);
+GTK_SOURCE_INTERNAL
+GtkSourceCompletionWordsProposal *gtk_source_completion_words_library_add_word (GtkSourceCompletionWordsLibrary *library,
+ const gchar *word);
+GTK_SOURCE_INTERNAL
+void gtk_source_completion_words_library_remove_word (GtkSourceCompletionWordsLibrary *library,
+ GtkSourceCompletionWordsProposal *proposal);
+GTK_SOURCE_INTERNAL
+gboolean gtk_source_completion_words_library_is_locked (GtkSourceCompletionWordsLibrary *library);
+GTK_SOURCE_INTERNAL
+void gtk_source_completion_words_library_lock (GtkSourceCompletionWordsLibrary *library);
+GTK_SOURCE_INTERNAL
+void gtk_source_completion_words_library_unlock (GtkSourceCompletionWordsLibrary *library);
+
+G_END_DECLS
diff --git a/gtksourceview/completion-providers/words/gtksourcecompletionwordslibrary.c b/gtksourceview/completion-providers/words/gtksourcecompletionwordslibrary.c
index 0c4940515a08102ce6662cd7c5680324e5b6efee..2e6f7bcce7117d285ad35c0a49c5a2ab60628a92 100644
--- a/gtksourceview/completion-providers/words/gtksourcecompletionwordslibrary.c
+++ b/gtksourceview/completion-providers/words/gtksourcecompletionwordslibrary.c
@@ -19,14 +19,12 @@
* along with this library; if not, see .
*/
-#ifdef HAVE_CONFIG_H
-#include
-#endif
-
-#include "gtksourcecompletionwordslibrary.h"
+#include "config.h"
#include
+#include "gtksourcecompletionwordslibrary-private.h"
+
enum
{
LOCK,
@@ -34,22 +32,23 @@ enum
N_SIGNALS
};
-struct _GtkSourceCompletionWordsLibraryPrivate
+struct _GtkSourceCompletionWordsLibrary
{
+ GObject parent_instance;
GSequence *store;
gboolean locked;
};
static guint signals[N_SIGNALS];
-G_DEFINE_TYPE_WITH_PRIVATE (GtkSourceCompletionWordsLibrary, gtk_source_completion_words_library, G_TYPE_OBJECT)
+G_DEFINE_TYPE (GtkSourceCompletionWordsLibrary, gtk_source_completion_words_library, G_TYPE_OBJECT)
static void
gtk_source_completion_words_library_finalize (GObject *object)
{
GtkSourceCompletionWordsLibrary *library = GTK_SOURCE_COMPLETION_WORDS_LIBRARY (object);
- g_sequence_free (library->priv->store);
+ g_sequence_free (library->store);
G_OBJECT_CLASS (gtk_source_completion_words_library_parent_class)->finalize (object);
}
@@ -81,9 +80,7 @@ gtk_source_completion_words_library_class_init (GtkSourceCompletionWordsLibraryC
static void
gtk_source_completion_words_library_init (GtkSourceCompletionWordsLibrary *self)
{
- self->priv = gtk_source_completion_words_library_get_instance_private (self);
-
- self->priv->store = g_sequence_new ((GDestroyNotify)g_object_unref);
+ self->store = g_sequence_new ((GDestroyNotify)g_object_unref);
}
GtkSourceCompletionWordsLibrary *
@@ -169,7 +166,7 @@ gtk_source_completion_words_library_find_first (GtkSourceCompletionWordsLibrary
proposal = gtk_source_completion_words_proposal_new (word);
- iter = g_sequence_lookup (library->priv->store,
+ iter = g_sequence_lookup (library->store,
proposal,
(GCompareDataFunc)compare_prefix,
GINT_TO_POINTER (len));
@@ -222,7 +219,7 @@ gtk_source_completion_words_library_find (GtkSourceCompletionWordsLibrary *libr
g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_WORDS_LIBRARY (library), NULL);
g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_WORDS_PROPOSAL (proposal), NULL);
- return g_sequence_lookup (library->priv->store,
+ return g_sequence_lookup (library->store,
proposal,
(GCompareDataFunc)compare_full,
NULL);
@@ -269,7 +266,7 @@ gtk_source_completion_words_library_add_word (GtkSourceCompletionWordsLibrary *l
return iter_proposal;
}
- if (library->priv->locked)
+ if (library->locked)
{
g_object_unref (proposal);
return NULL;
@@ -280,7 +277,7 @@ gtk_source_completion_words_library_add_word (GtkSourceCompletionWordsLibrary *l
G_CALLBACK (on_proposal_unused),
library);
- g_sequence_insert_sorted (library->priv->store,
+ g_sequence_insert_sorted (library->store,
proposal,
(GCompareDataFunc)compare_full,
NULL);
@@ -303,7 +300,7 @@ gtk_source_completion_words_library_lock (GtkSourceCompletionWordsLibrary *libra
{
g_return_if_fail (GTK_SOURCE_IS_COMPLETION_WORDS_LIBRARY (library));
- library->priv->locked = TRUE;
+ library->locked = TRUE;
g_signal_emit (library, signals[LOCK], 0);
}
@@ -312,7 +309,7 @@ gtk_source_completion_words_library_unlock (GtkSourceCompletionWordsLibrary *lib
{
g_return_if_fail (GTK_SOURCE_IS_COMPLETION_WORDS_LIBRARY (library));
- library->priv->locked = FALSE;
+ library->locked = FALSE;
g_signal_emit (library, signals[UNLOCK], 0);
}
@@ -321,5 +318,5 @@ gtk_source_completion_words_library_is_locked (GtkSourceCompletionWordsLibrary *
{
g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_WORDS_LIBRARY (library), TRUE);
- return library->priv->locked;
+ return library->locked;
}
diff --git a/gtksourceview/completion-providers/words/gtksourcecompletionwordslibrary.h b/gtksourceview/completion-providers/words/gtksourcecompletionwordslibrary.h
deleted file mode 100644
index 71474512b1c15085bd70aeccae6b9b09f5269ad1..0000000000000000000000000000000000000000
--- a/gtksourceview/completion-providers/words/gtksourcecompletionwordslibrary.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
- *
- * This file is part of GtkSourceView
- *
- * Copyright (C) 2009 - Jesse van den Kieboom
- *
- * gtksourceview is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * gtksourceview 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, see .
- */
-
-#ifndef GTK_SOURCE_COMPLETION_WORDS_LIBRARY_H
-#define GTK_SOURCE_COMPLETION_WORDS_LIBRARY_H
-
-#include
-#include "gtksourcecompletionwordsproposal.h"
-
-G_BEGIN_DECLS
-
-#define GTK_SOURCE_TYPE_COMPLETION_WORDS_LIBRARY (gtk_source_completion_words_library_get_type ())
-#define GTK_SOURCE_COMPLETION_WORDS_LIBRARY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_SOURCE_TYPE_COMPLETION_WORDS_LIBRARY, GtkSourceCompletionWordsLibrary))
-#define GTK_SOURCE_COMPLETION_WORDS_LIBRARY_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_SOURCE_TYPE_COMPLETION_WORDS_LIBRARY, GtkSourceCompletionWordsLibrary const))
-#define GTK_SOURCE_COMPLETION_WORDS_LIBRARY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_SOURCE_TYPE_COMPLETION_WORDS_LIBRARY, GtkSourceCompletionWordsLibraryClass))
-#define GTK_SOURCE_IS_COMPLETION_WORDS_LIBRARY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_SOURCE_TYPE_COMPLETION_WORDS_LIBRARY))
-#define GTK_SOURCE_IS_COMPLETION_WORDS_LIBRARY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_SOURCE_TYPE_COMPLETION_WORDS_LIBRARY))
-#define GTK_SOURCE_COMPLETION_WORDS_LIBRARY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_SOURCE_TYPE_COMPLETION_WORDS_LIBRARY, GtkSourceCompletionWordsLibraryClass))
-
-typedef struct _GtkSourceCompletionWordsLibrary GtkSourceCompletionWordsLibrary;
-typedef struct _GtkSourceCompletionWordsLibraryClass GtkSourceCompletionWordsLibraryClass;
-typedef struct _GtkSourceCompletionWordsLibraryPrivate GtkSourceCompletionWordsLibraryPrivate;
-
-struct _GtkSourceCompletionWordsLibrary {
- GObject parent;
-
- GtkSourceCompletionWordsLibraryPrivate *priv;
-};
-
-struct _GtkSourceCompletionWordsLibraryClass {
- GObjectClass parent_class;
-};
-
-GTK_SOURCE_INTERNAL
-GType gtk_source_completion_words_library_get_type (void) G_GNUC_CONST;
-
-GTK_SOURCE_INTERNAL
-GtkSourceCompletionWordsLibrary *
- gtk_source_completion_words_library_new (void);
-
-/* Finding */
-GTK_SOURCE_INTERNAL
-GSequenceIter *gtk_source_completion_words_library_find (GtkSourceCompletionWordsLibrary *library,
- GtkSourceCompletionWordsProposal *proposal);
-
-GTK_SOURCE_INTERNAL
-GSequenceIter *gtk_source_completion_words_library_find_first (GtkSourceCompletionWordsLibrary *library,
- const gchar *word,
- gint len);
-
-GTK_SOURCE_INTERNAL
-GSequenceIter *gtk_source_completion_words_library_find_next (GSequenceIter *iter,
- const gchar *word,
- gint len);
-
-/* Getting */
-GTK_SOURCE_INTERNAL
-GtkSourceCompletionWordsProposal *
- gtk_source_completion_words_library_get_proposal (GSequenceIter *iter);
-
-/* Adding/removing */
-GTK_SOURCE_INTERNAL
-GtkSourceCompletionWordsProposal *
- gtk_source_completion_words_library_add_word (GtkSourceCompletionWordsLibrary *library,
- const gchar *word);
-
-GTK_SOURCE_INTERNAL
-void gtk_source_completion_words_library_remove_word (GtkSourceCompletionWordsLibrary *library,
- GtkSourceCompletionWordsProposal *proposal);
-
-GTK_SOURCE_INTERNAL
-gboolean gtk_source_completion_words_library_is_locked (GtkSourceCompletionWordsLibrary *library);
-
-GTK_SOURCE_INTERNAL
-void gtk_source_completion_words_library_lock (GtkSourceCompletionWordsLibrary *library);
-
-GTK_SOURCE_INTERNAL
-void gtk_source_completion_words_library_unlock (GtkSourceCompletionWordsLibrary *library);
-
-G_END_DECLS
-
-#endif /* GTK_SOURCE_COMPLETION_WORDS_LIBRARY_H */
diff --git a/gtksourceview/completion-providers/words/gtksourcecompletionwordsproposal-private.h b/gtksourceview/completion-providers/words/gtksourcecompletionwordsproposal-private.h
new file mode 100644
index 0000000000000000000000000000000000000000..e4121077768a63651e6d54cb53dd57484cda6863
--- /dev/null
+++ b/gtksourceview/completion-providers/words/gtksourcecompletionwordsproposal-private.h
@@ -0,0 +1,44 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ *
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2009 - Jesse van den Kieboom
+ *
+ * gtksourceview is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * gtksourceview 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ */
+
+#pragma once
+
+#include
+
+#include "../../gtksourcecompletionproposal.h"
+#include "../../gtksourcetypes-private.h"
+
+G_BEGIN_DECLS
+
+#define GTK_SOURCE_TYPE_COMPLETION_WORDS_PROPOSAL (gtk_source_completion_words_proposal_get_type())
+
+GTK_SOURCE_INTERNAL
+G_DECLARE_FINAL_TYPE (GtkSourceCompletionWordsProposal, gtk_source_completion_words_proposal, GTK_SOURCE, COMPLETION_WORDS_PROPOSAL, GObject)
+
+GTK_SOURCE_INTERNAL
+GtkSourceCompletionWordsProposal *gtk_source_completion_words_proposal_new (const gchar *word);
+GTK_SOURCE_INTERNAL
+const gchar *gtk_source_completion_words_proposal_get_word (GtkSourceCompletionWordsProposal *proposal);
+GTK_SOURCE_INTERNAL
+void gtk_source_completion_words_proposal_use (GtkSourceCompletionWordsProposal *proposal);
+GTK_SOURCE_INTERNAL
+void gtk_source_completion_words_proposal_unuse (GtkSourceCompletionWordsProposal *proposal);
+
+G_END_DECLS
diff --git a/gtksourceview/completion-providers/words/gtksourcecompletionwordsproposal.c b/gtksourceview/completion-providers/words/gtksourcecompletionwordsproposal.c
index fbcc5d2977be97d1c192b60718dba41f38153dc6..bb394e18edae42c17a21d15310dc03242e33d602 100644
--- a/gtksourceview/completion-providers/words/gtksourcecompletionwordsproposal.c
+++ b/gtksourceview/completion-providers/words/gtksourcecompletionwordsproposal.c
@@ -18,14 +18,13 @@
* along with this library; if not, see .
*/
-#ifdef HAVE_CONFIG_H
-#include
-#endif
+#include "config.h"
-#include "gtksourcecompletionwordsproposal.h"
+#include "gtksourcecompletionwordsproposal-private.h"
-struct _GtkSourceCompletionWordsProposalPrivate
+struct _GtkSourceCompletionWordsProposal
{
+ GObject parent_instance;
gchar *word;
gint use_count;
};
@@ -36,43 +35,49 @@ enum
N_SIGNALS
};
-static guint signals[N_SIGNALS];
+enum
+{
+ PROP_0,
+ PROP_WORD,
+ N_PROPS
+};
-static void gtk_source_completion_proposal_iface_init (gpointer g_iface, gpointer iface_data);
+static GParamSpec *properties[N_PROPS];
+static guint signals[N_SIGNALS];
G_DEFINE_TYPE_WITH_CODE (GtkSourceCompletionWordsProposal,
- gtk_source_completion_words_proposal,
- G_TYPE_OBJECT,
- G_ADD_PRIVATE (GtkSourceCompletionWordsProposal)
- G_IMPLEMENT_INTERFACE (GTK_SOURCE_TYPE_COMPLETION_PROPOSAL,
- gtk_source_completion_proposal_iface_init))
-
-static gchar *
-gtk_source_completion_words_proposal_get_text (GtkSourceCompletionProposal *proposal)
-{
- return g_strdup (GTK_SOURCE_COMPLETION_WORDS_PROPOSAL(proposal)->priv->word);
-}
+ gtk_source_completion_words_proposal,
+ G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GTK_SOURCE_TYPE_COMPLETION_PROPOSAL, NULL))
static void
-gtk_source_completion_proposal_iface_init (gpointer g_iface,
- gpointer iface_data)
+gtk_source_completion_words_proposal_finalize (GObject *object)
{
- GtkSourceCompletionProposalIface *iface = (GtkSourceCompletionProposalIface *)g_iface;
+ GtkSourceCompletionWordsProposal *proposal;
+
+ proposal = GTK_SOURCE_COMPLETION_WORDS_PROPOSAL (object);
+ g_free (proposal->word);
- /* Interface data getter implementations */
- iface->get_label = gtk_source_completion_words_proposal_get_text;
- iface->get_text = gtk_source_completion_words_proposal_get_text;
+ G_OBJECT_CLASS (gtk_source_completion_words_proposal_parent_class)->finalize (object);
}
static void
-gtk_source_completion_words_proposal_finalize (GObject *object)
+gtk_source_completion_words_proposal_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
{
- GtkSourceCompletionWordsProposal *proposal;
+ GtkSourceCompletionWordsProposal *self = GTK_SOURCE_COMPLETION_WORDS_PROPOSAL (object);
- proposal = GTK_SOURCE_COMPLETION_WORDS_PROPOSAL (object);
- g_free (proposal->priv->word);
+ switch (prop_id)
+ {
+ case PROP_WORD:
+ g_value_set_string (value, self->word);
+ break;
- G_OBJECT_CLASS (gtk_source_completion_words_proposal_parent_class)->finalize (object);
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
}
static void
@@ -81,6 +86,16 @@ gtk_source_completion_words_proposal_class_init (GtkSourceCompletionWordsProposa
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gtk_source_completion_words_proposal_finalize;
+ object_class->get_property = gtk_source_completion_words_proposal_get_property;
+
+ properties [PROP_WORD] =
+ g_param_spec_string ("word",
+ "Word",
+ "The word for the proposal",
+ NULL,
+ (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
signals[UNUSED] =
g_signal_new ("unused",
@@ -94,8 +109,7 @@ gtk_source_completion_words_proposal_class_init (GtkSourceCompletionWordsProposa
static void
gtk_source_completion_words_proposal_init (GtkSourceCompletionWordsProposal *self)
{
- self->priv = gtk_source_completion_words_proposal_get_instance_private (self);
- self->priv->use_count = 1;
+ self->use_count = 1;
}
GtkSourceCompletionWordsProposal *
@@ -104,7 +118,7 @@ gtk_source_completion_words_proposal_new (const gchar *word)
GtkSourceCompletionWordsProposal *proposal =
g_object_new (GTK_SOURCE_TYPE_COMPLETION_WORDS_PROPOSAL, NULL);
- proposal->priv->word = g_strdup (word);
+ proposal->word = g_strdup (word);
return proposal;
}
@@ -113,7 +127,7 @@ gtk_source_completion_words_proposal_use (GtkSourceCompletionWordsProposal *prop
{
g_return_if_fail (GTK_SOURCE_IS_COMPLETION_WORDS_PROPOSAL (proposal));
- g_atomic_int_inc (&proposal->priv->use_count);
+ g_atomic_int_inc (&proposal->use_count);
}
void
@@ -121,7 +135,7 @@ gtk_source_completion_words_proposal_unuse (GtkSourceCompletionWordsProposal *pr
{
g_return_if_fail (GTK_SOURCE_IS_COMPLETION_WORDS_PROPOSAL (proposal));
- if (g_atomic_int_dec_and_test (&proposal->priv->use_count))
+ if (g_atomic_int_dec_and_test (&proposal->use_count))
{
g_signal_emit (proposal, signals[UNUSED], 0);
}
@@ -131,6 +145,6 @@ const gchar *
gtk_source_completion_words_proposal_get_word (GtkSourceCompletionWordsProposal *proposal)
{
g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_WORDS_PROPOSAL (proposal), NULL);
- return proposal->priv->word;
+ return proposal->word;
}
diff --git a/gtksourceview/completion-providers/words/gtksourcecompletionwordsproposal.h b/gtksourceview/completion-providers/words/gtksourcecompletionwordsproposal.h
deleted file mode 100644
index 117eabaa9d4e7415bdcdd225c7badf0a20b4199c..0000000000000000000000000000000000000000
--- a/gtksourceview/completion-providers/words/gtksourcecompletionwordsproposal.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
- *
- * This file is part of GtkSourceView
- *
- * Copyright (C) 2009 - Jesse van den Kieboom
- *
- * gtksourceview is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * gtksourceview 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, see .
- */
-
-#ifndef GTK_SOURCE_COMPLETION_WORDS_PROPOSAL_H
-#define GTK_SOURCE_COMPLETION_WORDS_PROPOSAL_H
-
-#include
-#include
-
-#include "gtksourceview/gtksourcetypes-private.h"
-
-G_BEGIN_DECLS
-
-#define GTK_SOURCE_TYPE_COMPLETION_WORDS_PROPOSAL (gtk_source_completion_words_proposal_get_type ())
-#define GTK_SOURCE_COMPLETION_WORDS_PROPOSAL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_SOURCE_TYPE_COMPLETION_WORDS_PROPOSAL, GtkSourceCompletionWordsProposal))
-#define GTK_SOURCE_COMPLETION_WORDS_PROPOSAL_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_SOURCE_TYPE_COMPLETION_WORDS_PROPOSAL, GtkSourceCompletionWordsProposal const))
-#define GTK_SOURCE_COMPLETION_WORDS_PROPOSAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_SOURCE_TYPE_COMPLETION_WORDS_PROPOSAL, GtkSourceCompletionWordsProposalClass))
-#define GTK_SOURCE_IS_COMPLETION_WORDS_PROPOSAL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_SOURCE_TYPE_COMPLETION_WORDS_PROPOSAL))
-#define GTK_SOURCE_IS_COMPLETION_WORDS_PROPOSAL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_SOURCE_TYPE_COMPLETION_WORDS_PROPOSAL))
-#define GTK_SOURCE_COMPLETION_WORDS_PROPOSAL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_SOURCE_TYPE_COMPLETION_WORDS_PROPOSAL, GtkSourceCompletionWordsProposalClass))
-
-typedef struct _GtkSourceCompletionWordsProposal GtkSourceCompletionWordsProposal;
-typedef struct _GtkSourceCompletionWordsProposalClass GtkSourceCompletionWordsProposalClass;
-typedef struct _GtkSourceCompletionWordsProposalPrivate GtkSourceCompletionWordsProposalPrivate;
-
-struct _GtkSourceCompletionWordsProposal {
- GObject parent;
-
- GtkSourceCompletionWordsProposalPrivate *priv;
-};
-
-struct _GtkSourceCompletionWordsProposalClass {
- GObjectClass parent_class;
-};
-
-GTK_SOURCE_INTERNAL
-GType gtk_source_completion_words_proposal_get_type (void) G_GNUC_CONST;
-
-GTK_SOURCE_INTERNAL
-GtkSourceCompletionWordsProposal *
- gtk_source_completion_words_proposal_new (const gchar *word);
-
-GTK_SOURCE_INTERNAL
-const gchar *gtk_source_completion_words_proposal_get_word (GtkSourceCompletionWordsProposal *proposal);
-
-GTK_SOURCE_INTERNAL
-void gtk_source_completion_words_proposal_use (GtkSourceCompletionWordsProposal *proposal);
-
-GTK_SOURCE_INTERNAL
-void gtk_source_completion_words_proposal_unuse (GtkSourceCompletionWordsProposal *proposal);
-
-G_END_DECLS
-
-#endif /* GTK_SOURCE_COMPLETION_WORDS_PROPOSAL_H */
diff --git a/gtksourceview/completion-providers/words/gtksourcecompletionwordsutils.h b/gtksourceview/completion-providers/words/gtksourcecompletionwordsutils-private.h
similarity index 61%
rename from gtksourceview/completion-providers/words/gtksourcecompletionwordsutils.h
rename to gtksourceview/completion-providers/words/gtksourcecompletionwordsutils-private.h
index 4fe4ab9a0a81a38efc4f309bdf4122359737d1bc..0c1828f2842ece58a2fdd7027e0af7ffacd78e80 100644
--- a/gtksourceview/completion-providers/words/gtksourcecompletionwordsutils.h
+++ b/gtksourceview/completion-providers/words/gtksourcecompletionwordsutils-private.h
@@ -19,28 +19,22 @@
* along with this library; if not, see .
*/
-#ifndef GTK_SOURCE_COMPLETION_WORDS_UTILS_H
-#define GTK_SOURCE_COMPLETION_WORDS_UTILS_H
+#pragma once
#include
G_BEGIN_DECLS
G_GNUC_INTERNAL
-GSList *_gtk_source_completion_words_utils_scan_words (gchar *text,
- guint minimum_word_size);
-
+GSList *_gtk_source_completion_words_utils_scan_words (gchar *text,
+ guint minimum_word_size);
G_GNUC_INTERNAL
-gchar *_gtk_source_completion_words_utils_get_end_word (gchar *text);
-
+gchar *_gtk_source_completion_words_utils_get_end_word (gchar *text);
G_GNUC_INTERNAL
-void _gtk_source_completion_words_utils_adjust_region (GtkTextIter *start,
- GtkTextIter *end);
-
+void _gtk_source_completion_words_utils_adjust_region (GtkTextIter *start,
+ GtkTextIter *end);
G_GNUC_INTERNAL
-void _gtk_source_completion_words_utils_check_scan_region (const GtkTextIter *start,
- const GtkTextIter *end);
+void _gtk_source_completion_words_utils_check_scan_region (const GtkTextIter *start,
+ const GtkTextIter *end);
G_END_DECLS
-
-#endif /* GTK_SOURCE_COMPLETION_WORDS_UTILS_H */
diff --git a/gtksourceview/completion-providers/words/gtksourcecompletionwordsutils.c b/gtksourceview/completion-providers/words/gtksourcecompletionwordsutils.c
index c0a317ac6363ad40135f7809c519eead579dd0b6..6f67bcefeca4ca59dbee22e0c992a1bf1c57afd0 100644
--- a/gtksourceview/completion-providers/words/gtksourcecompletionwordsutils.c
+++ b/gtksourceview/completion-providers/words/gtksourcecompletionwordsutils.c
@@ -19,13 +19,12 @@
* along with this library; if not, see .
*/
-#ifdef HAVE_CONFIG_H
-#include
-#endif
+#include "config.h"
-#include "gtksourcecompletionwordsutils.h"
#include
+#include "gtksourcecompletionwordsutils-private.h"
+
/* Here, we work on strings. It is more efficient than working with
* GtkTextIters to traverse the text (~3x faster). Both techniques are equally
* difficult to implement.
@@ -53,8 +52,8 @@ valid_start_char (gunichar ch)
*/
static gboolean
find_next_word (gchar *text,
- guint *start_idx,
- guint *end_idx)
+ guint *start_idx,
+ guint *end_idx)
{
gchar *cur_char;
@@ -104,7 +103,7 @@ find_next_word (gchar *text,
*/
GSList *
_gtk_source_completion_words_utils_scan_words (gchar *text,
- guint minimum_word_size)
+ guint minimum_word_size)
{
GSList *words = NULL;
guint start_idx = 0;
@@ -184,7 +183,7 @@ _gtk_source_completion_words_utils_get_end_word (gchar *text)
*/
void
_gtk_source_completion_words_utils_adjust_region (GtkTextIter *start,
- GtkTextIter *end)
+ GtkTextIter *end)
{
g_return_if_fail (gtk_text_iter_compare (start, end) <= 0);
@@ -239,7 +238,7 @@ iter_inside_word (const GtkTextIter *iter)
*/
void
_gtk_source_completion_words_utils_check_scan_region (const GtkTextIter *start,
- const GtkTextIter *end)
+ const GtkTextIter *end)
{
g_return_if_fail (gtk_text_iter_compare (start, end) <= 0);
diff --git a/gtksourceview/completion-providers/words/meson.build b/gtksourceview/completion-providers/words/meson.build
index f67506498401eeefe142084e33374b7864835d69..b63b28da6b5f83fae212498db2823d756c597459 100644
--- a/gtksourceview/completion-providers/words/meson.build
+++ b/gtksourceview/completion-providers/words/meson.build
@@ -1,11 +1,10 @@
completionwords_c_args = [
- '-DHAVE_CONFIG_H',
'-DGTK_SOURCE_COMPILATION',
'-DG_LOG_DOMAIN="GtkSourceView"',
]
completionwords_public_h = [
- 'gtksourcecompletionwords.h',
+ # 'gtksourcecompletionwords.h',
]
completionwords_public_c = [
diff --git a/gtksourceview/gtksource.h b/gtksourceview/gtksource.h
index e1ae114b16c946e6d103e58a67801620564635aa..31942337545c26bdab592536d03336d74b6ae854 100644
--- a/gtksourceview/gtksource.h
+++ b/gtksourceview/gtksource.h
@@ -15,53 +15,54 @@
* along with this library; if not, see .
*/
-#ifndef GTK_SOURCE_H
-#define GTK_SOURCE_H
+#pragma once
#define GTK_SOURCE_H_INSIDE
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
+#include "gtksourcetypes.h"
+#include "gtksourcebuffer.h"
+#include "gtksourcecompletion.h"
+#include "gtksourcecompletioncell.h"
+#include "gtksourcecompletioncontext.h"
+#include "gtksourcecompletionproposal.h"
+#include "gtksourcecompletionprovider.h"
+#include "gtksourceencoding.h"
+#include "gtksourcefile.h"
+#include "gtksourcefileloader.h"
+#include "gtksourcefilesaver.h"
+#include "gtksourcegutter.h"
+#include "gtksourcegutterrenderer.h"
+#include "gtksourcegutterrenderertext.h"
+#include "gtksourcegutterrendererpixbuf.h"
+#include "gtksourceinit.h"
+#include "gtksourcelanguage.h"
+#include "gtksourcelanguagemanager.h"
+#include "gtksourcegutterlines.h"
+#include "gtksourcemap.h"
+#include "gtksourcemark.h"
+#include "gtksourcemarkattributes.h"
+#include "gtksourceprintcompositor.h"
+#include "gtksourceregion.h"
+#include "gtksourcesearchcontext.h"
+#include "gtksourcesearchsettings.h"
+#include "gtksourcesnippet.h"
+#include "gtksourcesnippetchunk.h"
+#include "gtksourcesnippetcontext.h"
+#include "gtksourcesnippetmanager.h"
+#include "gtksourcespacedrawer.h"
+#include "gtksourcestyle.h"
+#include "gtksourcestylescheme.h"
+#include "gtksourcestyleschemechooser.h"
+#include "gtksourcestyleschemechooserbutton.h"
+#include "gtksourcestyleschemechooserwidget.h"
+#include "gtksourcestyleschememanager.h"
+#include "gtksourcetag.h"
+#include "gtksourceutils.h"
+#include "gtksourceversion.h"
+#include "gtksourceview.h"
+#include "gtksource-enumtypes.h"
-#undef GTK_SOURCE_H_INSIDE
+#include "completion-providers/words/gtksourcecompletionwords.h"
+#include "completion-providers/snippets/gtksourcecompletionsnippets.h"
-#endif /* GTK_SOURCE_H */
+#undef GTK_SOURCE_H_INSIDE
diff --git a/gtksourceview/gtksourceassistant-private.h b/gtksourceview/gtksourceassistant-private.h
new file mode 100644
index 0000000000000000000000000000000000000000..d8d2084b8c512731daa07990f4b7d2257f6a4edf
--- /dev/null
+++ b/gtksourceview/gtksourceassistant-private.h
@@ -0,0 +1,60 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2020 Christian Hergert
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#pragma once
+
+#include
+
+#include "gtksourcetypes-private.h"
+
+G_BEGIN_DECLS
+
+#define GTK_SOURCE_TYPE_ASSISTANT (_gtk_source_assistant_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (GtkSourceAssistant, _gtk_source_assistant, GTK_SOURCE, ASSISTANT, GtkPopover)
+
+struct _GtkSourceAssistantClass
+{
+ GtkPopoverClass parent_class;
+
+ void (*get_offset) (GtkSourceAssistant *assistant,
+ int *x_offset,
+ int *y_offset);
+ void (*get_target_location) (GtkSourceAssistant *assistant,
+ GdkRectangle *rect);
+};
+
+GtkSourceAssistant *_gtk_source_assistant_new (void);
+void _gtk_source_assistant_attach (GtkSourceAssistant *assistant,
+ GtkSourceAssistant *attached_to);
+void _gtk_source_assistant_detach (GtkSourceAssistant *assistant);
+void _gtk_source_assistant_get_offset (GtkSourceAssistant *assistant,
+ int *x,
+ int *y);
+GtkTextMark *_gtk_source_assistant_get_mark (GtkSourceAssistant *assistant);
+void _gtk_source_assistant_set_mark (GtkSourceAssistant *assistant,
+ GtkTextMark *mark);
+void _gtk_source_assistant_set_child (GtkSourceAssistant *assistant,
+ GtkWidget *child);
+void _gtk_source_assistant_reposition (GtkSourceAssistant *assistant);
+void _gtk_source_assistant_destroy (GtkSourceAssistant *assistant);
+
+G_END_DECLS
diff --git a/gtksourceview/gtksourceassistant.c b/gtksourceview/gtksourceassistant.c
new file mode 100644
index 0000000000000000000000000000000000000000..3c7e383ddb14cade9c363a1a235f1487b84f0eac
--- /dev/null
+++ b/gtksourceview/gtksourceassistant.c
@@ -0,0 +1,427 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2020 Christian Hergert
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include "gtksourceassistant-private.h"
+#include "gtksourceassistantchild-private.h"
+#include "gtksourceview-private.h"
+
+typedef struct
+{
+ GtkTextMark *mark;
+ GtkSourceAssistantChild *child;
+} GtkSourceAssistantPrivate;
+
+static void buildable_iface_init (GtkBuildableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GtkSourceAssistant, _gtk_source_assistant, GTK_TYPE_POPOVER,
+ G_ADD_PRIVATE (GtkSourceAssistant)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, buildable_iface_init))
+
+static GtkSourceView *
+_gtk_source_assistant_get_view (GtkSourceAssistant *assistant)
+{
+ GtkWidget *widget;
+
+ g_assert (GTK_SOURCE_IS_ASSISTANT (assistant));
+
+ widget = gtk_widget_get_ancestor (GTK_WIDGET (assistant), GTK_SOURCE_TYPE_VIEW);
+
+ g_return_val_if_fail (!widget || GTK_SOURCE_IS_VIEW (widget), NULL);
+
+ return GTK_SOURCE_VIEW (widget);
+}
+
+static void
+_gtk_source_assistant_hide_action (GtkWidget *widget,
+ const gchar *action_name,
+ GVariant *parameter)
+{
+ g_assert (GTK_SOURCE_IS_ASSISTANT (widget));
+
+ gtk_popover_popdown (GTK_POPOVER (widget));
+}
+
+static void
+_gtk_source_assistant_real_get_target_location (GtkSourceAssistant *assistant,
+ GdkRectangle *location)
+{
+ GtkSourceAssistantPrivate *priv = _gtk_source_assistant_get_instance_private (assistant);
+ GtkSourceView *view;
+
+ g_assert (GTK_SOURCE_IS_ASSISTANT (assistant));
+ g_assert (location != NULL);
+
+ view = _gtk_source_assistant_get_view (assistant);
+
+ if (view != NULL)
+ {
+ GtkTextBuffer *buffer;
+ GtkTextMark *mark;
+ GtkTextIter iter;
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+ mark = priv->mark ? priv->mark : gtk_text_buffer_get_insert (buffer);
+ gtk_text_buffer_get_iter_at_mark (buffer, &iter, mark);
+ gtk_text_view_get_iter_location (GTK_TEXT_VIEW (view), &iter, location);
+ }
+ else
+ {
+ location->x = 0;
+ location->y = 0;
+ location->width = 0;
+ location->height = 0;
+ }
+}
+
+static void
+_gtk_source_assistant_get_target_location (GtkSourceAssistant *assistant,
+ GdkRectangle *location)
+{
+ g_assert (GTK_SOURCE_IS_ASSISTANT (assistant));
+ g_assert (location != NULL);
+
+ GTK_SOURCE_ASSISTANT_GET_CLASS (assistant)->get_target_location (assistant, location);
+}
+
+static void
+_gtk_source_assistant_update_position (GtkSourceAssistant *assistant)
+{
+ GtkSourceAssistantPrivate *priv = _gtk_source_assistant_get_instance_private (assistant);
+ const GList *children = NULL;
+ GtkWidget *parent;
+ GdkRectangle rect;
+ int x = 0;
+ int y = 0;
+
+ g_assert (GTK_SOURCE_IS_ASSISTANT (assistant));
+
+ parent = gtk_widget_get_parent (GTK_WIDGET (assistant));
+
+ if (GTK_SOURCE_IS_VIEW (parent))
+ {
+ _gtk_source_assistant_get_offset (assistant, &x, &y);
+ _gtk_source_assistant_get_target_location (assistant, &rect);
+
+ gtk_popover_set_offset (GTK_POPOVER (assistant), x, y);
+ gtk_popover_set_pointing_to (GTK_POPOVER (assistant), &rect);
+ }
+
+ gtk_native_check_resize (GTK_NATIVE (assistant));
+
+ if (priv->child != NULL)
+ {
+ children = _gtk_source_assistant_child_get_attached (priv->child);
+ }
+
+ for (const GList *iter = children; iter; iter = iter->next)
+ {
+ GtkSourceAssistant *child = iter->data;
+
+ _gtk_source_assistant_get_offset (child, &x, &y);
+ gtk_popover_set_offset (GTK_POPOVER (child), x, y);
+
+ if (gtk_widget_get_visible (GTK_WIDGET (child)))
+ {
+ gtk_native_check_resize (GTK_NATIVE (child));
+ }
+ }
+}
+
+static void
+_gtk_source_assistant_update_size (GtkSourceAssistant *self)
+{
+ int min_width;
+ int nat_width;
+
+ g_assert (GTK_SOURCE_IS_ASSISTANT (self));
+
+ /* Hack to force the sizing request, otherwise the popover does
+ * not shrink as results are reduced.
+ */
+ gtk_widget_set_size_request (GTK_WIDGET (self), -1, -1);
+ gtk_widget_measure (GTK_WIDGET (self),
+ GTK_ORIENTATION_HORIZONTAL,
+ -1,
+ &min_width, &nat_width, NULL, NULL);
+ gtk_widget_set_size_request (GTK_WIDGET (self), min_width, -1);
+}
+
+void
+_gtk_source_assistant_reposition (GtkSourceAssistant *self)
+{
+ g_return_if_fail (GTK_SOURCE_IS_ASSISTANT (self));
+
+ _gtk_source_assistant_update_size (self);
+ _gtk_source_assistant_update_position (self);
+}
+
+static void
+_gtk_source_assistant_show (GtkWidget *widget)
+{
+ GtkSourceAssistant *assistant = (GtkSourceAssistant *)widget;
+
+ g_assert (GTK_SOURCE_IS_ASSISTANT (assistant));
+
+ _gtk_source_assistant_reposition (assistant);
+
+ GTK_WIDGET_CLASS (_gtk_source_assistant_parent_class)->show (widget);
+}
+
+static void
+_gtk_source_assistant_hide (GtkWidget *widget)
+{
+ GtkSourceAssistant *assistant = (GtkSourceAssistant *)widget;
+ GtkSourceAssistantPrivate *priv = _gtk_source_assistant_get_instance_private (assistant);
+
+ g_assert (GTK_SOURCE_IS_ASSISTANT (assistant));
+
+ _gtk_source_assistant_child_hide (priv->child);
+
+ GTK_WIDGET_CLASS (_gtk_source_assistant_parent_class)->hide (widget);
+}
+
+static void
+_gtk_source_assistant_real_get_offset (GtkSourceAssistant *assistant,
+ int *x,
+ int *y)
+{
+ GtkStyleContext *style_context;
+ GtkBorder margin;
+ GtkPositionType pos;
+
+ g_assert (GTK_SOURCE_IS_ASSISTANT (assistant));
+ g_assert (x != NULL);
+ g_assert (y != NULL);
+
+ pos = gtk_popover_get_position (GTK_POPOVER (assistant));
+
+ style_context = gtk_widget_get_style_context (GTK_WIDGET (assistant));
+ gtk_style_context_get_margin (style_context, &margin);
+
+ *x = -margin.left;
+
+ if (pos != GTK_POS_TOP)
+ {
+ *y = -margin.top + 1;
+ }
+ else
+ {
+ *y = (margin.bottom / 3 * 2) - 1;
+ }
+}
+
+static void
+_gtk_source_assistant_dispose (GObject *object)
+{
+ GtkSourceAssistant *self = (GtkSourceAssistant *)object;
+ GtkSourceAssistantPrivate *priv = _gtk_source_assistant_get_instance_private (self);
+
+ g_assert (GTK_SOURCE_IS_ASSISTANT (self));
+
+ _gtk_source_assistant_detach (self);
+ g_clear_object (&priv->mark);
+
+ G_OBJECT_CLASS (_gtk_source_assistant_parent_class)->dispose (object);
+}
+
+static void
+_gtk_source_assistant_class_init (GtkSourceAssistantClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = _gtk_source_assistant_dispose;
+
+ widget_class->hide = _gtk_source_assistant_hide;
+ widget_class->show = _gtk_source_assistant_show;
+
+ klass->get_offset = _gtk_source_assistant_real_get_offset;
+ klass->get_target_location = _gtk_source_assistant_real_get_target_location;
+
+ gtk_widget_class_install_action (widget_class, "assistant.hide", NULL, _gtk_source_assistant_hide_action);
+ gtk_widget_class_add_binding_action (widget_class, GDK_KEY_Escape, 0, "assistant.hide", NULL);
+ gtk_widget_class_set_css_name (widget_class, "GtkSourceAssistant");
+}
+
+static void
+_gtk_source_assistant_init (GtkSourceAssistant *self)
+{
+ GtkSourceAssistantPrivate *priv = _gtk_source_assistant_get_instance_private (self);
+
+ gtk_widget_set_halign (GTK_WIDGET (self), GTK_ALIGN_START);
+ gtk_widget_set_valign (GTK_WIDGET (self), GTK_ALIGN_START);
+ gtk_popover_set_position (GTK_POPOVER (self), GTK_POS_BOTTOM);
+ gtk_popover_set_has_arrow (GTK_POPOVER (self), FALSE);
+ gtk_popover_set_autohide (GTK_POPOVER (self), TRUE);
+
+ priv->child = _gtk_source_assistant_child_new ();
+ gtk_popover_set_child (GTK_POPOVER (self), GTK_WIDGET (priv->child));
+}
+
+GtkSourceAssistant *
+_gtk_source_assistant_new (void)
+{
+ return g_object_new (GTK_SOURCE_TYPE_ASSISTANT, NULL);
+}
+
+void
+_gtk_source_assistant_set_mark (GtkSourceAssistant *assistant,
+ GtkTextMark *mark)
+{
+ GtkSourceAssistantPrivate *priv = _gtk_source_assistant_get_instance_private (assistant);
+
+ g_return_if_fail (GTK_SOURCE_IS_ASSISTANT (assistant));
+ g_return_if_fail (GTK_IS_TEXT_MARK (mark));
+
+ if (g_set_object (&priv->mark, mark))
+ {
+ _gtk_source_assistant_update_position (assistant);
+ }
+}
+
+GtkTextMark *
+_gtk_source_assistant_get_mark (GtkSourceAssistant *assistant)
+{
+ GtkSourceAssistantPrivate *priv = _gtk_source_assistant_get_instance_private (assistant);
+
+ g_return_val_if_fail (GTK_SOURCE_IS_ASSISTANT (assistant), NULL);
+
+ return priv->mark;
+}
+
+void
+_gtk_source_assistant_get_offset (GtkSourceAssistant *assistant,
+ int *x,
+ int *y)
+{
+ int dummy_x;
+ int dummy_y;
+
+ g_return_if_fail (GTK_SOURCE_IS_ASSISTANT (assistant));
+
+ if (x == NULL)
+ x = &dummy_x;
+
+ if (y == NULL)
+ y = &dummy_y;
+
+ *x = 0;
+ *y = 0;
+
+ GTK_SOURCE_ASSISTANT_GET_CLASS (assistant)->get_offset (assistant, x, y);
+}
+
+void
+_gtk_source_assistant_detach (GtkSourceAssistant *assistant)
+{
+ GtkWidget *parent;
+
+ g_return_if_fail (GTK_SOURCE_IS_ASSISTANT (assistant));
+
+ parent = gtk_widget_get_parent (GTK_WIDGET (assistant));
+
+ if (GTK_SOURCE_IS_ASSISTANT_CHILD (parent))
+ {
+ _gtk_source_assistant_child_detach (GTK_SOURCE_ASSISTANT_CHILD (parent),
+ assistant);
+ }
+}
+
+void
+_gtk_source_assistant_attach (GtkSourceAssistant *assistant,
+ GtkSourceAssistant *attach_to)
+{
+ GtkSourceAssistantPrivate *priv;
+
+ g_return_if_fail (GTK_SOURCE_IS_ASSISTANT (assistant));
+ g_return_if_fail (!attach_to || GTK_SOURCE_IS_ASSISTANT (attach_to));
+
+ if (attach_to == NULL)
+ {
+ _gtk_source_assistant_detach (assistant);
+ }
+ else
+ {
+ priv = _gtk_source_assistant_get_instance_private (attach_to);
+ _gtk_source_assistant_child_attach (priv->child, assistant);
+ }
+}
+
+void
+_gtk_source_assistant_set_child (GtkSourceAssistant *assistant,
+ GtkWidget *child)
+{
+ GtkSourceAssistantPrivate *priv = _gtk_source_assistant_get_instance_private (assistant);
+
+ g_return_if_fail (GTK_SOURCE_IS_ASSISTANT (assistant));
+ g_return_if_fail (!child || GTK_IS_WIDGET (child));
+
+ _gtk_source_assistant_child_set_child (priv->child, child);
+}
+
+static void
+_gtk_source_assistant_add_child (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const char *type)
+{
+ GtkSourceAssistant *self = (GtkSourceAssistant *)buildable;
+
+ if (GTK_IS_WIDGET (child))
+ {
+ _gtk_source_assistant_set_child (self, GTK_WIDGET (child));
+ }
+}
+
+static void
+buildable_iface_init (GtkBuildableIface *iface)
+{
+ iface->add_child = _gtk_source_assistant_add_child;
+}
+
+void
+_gtk_source_assistant_destroy (GtkSourceAssistant *self)
+{
+ GtkWidget *parent;
+
+ g_return_if_fail (GTK_SOURCE_IS_ASSISTANT (self));
+
+ parent = gtk_widget_get_parent (GTK_WIDGET (self));
+
+ if (parent == NULL)
+ return;
+
+ if (GTK_SOURCE_IS_VIEW (parent))
+ {
+ _gtk_source_view_remove_assistant (GTK_SOURCE_VIEW (parent), self);
+ }
+ else if (GTK_SOURCE_IS_ASSISTANT_CHILD (parent))
+ {
+ _gtk_source_assistant_child_detach (GTK_SOURCE_ASSISTANT_CHILD (parent), self);
+ }
+ else
+ {
+ g_warning ("Cannot remove assistant from type %s",
+ G_OBJECT_TYPE_NAME (parent));
+ }
+}
diff --git a/gtksourceview/gtksourceassistantchild-private.h b/gtksourceview/gtksourceassistantchild-private.h
new file mode 100644
index 0000000000000000000000000000000000000000..cf2718343feb73355321df734d5e778cb6f10f26
--- /dev/null
+++ b/gtksourceview/gtksourceassistantchild-private.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2020 Christian Hergert
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#pragma once
+
+#include
+
+#include "gtksourcetypes-private.h"
+
+G_BEGIN_DECLS
+
+#define GTK_SOURCE_TYPE_ASSISTANT_CHILD (_gtk_source_assistant_child_get_type())
+
+G_DECLARE_FINAL_TYPE (GtkSourceAssistantChild, _gtk_source_assistant_child, GTK_SOURCE, ASSISTANT_CHILD, GtkWidget)
+
+GtkSourceAssistantChild *_gtk_source_assistant_child_new (void);
+void _gtk_source_assistant_child_hide (GtkSourceAssistantChild *self);
+void _gtk_source_assistant_child_set_child (GtkSourceAssistantChild *self,
+ GtkWidget *child);
+void _gtk_source_assistant_child_attach (GtkSourceAssistantChild *self,
+ GtkSourceAssistant *child);
+void _gtk_source_assistant_child_detach (GtkSourceAssistantChild *self,
+ GtkSourceAssistant *child);
+const GList *_gtk_source_assistant_child_get_attached (GtkSourceAssistantChild *self);
+
+G_END_DECLS
diff --git a/gtksourceview/gtksourceassistantchild.c b/gtksourceview/gtksourceassistantchild.c
new file mode 100644
index 0000000000000000000000000000000000000000..1981d251b6b2ba6e62c281d38f6e6f795a803fe6
--- /dev/null
+++ b/gtksourceview/gtksourceassistantchild.c
@@ -0,0 +1,186 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2020 Christian Hergert
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include "gtksourceassistant-private.h"
+#include "gtksourceassistantchild-private.h"
+
+struct _GtkSourceAssistantChild
+{
+ GtkWidget parent_instance;
+ GtkWidget *child;
+ GQueue attached;
+};
+
+G_DEFINE_TYPE (GtkSourceAssistantChild, _gtk_source_assistant_child, GTK_TYPE_WIDGET)
+
+static void
+_gtk_source_assistant_child_size_allocate (GtkWidget *widget,
+ int width,
+ int height,
+ int baseline)
+{
+ GtkSourceAssistantChild *child = (GtkSourceAssistantChild *)widget;
+
+ g_assert (GTK_SOURCE_IS_ASSISTANT_CHILD (child));
+
+ GTK_WIDGET_CLASS (_gtk_source_assistant_child_parent_class)->size_allocate (widget, width, height, baseline);
+
+ for (const GList *iter = child->attached.head; iter; iter = iter->next)
+ {
+ GtkSourceAssistant *attached = iter->data;
+
+ g_assert (GTK_SOURCE_IS_ASSISTANT (attached));
+ g_assert (GTK_IS_NATIVE (attached));
+
+ if (gtk_widget_get_visible (GTK_WIDGET (attached)))
+ {
+ gtk_native_check_resize (GTK_NATIVE (attached));
+ }
+ }
+}
+
+static void
+_gtk_source_assistant_child_dispose (GObject *object)
+{
+ GtkSourceAssistantChild *self = (GtkSourceAssistantChild *)object;
+
+ g_assert (GTK_SOURCE_IS_ASSISTANT_CHILD (self));
+
+ while (self->attached.head != NULL)
+ {
+ GtkSourceAssistant *attached = self->attached.head->data;
+
+ g_assert (GTK_SOURCE_IS_ASSISTANT (attached));
+
+ _gtk_source_assistant_child_detach (self, attached);
+ }
+
+ g_clear_pointer (&self->child, gtk_widget_unparent);
+
+ G_OBJECT_CLASS (_gtk_source_assistant_child_parent_class)->dispose (object);
+}
+
+static void
+_gtk_source_assistant_child_class_init (GtkSourceAssistantChildClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = _gtk_source_assistant_child_dispose;
+
+ widget_class->size_allocate = _gtk_source_assistant_child_size_allocate;
+
+ gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
+}
+
+static void
+_gtk_source_assistant_child_init (GtkSourceAssistantChild *self)
+{
+}
+
+GtkSourceAssistantChild *
+_gtk_source_assistant_child_new (void)
+{
+ return g_object_new (GTK_SOURCE_TYPE_ASSISTANT_CHILD, NULL);
+}
+
+void
+_gtk_source_assistant_child_hide (GtkSourceAssistantChild *self)
+{
+ g_assert (GTK_SOURCE_IS_ASSISTANT_CHILD (self));
+
+ for (const GList *iter = self->attached.head; iter; iter = iter->next)
+ {
+ GtkSourceAssistant *attached = iter->data;
+
+ g_assert (GTK_SOURCE_IS_ASSISTANT (attached));
+ g_assert (GTK_IS_POPOVER (attached));
+
+ gtk_popover_popdown (GTK_POPOVER (attached));
+ }
+}
+
+void
+_gtk_source_assistant_child_detach (GtkSourceAssistantChild *self,
+ GtkSourceAssistant *child)
+{
+ g_return_if_fail (GTK_SOURCE_IS_ASSISTANT_CHILD (self));
+ g_return_if_fail (GTK_SOURCE_IS_ASSISTANT (child));
+
+ if (g_queue_remove (&self->attached, child))
+ {
+ gtk_widget_unparent (GTK_WIDGET (child));
+ g_object_unref (child);
+ }
+}
+
+void
+_gtk_source_assistant_child_attach (GtkSourceAssistantChild *self,
+ GtkSourceAssistant *child)
+{
+ g_return_if_fail (GTK_SOURCE_IS_ASSISTANT_CHILD (self));
+ g_return_if_fail (GTK_SOURCE_IS_ASSISTANT (child));
+ g_return_if_fail (gtk_widget_get_parent (GTK_WIDGET (child)) == NULL);
+
+ g_queue_push_tail (&self->attached, g_object_ref_sink (child));
+ gtk_widget_set_parent (GTK_WIDGET (child), GTK_WIDGET (self));
+
+ if (GTK_IS_NATIVE (child))
+ {
+ if (gtk_widget_get_visible (GTK_WIDGET (child)))
+ {
+ gtk_native_check_resize (GTK_NATIVE (child));
+ }
+ }
+}
+
+void
+_gtk_source_assistant_child_set_child (GtkSourceAssistantChild *self,
+ GtkWidget *child)
+{
+ g_return_if_fail (GTK_SOURCE_IS_ASSISTANT_CHILD (self));
+ g_return_if_fail (GTK_IS_WIDGET (child));
+
+ if (child == self->child)
+ {
+ return;
+ }
+
+ g_clear_pointer (&self->child, gtk_widget_unparent);
+
+ if (child != NULL)
+ {
+ self->child = child;
+ gtk_widget_set_parent (child, GTK_WIDGET (self));
+ }
+
+ gtk_widget_queue_resize (GTK_WIDGET (self));
+}
+
+const GList *
+_gtk_source_assistant_child_get_attached (GtkSourceAssistantChild *self)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_ASSISTANT_CHILD (self), NULL);
+
+ return self->attached.head;
+}
diff --git a/gtksourceview/gtksourceautocleanups.h b/gtksourceview/gtksourceautocleanups.h
deleted file mode 100644
index 9929368a9830ab1b05df8cf5400d759552e1f884..0000000000000000000000000000000000000000
--- a/gtksourceview/gtksourceautocleanups.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * This file is part of gtksourceview
- *
- * gtksourceview is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * gtksourceview 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, see .
- */
-
-#ifndef GTK_SOURCE_AUTOCLEANUPS_H
-#define GTK_SOURCE_AUTOCLEANUPS_H
-
-#if !defined (GTK_SOURCE_H_INSIDE) && !defined (GTK_SOURCE_COMPILATION)
-#error "Only can be included directly."
-#endif
-
-#include
-#include
-
-G_BEGIN_DECLS
-
-#ifndef __GI_SCANNER__
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceBuffer, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceCompletion, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceCompletionContext, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceCompletionInfo, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceCompletionItem, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceFile, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceFileLoader, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceFileSaver, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceGutter, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceGutterRenderer, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceGutterRendererPixbuf, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceGutterRendererText, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceLanguage, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceLanguageManager, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceMark, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceMap, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourcePrintCompositor, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceSearchContext, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceSearchSettings, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceSpaceDrawer, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceStyleScheme, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceStyleSchemeChooserButton, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceStyleSchemeChooserWidget, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceStyleSchemeManager, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceUndoManager, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSourceView, g_object_unref)
-
-#endif /* __GI_SCANNER__ */
-
-G_END_DECLS
-
-#endif /* GTK_SOURCE_AUTOCLEANUPS_H */
diff --git a/gtksourceview/gtksourcebindinggroup-private.h b/gtksourceview/gtksourcebindinggroup-private.h
new file mode 100644
index 0000000000000000000000000000000000000000..2d2a345350ca617292edb50b65e7967a7465a4e9
--- /dev/null
+++ b/gtksourceview/gtksourcebindinggroup-private.h
@@ -0,0 +1,59 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2015 Christian Hergert
+ * Copyright 2015 Garrett Regier
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#pragma once
+
+#include
+
+G_BEGIN_DECLS
+
+#define GTK_SOURCE_TYPE_BINDING_GROUP (gtk_source_binding_group_get_type())
+
+G_DECLARE_FINAL_TYPE (GtkSourceBindingGroup, gtk_source_binding_group, GTK_SOURCE, BINDING_GROUP, GObject)
+
+GtkSourceBindingGroup *gtk_source_binding_group_new (void);
+GObject *gtk_source_binding_group_get_source (GtkSourceBindingGroup *self);
+void gtk_source_binding_group_set_source (GtkSourceBindingGroup *self,
+ gpointer source);
+void gtk_source_binding_group_bind (GtkSourceBindingGroup *self,
+ const gchar *source_property,
+ gpointer target,
+ const gchar *target_property,
+ GBindingFlags flags);
+void gtk_source_binding_group_bind_full (GtkSourceBindingGroup *self,
+ const gchar *source_property,
+ gpointer target,
+ const gchar *target_property,
+ GBindingFlags flags,
+ GBindingTransformFunc transform_to,
+ GBindingTransformFunc transform_from,
+ gpointer user_data,
+ GDestroyNotify user_data_destroy);
+void gtk_source_binding_group_bind_with_closures (GtkSourceBindingGroup *self,
+ const gchar *source_property,
+ gpointer target,
+ const gchar *target_property,
+ GBindingFlags flags,
+ GClosure *transform_to,
+ GClosure *transform_from);
+
+G_END_DECLS
diff --git a/gtksourceview/gtksourcebindinggroup.c b/gtksourceview/gtksourcebindinggroup.c
new file mode 100644
index 0000000000000000000000000000000000000000..198fb129a36578b39ac1cce90535ebfa300f4a77
--- /dev/null
+++ b/gtksourceview/gtksourcebindinggroup.c
@@ -0,0 +1,622 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2015 Christian Hergert
+ * Copyright 2015 Garrett Regier
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include
+
+#include "gtksourcebindinggroup-private.h"
+
+/**
+ * SECTION:gtksourcebindinggroup:
+ * @title: GtkSourceBindingGroup
+ * @short_description: Binding multiple properties as a group
+ *
+ * The #GtkSourceBindingGroup can be used to bind multiple properties
+ * from an object collectively.
+ *
+ * Use the various methods to bind properties from a single source
+ * object to multiple destination objects. Properties can be bound
+ * bidrectionally and are connected when the source object is set
+ * with gtk_source_binding_group_set_source().
+ */
+
+struct _GtkSourceBindingGroup
+{
+ GObject parent_instance;
+ GObject *source;
+ GPtrArray *lazy_bindings;
+};
+
+typedef struct
+{
+ GtkSourceBindingGroup *group;
+ const char *source_property;
+ const char *target_property;
+ GObject *target;
+ GBinding *binding;
+ gpointer user_data;
+ GDestroyNotify user_data_destroy;
+ gpointer transform_to;
+ gpointer transform_from;
+ GBindingFlags binding_flags;
+ guint using_closures : 1;
+} LazyBinding;
+
+G_DEFINE_TYPE (GtkSourceBindingGroup, gtk_source_binding_group, G_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_SOURCE,
+ N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+/*#define DEBUG_BINDINGS 1*/
+
+#ifdef DEBUG_BINDINGS
+static char *
+_g_flags_to_string (GFlagsClass *flags_class,
+ guint value)
+{
+ GString *str = g_string_new (NULL);
+ GFlagsValue *flags_value;
+ gboolean first = TRUE;
+
+ while ((first || value != 0) &&
+ (flags_value = g_flags_get_first_value (flags_class, value)) != NULL)
+ {
+ if (!first)
+ g_string_append (str, " | ");
+
+ g_string_append (str, flags_value->value_name);
+
+ first = FALSE;
+ value &= ~(flags_value->value);
+ }
+
+ return g_string_free (str, FALSE);
+}
+#endif
+
+static void
+gtk_source_binding_group_connect (GtkSourceBindingGroup *self,
+ LazyBinding *lazy_binding)
+{
+ GBinding *binding;
+
+ g_assert (GTK_SOURCE_IS_BINDING_GROUP (self));
+ g_assert (self->source != NULL);
+ g_assert (lazy_binding != NULL);
+ g_assert (lazy_binding->binding == NULL);
+ g_assert (lazy_binding->target != NULL);
+ g_assert (lazy_binding->target_property != NULL);
+ g_assert (lazy_binding->source_property != NULL);
+
+#ifdef DEBUG_BINDINGS
+ {
+ GFlagsClass *flags_class;
+ g_autofree gchar *flags_str = NULL;
+
+ flags_class = g_type_class_ref (G_TYPE_BINDING_FLAGS);
+ flags_str = _g_flags_to_string (flags_class, lazy_binding->binding_flags);
+
+ g_print ("Binding %s(%p):%s to %s(%p):%s (flags=%s)\n",
+ G_OBJECT_TYPE_NAME (self->source),
+ self->source,
+ lazy_binding->source_property,
+ G_OBJECT_TYPE_NAME (lazy_binding->target),
+ lazy_binding->target,
+ lazy_binding->target_property,
+ flags_str);
+
+ g_type_class_unref (flags_class);
+ }
+#endif
+
+ if (!lazy_binding->using_closures)
+ binding = g_object_bind_property_full (self->source,
+ lazy_binding->source_property,
+ lazy_binding->target,
+ lazy_binding->target_property,
+ lazy_binding->binding_flags,
+ lazy_binding->transform_to,
+ lazy_binding->transform_from,
+ lazy_binding->user_data,
+ NULL);
+ else
+ binding = g_object_bind_property_with_closures (self->source,
+ lazy_binding->source_property,
+ lazy_binding->target,
+ lazy_binding->target_property,
+ lazy_binding->binding_flags,
+ lazy_binding->transform_to,
+ lazy_binding->transform_from);
+
+ lazy_binding->binding = binding;
+}
+
+static void
+gtk_source_binding_group_disconnect (LazyBinding *lazy_binding)
+{
+ g_assert (lazy_binding != NULL);
+
+ if (lazy_binding->binding != NULL)
+ {
+ g_binding_unbind (lazy_binding->binding);
+ lazy_binding->binding = NULL;
+ }
+}
+
+static void
+gtk_source_binding_group__source_weak_notify (gpointer data,
+ GObject *where_object_was)
+{
+ GtkSourceBindingGroup *self = data;
+ gsize i;
+
+ g_assert (GTK_SOURCE_IS_BINDING_GROUP (self));
+
+ self->source = NULL;
+
+ for (i = 0; i < self->lazy_bindings->len; i++)
+ {
+ LazyBinding *lazy_binding;
+
+ lazy_binding = g_ptr_array_index (self->lazy_bindings, i);
+ lazy_binding->binding = NULL;
+ }
+}
+
+static void
+gtk_source_binding_group__target_weak_notify (gpointer data,
+ GObject *where_object_was)
+{
+ GtkSourceBindingGroup *self = data;
+ gsize i;
+
+ g_assert (GTK_SOURCE_IS_BINDING_GROUP (self));
+
+ for (i = 0; i < self->lazy_bindings->len; i++)
+ {
+ LazyBinding *lazy_binding;
+
+ lazy_binding = g_ptr_array_index (self->lazy_bindings, i);
+
+ if (lazy_binding->target == where_object_was)
+ {
+ lazy_binding->target = NULL;
+ lazy_binding->binding = NULL;
+
+ g_ptr_array_remove_index_fast (self->lazy_bindings, i);
+ break;
+ }
+ }
+}
+
+static void
+lazy_binding_free (gpointer data)
+{
+ LazyBinding *lazy_binding = data;
+
+ if (lazy_binding->target != NULL)
+ {
+ g_object_weak_unref (lazy_binding->target,
+ gtk_source_binding_group__target_weak_notify,
+ lazy_binding->group);
+ lazy_binding->target = NULL;
+ }
+
+ gtk_source_binding_group_disconnect (lazy_binding);
+
+ lazy_binding->group = NULL;
+ lazy_binding->source_property = NULL;
+ lazy_binding->target_property = NULL;
+
+ if (lazy_binding->user_data_destroy)
+ lazy_binding->user_data_destroy (lazy_binding->user_data);
+
+ if (lazy_binding->using_closures)
+ {
+ g_clear_pointer (&lazy_binding->transform_to, g_closure_unref);
+ g_clear_pointer (&lazy_binding->transform_from, g_closure_unref);
+ }
+
+ g_slice_free (LazyBinding, lazy_binding);
+}
+
+static void
+gtk_source_binding_group_dispose (GObject *object)
+{
+ GtkSourceBindingGroup *self = (GtkSourceBindingGroup *)object;
+
+ g_assert (GTK_SOURCE_IS_BINDING_GROUP (self));
+
+ if (self->source != NULL)
+ {
+ g_object_weak_unref (self->source,
+ gtk_source_binding_group__source_weak_notify,
+ self);
+ self->source = NULL;
+ }
+
+ if (self->lazy_bindings->len != 0)
+ g_ptr_array_remove_range (self->lazy_bindings, 0, self->lazy_bindings->len);
+
+ G_OBJECT_CLASS (gtk_source_binding_group_parent_class)->dispose (object);
+}
+
+static void
+gtk_source_binding_group_finalize (GObject *object)
+{
+ GtkSourceBindingGroup *self = (GtkSourceBindingGroup *)object;
+
+ g_assert (self->lazy_bindings != NULL);
+ g_assert (self->lazy_bindings->len == 0);
+
+ g_clear_pointer (&self->lazy_bindings, g_ptr_array_unref);
+
+ G_OBJECT_CLASS (gtk_source_binding_group_parent_class)->finalize (object);
+}
+
+static void
+gtk_source_binding_group_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceBindingGroup *self = GTK_SOURCE_BINDING_GROUP (object);
+
+ switch (prop_id)
+ {
+ case PROP_SOURCE:
+ g_value_set_object (value, gtk_source_binding_group_get_source (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gtk_source_binding_group_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceBindingGroup *self = GTK_SOURCE_BINDING_GROUP (object);
+
+ switch (prop_id)
+ {
+ case PROP_SOURCE:
+ gtk_source_binding_group_set_source (self, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gtk_source_binding_group_class_init (GtkSourceBindingGroupClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = gtk_source_binding_group_dispose;
+ object_class->finalize = gtk_source_binding_group_finalize;
+ object_class->get_property = gtk_source_binding_group_get_property;
+ object_class->set_property = gtk_source_binding_group_set_property;
+
+ /**
+ * GtkSourceBindingGroup:source:
+ *
+ * The source object used for binding properties.
+ */
+ properties [PROP_SOURCE] =
+ g_param_spec_object ("source",
+ "Source",
+ "The source GObject used for binding properties.",
+ G_TYPE_OBJECT,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+gtk_source_binding_group_init (GtkSourceBindingGroup *self)
+{
+ self->lazy_bindings = g_ptr_array_new_with_free_func (lazy_binding_free);
+}
+
+/**
+ * gtk_source_binding_group_new:
+ *
+ * Creates a new #GtkSourceBindingGroup.
+ *
+ * Returns: a new #GtkSourceBindingGroup
+ */
+GtkSourceBindingGroup *
+gtk_source_binding_group_new (void)
+{
+ return g_object_new (GTK_SOURCE_TYPE_BINDING_GROUP, NULL);
+}
+
+/**
+ * gtk_source_binding_group_get_source:
+ * @self: the #GtkSourceBindingGroup
+ *
+ * Gets the source object used for binding properties.
+ *
+ * Returns: (transfer none) (nullable): the source object.
+ */
+GObject *
+gtk_source_binding_group_get_source (GtkSourceBindingGroup *self)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_BINDING_GROUP (self), NULL);
+
+ return self->source;
+}
+
+static gboolean
+gtk_source_binding_group_check_source (GtkSourceBindingGroup *self,
+ gpointer source)
+{
+ for (guint i = 0; i < self->lazy_bindings->len; i++)
+ {
+ LazyBinding *lazy_binding = g_ptr_array_index (self->lazy_bindings, i);
+
+ g_return_val_if_fail (g_object_class_find_property (G_OBJECT_GET_CLASS (source),
+ lazy_binding->source_property) != NULL,
+ FALSE);
+ }
+
+ return TRUE;
+}
+
+/**
+ * gtk_source_binding_group_set_source:
+ * @self: the #GtkSourceBindingGroup
+ * @source: (type GObject) (nullable): the source #GObject
+ *
+ * Sets @source as the source object used for creating property
+ * bindings. If there is already a source object all bindings from it
+ * will be removed.
+ *
+ * Note: All properties that have been bound must exist on @source.
+ */
+void
+gtk_source_binding_group_set_source (GtkSourceBindingGroup *self,
+ gpointer source)
+{
+ g_return_if_fail (GTK_SOURCE_IS_BINDING_GROUP (self));
+ g_return_if_fail (!source || G_IS_OBJECT (source));
+ g_return_if_fail (source != (gpointer)self);
+
+ if (source == (gpointer)self->source)
+ return;
+
+ if (self->source != NULL)
+ {
+ g_object_weak_unref (self->source,
+ gtk_source_binding_group__source_weak_notify,
+ self);
+ self->source = NULL;
+
+ for (guint i = 0; i < self->lazy_bindings->len; i++)
+ {
+ LazyBinding *lazy_binding;
+
+ lazy_binding = g_ptr_array_index (self->lazy_bindings, i);
+ gtk_source_binding_group_disconnect (lazy_binding);
+ }
+ }
+
+ if (source != NULL && gtk_source_binding_group_check_source (self, source))
+ {
+ self->source = source;
+ g_object_weak_ref (self->source,
+ gtk_source_binding_group__source_weak_notify,
+ self);
+
+ for (guint i = 0; i < self->lazy_bindings->len; i++)
+ {
+ LazyBinding *lazy_binding;
+
+ lazy_binding = g_ptr_array_index (self->lazy_bindings, i);
+ gtk_source_binding_group_connect (self, lazy_binding);
+ }
+ }
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SOURCE]);
+}
+
+static void
+gtk_source_binding_group_bind_helper (GtkSourceBindingGroup *self,
+ const gchar *source_property,
+ gpointer target,
+ const gchar *target_property,
+ GBindingFlags flags,
+ gpointer transform_to,
+ gpointer transform_from,
+ gpointer user_data,
+ GDestroyNotify user_data_destroy,
+ gboolean using_closures)
+{
+ LazyBinding *lazy_binding;
+
+ g_return_if_fail (GTK_SOURCE_IS_BINDING_GROUP (self));
+ g_return_if_fail (source_property != NULL);
+ g_return_if_fail (self->source == NULL ||
+ g_object_class_find_property (G_OBJECT_GET_CLASS (self->source),
+ source_property) != NULL);
+ g_return_if_fail (G_IS_OBJECT (target));
+ g_return_if_fail (target_property != NULL);
+ g_return_if_fail (g_object_class_find_property (G_OBJECT_GET_CLASS (target),
+ target_property) != NULL);
+ g_return_if_fail (target != (gpointer)self ||
+ strcmp (source_property, target_property) != 0);
+
+ lazy_binding = g_slice_new0 (LazyBinding);
+ lazy_binding->group = self;
+ lazy_binding->source_property = g_intern_string (source_property);
+ lazy_binding->target_property = g_intern_string (target_property);
+ lazy_binding->target = target;
+ lazy_binding->binding_flags = flags | G_BINDING_SYNC_CREATE;
+ lazy_binding->user_data = user_data;
+ lazy_binding->user_data_destroy = user_data_destroy;
+ lazy_binding->transform_to = transform_to;
+ lazy_binding->transform_from = transform_from;
+
+ if (using_closures)
+ {
+ lazy_binding->using_closures = TRUE;
+
+ if (transform_to != NULL)
+ g_closure_sink (g_closure_ref (transform_to));
+
+ if (transform_from != NULL)
+ g_closure_sink (g_closure_ref (transform_from));
+ }
+
+ g_object_weak_ref (target,
+ gtk_source_binding_group__target_weak_notify,
+ self);
+
+ g_ptr_array_add (self->lazy_bindings, lazy_binding);
+
+ if (self->source != NULL)
+ gtk_source_binding_group_connect (self, lazy_binding);
+}
+
+/**
+ * gtk_source_binding_group_bind:
+ * @self: the #GtkSourceBindingGroup
+ * @source_property: the property on the source to bind
+ * @target: (type GObject): the target #GObject
+ * @target_property: the property on @target to bind
+ * @flags: the flags used to create the #GBinding
+ *
+ * Creates a binding between @source_property on the source object
+ * and @target_property on @target. Whenever the @source_property
+ * is changed the @target_property is updated using the same value.
+ * The binding flags #G_BINDING_SYNC_CREATE is automatically specified.
+ *
+ * See: g_object_bind_property().
+ */
+void
+gtk_source_binding_group_bind (GtkSourceBindingGroup *self,
+ const gchar *source_property,
+ gpointer target,
+ const gchar *target_property,
+ GBindingFlags flags)
+{
+ gtk_source_binding_group_bind_full (self, source_property,
+ target, target_property,
+ flags,
+ NULL, NULL,
+ NULL, NULL);
+}
+
+/**
+ * gtk_source_binding_group_bind_full:
+ * @self: the #GtkSourceBindingGroup
+ * @source_property: the property on the source to bind
+ * @target: (type GObject): the target #GObject
+ * @target_property: the property on @target to bind
+ * @flags: the flags used to create the #GBinding
+ * @transform_to: (scope notified) (nullable): the transformation function
+ * from the source object to the @target, or %NULL to use the default
+ * @transform_from: (scope notified) (nullable): the transformation function
+ * from the @target to the source object, or %NULL to use the default
+ * @user_data: custom data to be passed to the transformation
+ * functions, or %NULL
+ * @user_data_destroy: function to be called when disposing the binding,
+ * to free the resources used by the transformation functions
+ *
+ * Creates a binding between @source_property on the source object and
+ * @target_property on @target, allowing you to set the transformation
+ * functions to be used by the binding. The binding flags
+ * #G_BINDING_SYNC_CREATE is automatically specified.
+ *
+ * See: g_object_bind_property_full().
+ */
+void
+gtk_source_binding_group_bind_full (GtkSourceBindingGroup *self,
+ const gchar *source_property,
+ gpointer target,
+ const gchar *target_property,
+ GBindingFlags flags,
+ GBindingTransformFunc transform_to,
+ GBindingTransformFunc transform_from,
+ gpointer user_data,
+ GDestroyNotify user_data_destroy)
+{
+ gtk_source_binding_group_bind_helper (self, source_property,
+ target, target_property,
+ flags,
+ transform_to, transform_from,
+ user_data, user_data_destroy,
+ FALSE);
+}
+
+/**
+ * gtk_source_binding_group_bind_with_closures: (rename-to gtk_source_binding_group_bind_full)
+ * @self: the #GtkSourceBindingGroup
+ * @source_property: the property on the source to bind
+ * @target: (type GObject): the target #GObject
+ * @target_property: the property on @target to bind
+ * @flags: the flags used to create the #GBinding
+ * @transform_to: (nullable): a #GClosure wrapping the
+ * transformation function from the source object to the @target,
+ * or %NULL to use the default
+ * @transform_from: (nullable): a #GClosure wrapping the
+ * transformation function from the @target to the source object,
+ * or %NULL to use the default
+ *
+ * Creates a binding between @source_property on the source object and
+ * @target_property on @target, allowing you to set the transformation
+ * functions to be used by the binding. The binding flags
+ * #G_BINDING_SYNC_CREATE is automatically specified.
+ *
+ * This function is the language bindings friendly version of
+ * gtk_source_binding_group_bind_property_full(), using #GClosures
+ * instead of function pointers.
+ *
+ * See: g_object_bind_property_with_closures().
+ */
+void
+gtk_source_binding_group_bind_with_closures (GtkSourceBindingGroup *self,
+ const gchar *source_property,
+ gpointer target,
+ const gchar *target_property,
+ GBindingFlags flags,
+ GClosure *transform_to,
+ GClosure *transform_from)
+{
+ gtk_source_binding_group_bind_helper (self, source_property,
+ target, target_property,
+ flags,
+ transform_to, transform_from,
+ NULL, NULL,
+ TRUE);
+}
diff --git a/gtksourceview/gtksourcebuffer-private.h b/gtksourceview/gtksourcebuffer-private.h
index 5fcf12b90ea8f4bf0f63ca1ea14a151f01aa560d..4a0765f08c326a6d8fe8ce7207717fe5bdaab572 100644
--- a/gtksourceview/gtksourcebuffer-private.h
+++ b/gtksourceview/gtksourcebuffer-private.h
@@ -1,8 +1,7 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- */
/*
* This file is part of GtkSourceView
*
- * Copyright (C) 2013, 2016 - Sébastien Wilmet
+ * Copyright 2013, 2016 - Sébastien Wilmet
*
* GtkSourceView is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -18,8 +17,7 @@
* along with this library; if not, see .
*/
-#ifndef GTK_SOURCE_BUFFER_PRIVATE_H
-#define GTK_SOURCE_BUFFER_PRIVATE_H
+#pragma once
#include
@@ -30,64 +28,48 @@
G_BEGIN_DECLS
GTK_SOURCE_INTERNAL
-void _gtk_source_buffer_update_syntax_highlight (GtkSourceBuffer *buffer,
- const GtkTextIter *start,
- const GtkTextIter *end,
- gboolean synchronous);
-
+void _gtk_source_buffer_update_syntax_highlight (GtkSourceBuffer *buffer,
+ const GtkTextIter *start,
+ const GtkTextIter *end,
+ gboolean synchronous);
GTK_SOURCE_INTERNAL
-void _gtk_source_buffer_update_search_highlight (GtkSourceBuffer *buffer,
- const GtkTextIter *start,
- const GtkTextIter *end,
- gboolean synchronous);
-
+void _gtk_source_buffer_update_search_highlight (GtkSourceBuffer *buffer,
+ const GtkTextIter *start,
+ const GtkTextIter *end,
+ gboolean synchronous);
GTK_SOURCE_INTERNAL
-GtkSourceMark *_gtk_source_buffer_source_mark_next (GtkSourceBuffer *buffer,
- GtkSourceMark *mark,
- const gchar *category);
-
+GtkSourceMark *_gtk_source_buffer_source_mark_next (GtkSourceBuffer *buffer,
+ GtkSourceMark *mark,
+ const gchar *category);
GTK_SOURCE_INTERNAL
-GtkSourceMark *_gtk_source_buffer_source_mark_prev (GtkSourceBuffer *buffer,
- GtkSourceMark *mark,
- const gchar *category);
-
+GtkSourceMark *_gtk_source_buffer_source_mark_prev (GtkSourceBuffer *buffer,
+ GtkSourceMark *mark,
+ const gchar *category);
GTK_SOURCE_INTERNAL
-GtkTextTag *_gtk_source_buffer_get_bracket_match_tag (GtkSourceBuffer *buffer);
-
+GtkTextTag *_gtk_source_buffer_get_bracket_match_tag (GtkSourceBuffer *buffer);
GTK_SOURCE_INTERNAL
-void _gtk_source_buffer_add_search_context (GtkSourceBuffer *buffer,
- GtkSourceSearchContext *search_context);
-
+void _gtk_source_buffer_add_search_context (GtkSourceBuffer *buffer,
+ GtkSourceSearchContext *search_context);
GTK_SOURCE_INTERNAL
-void _gtk_source_buffer_set_as_invalid_character (GtkSourceBuffer *buffer,
- const GtkTextIter *start,
- const GtkTextIter *end);
-
+void _gtk_source_buffer_set_as_invalid_character (GtkSourceBuffer *buffer,
+ const GtkTextIter *start,
+ const GtkTextIter *end);
GTK_SOURCE_INTERNAL
-gboolean _gtk_source_buffer_has_invalid_chars (GtkSourceBuffer *buffer);
-
+gboolean _gtk_source_buffer_has_invalid_chars (GtkSourceBuffer *buffer);
GTK_SOURCE_INTERNAL
-GtkSourceBracketMatchType
- _gtk_source_buffer_find_bracket_match (GtkSourceBuffer *buffer,
- const GtkTextIter *pos,
- GtkTextIter *bracket,
- GtkTextIter *bracket_match);
-
+GtkSourceBracketMatchType _gtk_source_buffer_find_bracket_match (GtkSourceBuffer *buffer,
+ const GtkTextIter *pos,
+ GtkTextIter *bracket,
+ GtkTextIter *bracket_match);
GTK_SOURCE_INTERNAL
-void _gtk_source_buffer_save_and_clear_selection (GtkSourceBuffer *buffer);
-
+void _gtk_source_buffer_save_and_clear_selection (GtkSourceBuffer *buffer);
GTK_SOURCE_INTERNAL
-void _gtk_source_buffer_restore_selection (GtkSourceBuffer *buffer);
-
+void _gtk_source_buffer_restore_selection (GtkSourceBuffer *buffer);
GTK_SOURCE_INTERNAL
-gboolean _gtk_source_buffer_is_undo_redo_enabled (GtkSourceBuffer *buffer);
-
+gboolean _gtk_source_buffer_has_source_marks (GtkSourceBuffer *buffer);
GTK_SOURCE_INTERNAL
-gboolean _gtk_source_buffer_has_source_marks (GtkSourceBuffer *buffer);
-
+gboolean _gtk_source_buffer_has_spaces_tag (GtkSourceBuffer *buffer);
GTK_SOURCE_INTERNAL
-gboolean _gtk_source_buffer_has_spaces_tag (GtkSourceBuffer *buffer);
+GtkTextTag *_gtk_source_buffer_get_snippet_focus_tag (GtkSourceBuffer *buffer);
G_END_DECLS
-
-#endif /* GTK_SOURCE_BUFFER_PRIVATE_H */
diff --git a/gtksourceview/gtksourcebuffer.c b/gtksourceview/gtksourcebuffer.c
index 57c8a437bedb133dc5981e496fba02801d5b2388..758f37ed36df41de493f7f5b925d720c7bda8855 100644
--- a/gtksourceview/gtksourcebuffer.c
+++ b/gtksourceview/gtksourcebuffer.c
@@ -1,12 +1,11 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- */
/*
* This file is part of GtkSourceView
*
- * Copyright (C) 1999-2002 - Mikael Hermansson ,
- * Chris Phelps and
- * Jeroen Zwartepoorte
- * Copyright (C) 2003 - Paolo Maggi and
- * Gustavo Giráldez
+ * Copyright 1999-2002 - Mikael Hermansson ,
+ * Chris Phelps and
+ * Jeroen Zwartepoorte
+ * Copyright 2003 - Paolo Maggi and
+ * Gustavo Giráldez
*
* GtkSourceView is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -22,9 +21,7 @@
* along with this library; if not, see .
*/
-#ifdef HAVE_CONFIG_H
-#include
-#endif
+#include "config.h"
#include "gtksourcebuffer.h"
#include "gtksourcebuffer-private.h"
@@ -36,14 +33,12 @@
#include "gtksourcelanguage.h"
#include "gtksourcelanguage-private.h"
#include "gtksource-marshal.h"
-#include "gtksourceundomanager.h"
-#include "gtksourceundomanagerdefault.h"
#include "gtksourcestyle.h"
-#include "gtksourcestylescheme.h"
+#include "gtksourcestylescheme-private.h"
#include "gtksourcestyleschememanager.h"
#include "gtksourcemark.h"
-#include "gtksourcemarkssequence.h"
-#include "gtksourcesearchcontext.h"
+#include "gtksourcemarkssequence-private.h"
+#include "gtksourcesearchcontext-private.h"
#include "gtksourcetag.h"
#include "gtksource-enumtypes.h"
@@ -55,8 +50,7 @@
*
* A #GtkSourceBuffer object is the model for #GtkSourceView widgets.
* It extends the #GtkTextBuffer class by adding features useful to display
- * and edit source code such as syntax highlighting and bracket matching. It
- * also implements support for the undo/redo.
+ * and edit source code such as syntax highlighting and bracket matching.
*
* To create a #GtkSourceBuffer use gtk_source_buffer_new() or
* gtk_source_buffer_new_with_language(). The second form is just a convenience
@@ -67,34 +61,6 @@
* The highlighting is enabled by default, but you can disable it with
* gtk_source_buffer_set_highlight_syntax().
*
- * # Undo/Redo
- *
- * A custom #GtkSourceUndoManager can be implemented and set with
- * gtk_source_buffer_set_undo_manager(). However the default implementation
- * should be suitable for most uses, so you can use the API provided by
- * #GtkSourceBuffer instead of using #GtkSourceUndoManager. By default, actions
- * that can be undone or redone are defined as groups of operations between a
- * call to gtk_text_buffer_begin_user_action() and
- * gtk_text_buffer_end_user_action(). In general, this happens whenever the user
- * presses any key which modifies the buffer. But the default undo manager will
- * try to merge similar consecutive actions into one undo/redo level. The
- * merging is done word by word, so after writing a new sentence (character by
- * character), each undo will remove the previous word.
- *
- * The default undo manager remembers the "modified" state of the buffer, and
- * restores it when an action is undone or redone. It can be useful in a text
- * editor to know whether the file is saved. See gtk_text_buffer_get_modified()
- * and gtk_text_buffer_set_modified().
- *
- * The default undo manager also restores the selected text (or cursor
- * position), if the selection was related to the action. For example if the
- * user selects some text and deletes it, an undo will restore the selection. On
- * the other hand, if some text is selected but a deletion occurs elsewhere (the
- * deletion was done programmatically), an undo will not restore the selection,
- * it will only moves the cursor (the cursor is moved so that the user sees the
- * undo's effect). Warning: the selection restoring behavior might change in the
- * future.
- *
* # Context Classes # {#context-classes}
*
* It is possible to retrieve some information from the syntax highlighting
@@ -163,12 +129,13 @@
#define PROFILE(x)
#endif
-#define UPDATE_BRACKET_DELAY 50
-#define BRACKET_MATCHING_CHARS_LIMIT 10000
-#define CONTEXT_CLASSES_PREFIX "gtksourceview:context-classes:"
+#define UPDATE_BRACKET_DELAY 50
+#define BRACKET_MATCHING_CHARS_LIMIT 10000
+#define CONTEXT_CLASSES_PREFIX "gtksourceview:context-classes:"
enum
{
+ CURSOR_MOVED,
HIGHLIGHT_UPDATED,
SOURCE_MARK_UPDATED,
UNDO,
@@ -180,19 +147,15 @@ enum
enum
{
PROP_0,
- PROP_CAN_UNDO,
- PROP_CAN_REDO,
- PROP_HIGHLIGHT_SYNTAX,
PROP_HIGHLIGHT_MATCHING_BRACKETS,
- PROP_MAX_UNDO_LEVELS,
+ PROP_HIGHLIGHT_SYNTAX,
+ PROP_IMPLICIT_TRAILING_NEWLINE,
PROP_LANGUAGE,
PROP_STYLE_SCHEME,
- PROP_UNDO_MANAGER,
- PROP_IMPLICIT_TRAILING_NEWLINE,
N_PROPERTIES
};
-struct _GtkSourceBufferPrivate
+typedef struct
{
GtkTextTag *bracket_match_tag;
GtkSourceBracketMatchType bracket_match_state;
@@ -206,12 +169,11 @@ struct _GtkSourceBufferPrivate
GtkSourceLanguage *language;
GtkSourceEngine *highlight_engine;
- GtkSourceUndoManager *undo_manager;
- gint max_undo_levels;
-
GtkTextMark *tmp_insert_mark;
GtkTextMark *tmp_selection_bound_mark;
+ GtkTextTag *snippet_focus_tag;
+
GList *search_contexts;
GtkTextTag *invalid_char_tag;
@@ -220,61 +182,51 @@ struct _GtkSourceBufferPrivate
guint highlight_syntax : 1;
guint highlight_brackets : 1;
guint implicit_trailing_newline : 1;
-};
+} GtkSourceBufferPrivate;
-static guint buffer_signals[N_SIGNALS];
static GParamSpec *buffer_properties[N_PROPERTIES];
+static guint buffer_signals[N_SIGNALS];
G_DEFINE_TYPE_WITH_PRIVATE (GtkSourceBuffer, gtk_source_buffer, GTK_TYPE_TEXT_BUFFER)
-/* Prototypes */
-static void gtk_source_buffer_dispose (GObject *object);
-static void gtk_source_buffer_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
-static void gtk_source_buffer_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
-static void gtk_source_buffer_can_undo_handler (GtkSourceUndoManager *manager,
- GtkSourceBuffer *buffer);
-static void gtk_source_buffer_can_redo_handler (GtkSourceUndoManager *manager,
- GtkSourceBuffer *buffer);
-static void gtk_source_buffer_real_insert_text (GtkTextBuffer *buffer,
- GtkTextIter *iter,
- const gchar *text,
- gint len);
-static void gtk_source_buffer_real_insert_pixbuf (GtkTextBuffer *buffer,
- GtkTextIter *pos,
- GdkPixbuf *pixbuf);
-static void gtk_source_buffer_real_insert_child_anchor
- (GtkTextBuffer *buffer,
- GtkTextIter *pos,
- GtkTextChildAnchor *anchor);
-static void gtk_source_buffer_real_delete_range (GtkTextBuffer *buffer,
- GtkTextIter *iter,
- GtkTextIter *end);
-static void gtk_source_buffer_real_mark_set (GtkTextBuffer *buffer,
- const GtkTextIter *location,
- GtkTextMark *mark);
-
-static void gtk_source_buffer_real_mark_deleted (GtkTextBuffer *buffer,
- GtkTextMark *mark);
-
-static void gtk_source_buffer_real_undo (GtkSourceBuffer *buffer);
-static void gtk_source_buffer_real_redo (GtkSourceBuffer *buffer);
-
-static void gtk_source_buffer_real_highlight_updated
- (GtkSourceBuffer *buffer,
- GtkTextIter *start,
- GtkTextIter *end);
+static void gtk_source_buffer_dispose (GObject *object);
+static void gtk_source_buffer_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gtk_source_buffer_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void gtk_source_buffer_real_insert_text (GtkTextBuffer *buffer,
+ GtkTextIter *iter,
+ const gchar *text,
+ gint len);
+static void gtk_source_buffer_real_insert_paintable (GtkTextBuffer *buffer,
+ GtkTextIter *pos,
+ GdkPaintable *paintable);
+static void gtk_source_buffer_real_insert_child_anchor (GtkTextBuffer *buffer,
+ GtkTextIter *pos,
+ GtkTextChildAnchor *anchor);
+static void gtk_source_buffer_real_delete_range (GtkTextBuffer *buffer,
+ GtkTextIter *iter,
+ GtkTextIter *end);
+static void gtk_source_buffer_real_mark_set (GtkTextBuffer *buffer,
+ const GtkTextIter *location,
+ GtkTextMark *mark);
+static void gtk_source_buffer_real_mark_deleted (GtkTextBuffer *buffer,
+ GtkTextMark *mark);
+static void gtk_source_buffer_real_highlight_updated (GtkSourceBuffer *buffer,
+ GtkTextIter *start,
+ GtkTextIter *end);
static void
gtk_source_buffer_check_tag_for_spaces (GtkSourceBuffer *buffer,
GtkSourceTag *tag)
{
- if (!buffer->priv->has_draw_spaces_tag)
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
+ if (!priv->has_draw_spaces_tag)
{
gboolean draw_spaces_set;
@@ -284,7 +236,7 @@ gtk_source_buffer_check_tag_for_spaces (GtkSourceBuffer *buffer,
if (draw_spaces_set)
{
- buffer->priv->has_draw_spaces_tag = TRUE;
+ priv->has_draw_spaces_tag = TRUE;
}
}
}
@@ -306,10 +258,18 @@ gtk_source_buffer_tag_added_cb (GtkTextTagTable *table,
GtkTextTag *tag,
GtkSourceBuffer *buffer)
{
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
if (GTK_SOURCE_IS_TAG (tag))
{
gtk_source_buffer_check_tag_for_spaces (buffer, GTK_SOURCE_TAG (tag));
}
+
+ if (priv->snippet_focus_tag != NULL)
+ {
+ gtk_text_tag_set_priority (priv->snippet_focus_tag,
+ gtk_text_tag_table_get_size (table) - 1);
+ }
}
static void
@@ -318,12 +278,6 @@ gtk_source_buffer_constructed (GObject *object)
GtkSourceBuffer *buffer = GTK_SOURCE_BUFFER (object);
GtkTextTagTable *table;
- if (buffer->priv->undo_manager == NULL)
- {
- /* This will install the default undo manager */
- gtk_source_buffer_set_undo_manager (buffer, NULL);
- }
-
G_OBJECT_CLASS (gtk_source_buffer_parent_class)->constructed (object);
table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (buffer));
@@ -353,14 +307,11 @@ gtk_source_buffer_class_init (GtkSourceBufferClass *klass)
text_buffer_class->delete_range = gtk_source_buffer_real_delete_range;
text_buffer_class->insert_text = gtk_source_buffer_real_insert_text;
- text_buffer_class->insert_pixbuf = gtk_source_buffer_real_insert_pixbuf;
+ text_buffer_class->insert_paintable = gtk_source_buffer_real_insert_paintable;
text_buffer_class->insert_child_anchor = gtk_source_buffer_real_insert_child_anchor;
text_buffer_class->mark_set = gtk_source_buffer_real_mark_set;
text_buffer_class->mark_deleted = gtk_source_buffer_real_mark_deleted;
- klass->undo = gtk_source_buffer_real_undo;
- klass->redo = gtk_source_buffer_real_redo;
-
/**
* GtkSourceBuffer:highlight-syntax:
*
@@ -387,22 +338,6 @@ gtk_source_buffer_class_init (GtkSourceBufferClass *klass)
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS);
- /**
- * GtkSourceBuffer:max-undo-levels:
- *
- * Number of undo levels for the buffer. -1 means no limit. This property
- * will only affect the default undo manager.
- */
- buffer_properties[PROP_MAX_UNDO_LEVELS] =
- g_param_spec_int ("max-undo-levels",
- "Maximum Undo Levels",
- "Number of undo levels for the buffer",
- -1,
- G_MAXINT,
- -1,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS);
-
buffer_properties[PROP_LANGUAGE] =
g_param_spec_object ("language",
"Language",
@@ -411,22 +346,6 @@ gtk_source_buffer_class_init (GtkSourceBufferClass *klass)
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS);
- buffer_properties[PROP_CAN_UNDO] =
- g_param_spec_boolean ("can-undo",
- "Can undo",
- "Whether Undo operation is possible",
- FALSE,
- G_PARAM_READABLE |
- G_PARAM_STATIC_STRINGS);
-
- buffer_properties[PROP_CAN_REDO] =
- g_param_spec_boolean ("can-redo",
- "Can redo",
- "Whether Redo operation is possible",
- FALSE,
- G_PARAM_READABLE |
- G_PARAM_STATIC_STRINGS);
-
/**
* GtkSourceBuffer:style-scheme:
*
@@ -442,15 +361,6 @@ gtk_source_buffer_class_init (GtkSourceBufferClass *klass)
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS);
- buffer_properties[PROP_UNDO_MANAGER] =
- g_param_spec_object ("undo-manager",
- "Undo manager",
- "The buffer undo manager",
- GTK_SOURCE_TYPE_UNDO_MANAGER,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT |
- G_PARAM_STATIC_STRINGS);
-
/**
* GtkSourceBuffer:implicit-trailing-newline:
*
@@ -470,6 +380,21 @@ gtk_source_buffer_class_init (GtkSourceBufferClass *klass)
g_object_class_install_properties (object_class, N_PROPERTIES, buffer_properties);
+ /**
+ * GtkSourceBuffer::cursor-moved:
+ * @buffer: a #GtkSourceBuffer
+ *
+ * The "cursor-moved" signal is emitted when then insertion mark has moved.
+ *
+ * Since: 5.0
+ */
+ buffer_signals[CURSOR_MOVED] =
+ g_signal_new_class_handler ("cursor-moved",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ NULL, NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+
/**
* GtkSourceBuffer::highlight-updated:
* @buffer: the buffer that received the signal
@@ -516,43 +441,6 @@ gtk_source_buffer_class_init (GtkSourceBufferClass *klass)
G_TYPE_FROM_CLASS (klass),
g_cclosure_marshal_VOID__OBJECTv);
- /**
- * GtkSourceBuffer::undo:
- * @buffer: the buffer that received the signal
- *
- * The ::undo signal is emitted to undo the last user action which
- * modified the buffer.
- */
- buffer_signals[UNDO] =
- g_signal_new ("undo",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkSourceBufferClass, undo),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
- g_signal_set_va_marshaller (buffer_signals[UNDO],
- G_TYPE_FROM_CLASS (klass),
- g_cclosure_marshal_VOID__VOIDv);
-
- /**
- * GtkSourceBuffer::redo:
- * @buffer: the buffer that received the signal
- *
- * The ::redo signal is emitted to redo the last undo operation.
- */
- buffer_signals[REDO] =
- g_signal_new ("redo",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkSourceBufferClass, redo),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
- g_signal_set_va_marshaller (buffer_signals[REDO],
- G_TYPE_FROM_CLASS (klass),
- g_cclosure_marshal_VOID__VOIDv);
-
/**
* GtkSourceBuffer::bracket-matched:
* @buffer: a #GtkSourceBuffer.
@@ -585,55 +473,13 @@ gtk_source_buffer_class_init (GtkSourceBufferClass *klass)
_gtk_source_marshal_VOID__BOXED_ENUMv);
}
-static void
-set_undo_manager (GtkSourceBuffer *buffer,
- GtkSourceUndoManager *manager)
-{
- if (manager == buffer->priv->undo_manager)
- {
- return;
- }
-
- if (buffer->priv->undo_manager != NULL)
- {
- g_signal_handlers_disconnect_by_func (buffer->priv->undo_manager,
- G_CALLBACK (gtk_source_buffer_can_undo_handler),
- buffer);
-
- g_signal_handlers_disconnect_by_func (buffer->priv->undo_manager,
- G_CALLBACK (gtk_source_buffer_can_redo_handler),
- buffer);
-
- g_object_unref (buffer->priv->undo_manager);
- buffer->priv->undo_manager = NULL;
- }
-
- if (manager != NULL)
- {
- buffer->priv->undo_manager = g_object_ref (manager);
-
- g_signal_connect (buffer->priv->undo_manager,
- "can-undo-changed",
- G_CALLBACK (gtk_source_buffer_can_undo_handler),
- buffer);
-
- g_signal_connect (buffer->priv->undo_manager,
- "can-redo-changed",
- G_CALLBACK (gtk_source_buffer_can_redo_handler),
- buffer);
-
- /* Notify possible changes in the can-undo/redo state */
- g_object_notify_by_pspec (G_OBJECT (buffer), buffer_properties[PROP_CAN_UNDO]);
- g_object_notify_by_pspec (G_OBJECT (buffer), buffer_properties[PROP_CAN_REDO]);
- }
-}
-
static void
search_context_weak_notify_cb (GtkSourceBuffer *buffer,
GObject *search_context)
{
- buffer->priv->search_contexts = g_list_remove (buffer->priv->search_contexts,
- search_context);
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
+ priv->search_contexts = g_list_remove (priv->search_contexts, search_context);
}
static void
@@ -641,12 +487,9 @@ gtk_source_buffer_init (GtkSourceBuffer *buffer)
{
GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
- buffer->priv = priv;
-
priv->highlight_syntax = TRUE;
priv->highlight_brackets = TRUE;
priv->bracket_match_state = GTK_SOURCE_BRACKET_MATCH_NONE;
- priv->max_undo_levels = -1;
priv->source_marks = g_hash_table_new_full (g_str_hash,
g_str_equal,
@@ -667,29 +510,25 @@ static void
gtk_source_buffer_dispose (GObject *object)
{
GtkSourceBuffer *buffer = GTK_SOURCE_BUFFER (object);
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
GList *l;
- if (buffer->priv->bracket_highlighting_timeout_id != 0)
+ if (priv->bracket_highlighting_timeout_id != 0)
{
- g_source_remove (buffer->priv->bracket_highlighting_timeout_id);
- buffer->priv->bracket_highlighting_timeout_id = 0;
+ g_source_remove (priv->bracket_highlighting_timeout_id);
+ priv->bracket_highlighting_timeout_id = 0;
}
- if (buffer->priv->undo_manager != NULL)
+ if (priv->highlight_engine != NULL)
{
- set_undo_manager (buffer, NULL);
+ _gtk_source_engine_attach_buffer (priv->highlight_engine, NULL);
}
- if (buffer->priv->highlight_engine != NULL)
- {
- _gtk_source_engine_attach_buffer (buffer->priv->highlight_engine, NULL);
- }
+ g_clear_object (&priv->highlight_engine);
+ g_clear_object (&priv->language);
+ g_clear_object (&priv->style_scheme);
- g_clear_object (&buffer->priv->highlight_engine);
- g_clear_object (&buffer->priv->language);
- g_clear_object (&buffer->priv->style_scheme);
-
- for (l = buffer->priv->search_contexts; l != NULL; l = l->next)
+ for (l = priv->search_contexts; l != NULL; l = l->next)
{
GtkSourceSearchContext *search_context = l->data;
@@ -698,15 +537,15 @@ gtk_source_buffer_dispose (GObject *object)
buffer);
}
- g_list_free (buffer->priv->search_contexts);
- buffer->priv->search_contexts = NULL;
+ g_list_free (priv->search_contexts);
+ priv->search_contexts = NULL;
- g_clear_object (&buffer->priv->all_source_marks);
+ g_clear_object (&priv->all_source_marks);
- if (buffer->priv->source_marks != NULL)
+ if (priv->source_marks != NULL)
{
- g_hash_table_unref (buffer->priv->source_marks);
- buffer->priv->source_marks = NULL;
+ g_hash_table_unref (priv->source_marks);
+ priv->source_marks = NULL;
}
G_OBJECT_CLASS (gtk_source_buffer_parent_class)->dispose (object);
@@ -718,11 +557,7 @@ gtk_source_buffer_set_property (GObject *object,
const GValue *value,
GParamSpec *pspec)
{
- GtkSourceBuffer *buffer;
-
- g_return_if_fail (GTK_SOURCE_IS_BUFFER (object));
-
- buffer = GTK_SOURCE_BUFFER (object);
+ GtkSourceBuffer *buffer = GTK_SOURCE_BUFFER (object);
switch (prop_id)
{
@@ -734,10 +569,6 @@ gtk_source_buffer_set_property (GObject *object,
gtk_source_buffer_set_highlight_matching_brackets (buffer, g_value_get_boolean (value));
break;
- case PROP_MAX_UNDO_LEVELS:
- gtk_source_buffer_set_max_undo_levels (buffer, g_value_get_int (value));
- break;
-
case PROP_LANGUAGE:
gtk_source_buffer_set_language (buffer, g_value_get_object (value));
break;
@@ -746,10 +577,6 @@ gtk_source_buffer_set_property (GObject *object,
gtk_source_buffer_set_style_scheme (buffer, g_value_get_object (value));
break;
- case PROP_UNDO_MANAGER:
- gtk_source_buffer_set_undo_manager (buffer, g_value_get_object (value));
- break;
-
case PROP_IMPLICIT_TRAILING_NEWLINE:
gtk_source_buffer_set_implicit_trailing_newline (buffer, g_value_get_boolean (value));
break;
@@ -766,48 +593,29 @@ gtk_source_buffer_get_property (GObject *object,
GValue *value,
GParamSpec *pspec)
{
- GtkSourceBuffer *buffer;
-
- g_return_if_fail (GTK_SOURCE_IS_BUFFER (object));
-
- buffer = GTK_SOURCE_BUFFER (object);
+ GtkSourceBuffer *buffer = GTK_SOURCE_BUFFER (object);
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
switch (prop_id)
{
case PROP_HIGHLIGHT_SYNTAX:
- g_value_set_boolean (value, buffer->priv->highlight_syntax);
+ g_value_set_boolean (value, priv->highlight_syntax);
break;
case PROP_HIGHLIGHT_MATCHING_BRACKETS:
- g_value_set_boolean (value, buffer->priv->highlight_brackets);
- break;
-
- case PROP_MAX_UNDO_LEVELS:
- g_value_set_int (value, buffer->priv->max_undo_levels);
+ g_value_set_boolean (value, priv->highlight_brackets);
break;
case PROP_LANGUAGE:
- g_value_set_object (value, buffer->priv->language);
+ g_value_set_object (value, priv->language);
break;
case PROP_STYLE_SCHEME:
- g_value_set_object (value, buffer->priv->style_scheme);
- break;
-
- case PROP_CAN_UNDO:
- g_value_set_boolean (value, gtk_source_buffer_can_undo (buffer));
- break;
-
- case PROP_CAN_REDO:
- g_value_set_boolean (value, gtk_source_buffer_can_redo (buffer));
- break;
-
- case PROP_UNDO_MANAGER:
- g_value_set_object (value, buffer->priv->undo_manager);
+ g_value_set_object (value, priv->style_scheme);
break;
case PROP_IMPLICIT_TRAILING_NEWLINE:
- g_value_set_boolean (value, buffer->priv->implicit_trailing_newline);
+ g_value_set_boolean (value, priv->implicit_trailing_newline);
break;
default:
@@ -827,6 +635,8 @@ gtk_source_buffer_get_property (GObject *object,
GtkSourceBuffer *
gtk_source_buffer_new (GtkTextTagTable *table)
{
+ g_return_val_if_fail (table == NULL || GTK_IS_TEXT_TAG_TABLE (table), NULL);
+
return g_object_new (GTK_SOURCE_TYPE_BUFFER,
"tag-table", table,
NULL);
@@ -855,54 +665,75 @@ gtk_source_buffer_new_with_language (GtkSourceLanguage *language)
}
static void
-gtk_source_buffer_can_undo_handler (GtkSourceUndoManager *manager,
- GtkSourceBuffer *buffer)
+update_snippet_focus_style (GtkSourceBuffer *buffer)
{
- g_return_if_fail (GTK_SOURCE_IS_BUFFER (buffer));
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+ GtkSourceStyle *style = NULL;
+
+ if (priv->snippet_focus_tag == NULL)
+ {
+ return;
+ }
+
+ if (priv->style_scheme != NULL)
+ {
+ style = _gtk_source_style_scheme_get_snippet_focus_style (priv->style_scheme);
+ }
- g_object_notify_by_pspec (G_OBJECT (buffer), buffer_properties[PROP_CAN_UNDO]);
+ gtk_source_style_apply (style, priv->snippet_focus_tag);
}
-static void
-gtk_source_buffer_can_redo_handler (GtkSourceUndoManager *manager,
- GtkSourceBuffer *buffer)
+GtkTextTag *
+_gtk_source_buffer_get_snippet_focus_tag (GtkSourceBuffer *buffer)
{
- g_return_if_fail (GTK_SOURCE_IS_BUFFER (buffer));
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
+ if (priv->snippet_focus_tag == NULL)
+ {
+ priv->snippet_focus_tag =
+ gtk_text_buffer_create_tag (GTK_TEXT_BUFFER (buffer),
+ NULL,
+ NULL);
+ update_snippet_focus_style (buffer);
+ }
- g_object_notify_by_pspec (G_OBJECT (buffer), buffer_properties[PROP_CAN_REDO]);
+ return priv->snippet_focus_tag;
}
static void
update_bracket_match_style (GtkSourceBuffer *buffer)
{
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
GtkSourceStyle *style = NULL;
- if (buffer->priv->bracket_match_tag == NULL)
+ if (priv->bracket_match_tag == NULL)
{
return;
}
- if (buffer->priv->style_scheme != NULL)
+ if (priv->style_scheme != NULL)
{
- style = _gtk_source_style_scheme_get_matching_brackets_style (buffer->priv->style_scheme);
+ style = _gtk_source_style_scheme_get_matching_brackets_style (priv->style_scheme);
}
- gtk_source_style_apply (style, buffer->priv->bracket_match_tag);
+ gtk_source_style_apply (style, priv->bracket_match_tag);
}
static GtkTextTag *
get_bracket_match_tag (GtkSourceBuffer *buffer)
{
- if (buffer->priv->bracket_match_tag == NULL)
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
+ if (priv->bracket_match_tag == NULL)
{
- buffer->priv->bracket_match_tag =
+ priv->bracket_match_tag =
gtk_text_buffer_create_tag (GTK_TEXT_BUFFER (buffer),
NULL,
NULL);
update_bracket_match_style (buffer);
}
- return buffer->priv->bracket_match_tag;
+ return priv->bracket_match_tag;
}
/* This is private, just used by the print compositor to not print bracket
@@ -912,7 +743,9 @@ get_bracket_match_tag (GtkSourceBuffer *buffer)
GtkTextTag *
_gtk_source_buffer_get_bracket_match_tag (GtkSourceBuffer *buffer)
{
- return buffer->priv->bracket_match_tag;
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
+ return priv->bracket_match_tag;
}
static gunichar
@@ -1059,15 +892,14 @@ remove_tag_with_minimal_damage (GtkTextBuffer *buffer,
static void
update_bracket_highlighting (GtkSourceBuffer *source_buffer)
{
- GtkTextBuffer *buffer;
+ GtkTextBuffer *buffer = GTK_TEXT_BUFFER (source_buffer);
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (source_buffer);
GtkTextIter insert_iter;
GtkTextIter bracket;
GtkTextIter bracket_match;
GtkSourceBracketMatchType previous_state;
- buffer = GTK_TEXT_BUFFER (source_buffer);
-
- if (source_buffer->priv->bracket_match_tag != NULL)
+ if (priv->bracket_match_tag != NULL)
{
GtkTextIter start;
GtkTextIter end;
@@ -1075,20 +907,20 @@ update_bracket_highlighting (GtkSourceBuffer *source_buffer)
gtk_text_buffer_get_bounds (buffer, &start, &end);
remove_tag_with_minimal_damage (GTK_TEXT_BUFFER (source_buffer),
- source_buffer->priv->bracket_match_tag,
+ priv->bracket_match_tag,
&start,
&end);
}
- if (!source_buffer->priv->highlight_brackets)
+ if (!priv->highlight_brackets)
{
- if (source_buffer->priv->bracket_match_tag != NULL)
+ if (priv->bracket_match_tag != NULL)
{
GtkTextTagTable *table;
table = gtk_text_buffer_get_tag_table (buffer);
- gtk_text_tag_table_remove (table, source_buffer->priv->bracket_match_tag);
- source_buffer->priv->bracket_match_tag = NULL;
+ gtk_text_tag_table_remove (table, priv->bracket_match_tag);
+ priv->bracket_match_tag = NULL;
}
return;
@@ -1098,14 +930,14 @@ update_bracket_highlighting (GtkSourceBuffer *source_buffer)
&insert_iter,
gtk_text_buffer_get_insert (buffer));
- previous_state = source_buffer->priv->bracket_match_state;
- source_buffer->priv->bracket_match_state =
+ previous_state = priv->bracket_match_state;
+ priv->bracket_match_state =
_gtk_source_buffer_find_bracket_match (source_buffer,
&insert_iter,
&bracket,
&bracket_match);
- if (source_buffer->priv->bracket_match_state == GTK_SOURCE_BRACKET_MATCH_FOUND)
+ if (priv->bracket_match_state == GTK_SOURCE_BRACKET_MATCH_FOUND)
{
GtkTextIter next_iter;
@@ -1135,13 +967,13 @@ update_bracket_highlighting (GtkSourceBuffer *source_buffer)
* positions are nonbrackets.
*/
if (previous_state != GTK_SOURCE_BRACKET_MATCH_NONE ||
- source_buffer->priv->bracket_match_state != GTK_SOURCE_BRACKET_MATCH_NONE)
+ priv->bracket_match_state != GTK_SOURCE_BRACKET_MATCH_NONE)
{
g_signal_emit (source_buffer,
buffer_signals[BRACKET_MATCHED],
0,
NULL,
- source_buffer->priv->bracket_match_state);
+ priv->bracket_match_state);
}
}
@@ -1149,19 +981,22 @@ static gboolean
bracket_highlighting_timeout_cb (gpointer user_data)
{
GtkSourceBuffer *buffer = GTK_SOURCE_BUFFER (user_data);
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
update_bracket_highlighting (buffer);
- buffer->priv->bracket_highlighting_timeout_id = 0;
+ priv->bracket_highlighting_timeout_id = 0;
return G_SOURCE_REMOVE;
}
static void
queue_bracket_highlighting_update (GtkSourceBuffer *buffer)
{
- if (buffer->priv->bracket_highlighting_timeout_id != 0)
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
+ if (priv->bracket_highlighting_timeout_id != 0)
{
- g_source_remove (buffer->priv->bracket_highlighting_timeout_id);
+ g_source_remove (priv->bracket_highlighting_timeout_id);
}
/* Queue an update to the bracket location instead of doing it
@@ -1181,12 +1016,12 @@ queue_bracket_highlighting_update (GtkSourceBuffer *buffer)
* If we had access to a GdkFrameClock, we might consider using
* ::update() or ::after-paint() to synchronize this.
*/
- buffer->priv->bracket_highlighting_timeout_id =
- gdk_threads_add_timeout_full (G_PRIORITY_LOW,
- UPDATE_BRACKET_DELAY,
- bracket_highlighting_timeout_cb,
- buffer,
- NULL);
+ priv->bracket_highlighting_timeout_id =
+ g_timeout_add_full (G_PRIORITY_LOW,
+ UPDATE_BRACKET_DELAY,
+ bracket_highlighting_timeout_cb,
+ buffer,
+ NULL);
}
/* Although this function is not really useful
@@ -1197,6 +1032,8 @@ static void
cursor_moved (GtkSourceBuffer *buffer)
{
queue_bracket_highlighting_update (buffer);
+
+ g_signal_emit (buffer, buffer_signals[CURSOR_MOVED], 0);
}
static void
@@ -1213,12 +1050,13 @@ gtk_source_buffer_content_inserted (GtkTextBuffer *buffer,
gint end_offset)
{
GtkSourceBuffer *source_buffer = GTK_SOURCE_BUFFER (buffer);
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (source_buffer);
cursor_moved (source_buffer);
- if (source_buffer->priv->highlight_engine != NULL)
+ if (priv->highlight_engine != NULL)
{
- _gtk_source_engine_text_inserted (source_buffer->priv->highlight_engine,
+ _gtk_source_engine_text_inserted (priv->highlight_engine,
start_offset,
end_offset);
}
@@ -1251,14 +1089,14 @@ gtk_source_buffer_real_insert_text (GtkTextBuffer *buffer,
gtk_text_iter_get_offset (iter));
}
-/* insert_pixbuf and insert_child_anchor do nothing except notifying
+/* insert_paintable and insert_child_anchor do nothing except notifying
* the highlighting engine about the change, because engine's idea
* of buffer char count must be correct at all times.
*/
static void
-gtk_source_buffer_real_insert_pixbuf (GtkTextBuffer *buffer,
- GtkTextIter *iter,
- GdkPixbuf *pixbuf)
+gtk_source_buffer_real_insert_paintable (GtkTextBuffer *buffer,
+ GtkTextIter *iter,
+ GdkPaintable *paintable)
{
gint start_offset;
@@ -1273,7 +1111,7 @@ gtk_source_buffer_real_insert_pixbuf (GtkTextBuffer *buffer,
* default signal handler revalidates it to point to the end of the
* inserted text.
*/
- GTK_TEXT_BUFFER_CLASS (gtk_source_buffer_parent_class)->insert_pixbuf (buffer, iter, pixbuf);
+ GTK_TEXT_BUFFER_CLASS (gtk_source_buffer_parent_class)->insert_paintable (buffer, iter, paintable);
gtk_source_buffer_content_inserted (buffer,
start_offset,
@@ -1311,6 +1149,7 @@ gtk_source_buffer_real_delete_range (GtkTextBuffer *buffer,
{
gint offset, length;
GtkSourceBuffer *source_buffer = GTK_SOURCE_BUFFER (buffer);
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (source_buffer);
g_return_if_fail (GTK_SOURCE_IS_BUFFER (buffer));
g_return_if_fail (start != NULL);
@@ -1327,9 +1166,9 @@ gtk_source_buffer_real_delete_range (GtkTextBuffer *buffer,
cursor_moved (source_buffer);
/* emit text deleted for engines */
- if (source_buffer->priv->highlight_engine != NULL)
+ if (priv->highlight_engine != NULL)
{
- _gtk_source_engine_text_deleted (source_buffer->priv->highlight_engine,
+ _gtk_source_engine_text_deleted (priv->highlight_engine,
offset, length);
}
}
@@ -1525,181 +1364,6 @@ _gtk_source_buffer_find_bracket_match (GtkSourceBuffer *buffer,
return result_right;
}
-/**
- * gtk_source_buffer_can_undo:
- * @buffer: a #GtkSourceBuffer.
- *
- * Determines whether a source buffer can undo the last action.
- *
- * Returns: %TRUE if it's possible to undo the last action.
- */
-gboolean
-gtk_source_buffer_can_undo (GtkSourceBuffer *buffer)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_BUFFER (buffer), FALSE);
-
- return gtk_source_undo_manager_can_undo (buffer->priv->undo_manager);
-}
-
-/**
- * gtk_source_buffer_can_redo:
- * @buffer: a #GtkSourceBuffer.
- *
- * Determines whether a source buffer can redo the last action
- * (i.e. if the last operation was an undo).
- *
- * Returns: %TRUE if a redo is possible.
- */
-gboolean
-gtk_source_buffer_can_redo (GtkSourceBuffer *buffer)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_BUFFER (buffer), FALSE);
-
- return gtk_source_undo_manager_can_redo (buffer->priv->undo_manager);
-}
-
-/**
- * gtk_source_buffer_undo:
- * @buffer: a #GtkSourceBuffer.
- *
- * Undoes the last user action which modified the buffer. Use
- * gtk_source_buffer_can_undo() to check whether a call to this
- * function will have any effect.
- *
- * This function emits the #GtkSourceBuffer::undo signal.
- */
-void
-gtk_source_buffer_undo (GtkSourceBuffer *buffer)
-{
- g_return_if_fail (GTK_SOURCE_IS_BUFFER (buffer));
-
- g_signal_emit (buffer, buffer_signals[UNDO], 0);
-}
-
-/**
- * gtk_source_buffer_redo:
- * @buffer: a #GtkSourceBuffer.
- *
- * Redoes the last undo operation. Use gtk_source_buffer_can_redo()
- * to check whether a call to this function will have any effect.
- *
- * This function emits the #GtkSourceBuffer::redo signal.
- */
-void
-gtk_source_buffer_redo (GtkSourceBuffer *buffer)
-{
- g_return_if_fail (GTK_SOURCE_IS_BUFFER (buffer));
-
- g_signal_emit (buffer, buffer_signals[REDO], 0);
-}
-
-/**
- * gtk_source_buffer_get_max_undo_levels:
- * @buffer: a #GtkSourceBuffer.
- *
- * Determines the number of undo levels the buffer will track for buffer edits.
- *
- * Returns: the maximum number of possible undo levels or -1 if no limit is set.
- */
-gint
-gtk_source_buffer_get_max_undo_levels (GtkSourceBuffer *buffer)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_BUFFER (buffer), 0);
-
- return buffer->priv->max_undo_levels;
-}
-
-/**
- * gtk_source_buffer_set_max_undo_levels:
- * @buffer: a #GtkSourceBuffer.
- * @max_undo_levels: the desired maximum number of undo levels.
- *
- * Sets the number of undo levels for user actions the buffer will
- * track. If the number of user actions exceeds the limit set by this
- * function, older actions will be discarded.
- *
- * If @max_undo_levels is -1, the undo/redo is unlimited.
- *
- * If @max_undo_levels is 0, the undo/redo is disabled.
- */
-void
-gtk_source_buffer_set_max_undo_levels (GtkSourceBuffer *buffer,
- gint max_undo_levels)
-{
- g_return_if_fail (GTK_SOURCE_IS_BUFFER (buffer));
-
- if (buffer->priv->max_undo_levels == max_undo_levels)
- {
- return;
- }
-
- buffer->priv->max_undo_levels = max_undo_levels;
-
- if (GTK_SOURCE_IS_UNDO_MANAGER_DEFAULT (buffer->priv->undo_manager))
- {
- gtk_source_undo_manager_default_set_max_undo_levels (GTK_SOURCE_UNDO_MANAGER_DEFAULT (buffer->priv->undo_manager),
- max_undo_levels);
- }
-
- g_object_notify_by_pspec (G_OBJECT (buffer), buffer_properties[PROP_MAX_UNDO_LEVELS]);
-}
-
-gboolean
-_gtk_source_buffer_is_undo_redo_enabled (GtkSourceBuffer *buffer)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_BUFFER (buffer), FALSE);
-
- if (buffer->priv->undo_manager == NULL)
- {
- return FALSE;
- }
-
- /* A custom UndoManager is not forced to follow max_undo_levels. */
- if (!GTK_SOURCE_IS_UNDO_MANAGER_DEFAULT (buffer->priv->undo_manager))
- {
- return TRUE;
- }
-
- return buffer->priv->max_undo_levels != 0;
-}
-
-/**
- * gtk_source_buffer_begin_not_undoable_action:
- * @buffer: a #GtkSourceBuffer.
- *
- * Marks the beginning of a not undoable action on the buffer,
- * disabling the undo manager. Typically you would call this function
- * before initially setting the contents of the buffer (e.g. when
- * loading a file in a text editor).
- *
- * You may nest gtk_source_buffer_begin_not_undoable_action() /
- * gtk_source_buffer_end_not_undoable_action() blocks.
- */
-void
-gtk_source_buffer_begin_not_undoable_action (GtkSourceBuffer *buffer)
-{
- g_return_if_fail (GTK_SOURCE_IS_BUFFER (buffer));
-
- gtk_source_undo_manager_begin_not_undoable_action (buffer->priv->undo_manager);
-}
-
-/**
- * gtk_source_buffer_end_not_undoable_action:
- * @buffer: a #GtkSourceBuffer.
- *
- * Marks the end of a not undoable action on the buffer. When the
- * last not undoable block is closed through the call to this
- * function, the list of undo actions is cleared and the undo manager
- * is re-enabled.
- */
-void
-gtk_source_buffer_end_not_undoable_action (GtkSourceBuffer *buffer)
-{
- g_return_if_fail (GTK_SOURCE_IS_BUFFER (buffer));
-
- gtk_source_undo_manager_end_not_undoable_action (buffer->priv->undo_manager);
-}
-
/**
* gtk_source_buffer_get_highlight_matching_brackets:
* @buffer: a #GtkSourceBuffer.
@@ -1713,9 +1377,11 @@ gtk_source_buffer_end_not_undoable_action (GtkSourceBuffer *buffer)
gboolean
gtk_source_buffer_get_highlight_matching_brackets (GtkSourceBuffer *buffer)
{
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
g_return_val_if_fail (GTK_SOURCE_IS_BUFFER (buffer), FALSE);
- return buffer->priv->highlight_brackets;
+ return priv->highlight_brackets;
}
/**
@@ -1732,13 +1398,15 @@ void
gtk_source_buffer_set_highlight_matching_brackets (GtkSourceBuffer *buffer,
gboolean highlight)
{
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
g_return_if_fail (GTK_SOURCE_IS_BUFFER (buffer));
highlight = highlight != FALSE;
- if (highlight != buffer->priv->highlight_brackets)
+ if (highlight != priv->highlight_brackets)
{
- buffer->priv->highlight_brackets = highlight;
+ priv->highlight_brackets = highlight;
update_bracket_highlighting (buffer);
@@ -1758,9 +1426,11 @@ gtk_source_buffer_set_highlight_matching_brackets (GtkSourceBuffer *buffer,
gboolean
gtk_source_buffer_get_highlight_syntax (GtkSourceBuffer *buffer)
{
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
g_return_val_if_fail (GTK_SOURCE_IS_BUFFER (buffer), FALSE);
- return buffer->priv->highlight_syntax;
+ return priv->highlight_syntax;
}
/**
@@ -1782,13 +1452,15 @@ void
gtk_source_buffer_set_highlight_syntax (GtkSourceBuffer *buffer,
gboolean highlight)
{
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
g_return_if_fail (GTK_SOURCE_IS_BUFFER (buffer));
highlight = highlight != FALSE;
- if (buffer->priv->highlight_syntax != highlight)
+ if (priv->highlight_syntax != highlight)
{
- buffer->priv->highlight_syntax = highlight;
+ priv->highlight_syntax = highlight;
g_object_notify_by_pspec (G_OBJECT (buffer), buffer_properties[PROP_HIGHLIGHT_SYNTAX]);
}
}
@@ -1810,36 +1482,38 @@ void
gtk_source_buffer_set_language (GtkSourceBuffer *buffer,
GtkSourceLanguage *language)
{
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
g_return_if_fail (GTK_SOURCE_IS_BUFFER (buffer));
g_return_if_fail (GTK_SOURCE_IS_LANGUAGE (language) || language == NULL);
- if (!g_set_object (&buffer->priv->language, language))
+ if (!g_set_object (&priv->language, language))
{
return;
}
- if (buffer->priv->highlight_engine != NULL)
+ if (priv->highlight_engine != NULL)
{
/* disconnect the old engine */
- _gtk_source_engine_attach_buffer (buffer->priv->highlight_engine, NULL);
- g_object_unref (buffer->priv->highlight_engine);
- buffer->priv->highlight_engine = NULL;
+ _gtk_source_engine_attach_buffer (priv->highlight_engine, NULL);
+ g_object_unref (priv->highlight_engine);
+ priv->highlight_engine = NULL;
}
if (language != NULL)
{
/* get a new engine */
- buffer->priv->highlight_engine = _gtk_source_language_create_engine (language);
+ priv->highlight_engine = _gtk_source_language_create_engine (language);
- if (buffer->priv->highlight_engine != NULL)
+ if (priv->highlight_engine != NULL)
{
- _gtk_source_engine_attach_buffer (buffer->priv->highlight_engine,
+ _gtk_source_engine_attach_buffer (priv->highlight_engine,
GTK_TEXT_BUFFER (buffer));
- if (buffer->priv->style_scheme != NULL)
+ if (priv->style_scheme != NULL)
{
- _gtk_source_engine_set_style_scheme (buffer->priv->highlight_engine,
- buffer->priv->style_scheme);
+ _gtk_source_engine_set_style_scheme (priv->highlight_engine,
+ priv->style_scheme);
}
}
}
@@ -1861,9 +1535,11 @@ gtk_source_buffer_set_language (GtkSourceBuffer *buffer,
GtkSourceLanguage *
gtk_source_buffer_get_language (GtkSourceBuffer *buffer)
{
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
g_return_val_if_fail (GTK_SOURCE_IS_BUFFER (buffer), NULL);
- return buffer->priv->language;
+ return priv->language;
}
/*
@@ -1881,11 +1557,13 @@ _gtk_source_buffer_update_syntax_highlight (GtkSourceBuffer *buffer,
const GtkTextIter *end,
gboolean synchronous)
{
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
g_return_if_fail (GTK_SOURCE_IS_BUFFER (buffer));
- if (buffer->priv->highlight_engine != NULL)
+ if (priv->highlight_engine != NULL)
{
- _gtk_source_engine_update_highlight (buffer->priv->highlight_engine,
+ _gtk_source_engine_update_highlight (priv->highlight_engine,
start,
end,
synchronous);
@@ -1898,11 +1576,12 @@ _gtk_source_buffer_update_search_highlight (GtkSourceBuffer *buffer,
const GtkTextIter *end,
gboolean synchronous)
{
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
GList *l;
g_return_if_fail (GTK_SOURCE_IS_BUFFER (buffer));
- for (l = buffer->priv->search_contexts; l != NULL; l = l->next)
+ for (l = priv->search_contexts; l != NULL; l = l->next)
{
GtkSourceSearchContext *search_context = l->data;
@@ -1961,16 +1640,18 @@ void
gtk_source_buffer_set_style_scheme (GtkSourceBuffer *buffer,
GtkSourceStyleScheme *scheme)
{
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
g_return_if_fail (GTK_SOURCE_IS_BUFFER (buffer));
g_return_if_fail (GTK_SOURCE_IS_STYLE_SCHEME (scheme) || scheme == NULL);
- if (g_set_object (&buffer->priv->style_scheme, scheme))
+ if (g_set_object (&priv->style_scheme, scheme))
{
update_bracket_match_style (buffer);
- if (buffer->priv->highlight_engine != NULL)
+ if (priv->highlight_engine != NULL)
{
- _gtk_source_engine_set_style_scheme (buffer->priv->highlight_engine, scheme);
+ _gtk_source_engine_set_style_scheme (priv->highlight_engine, scheme);
}
g_object_notify_by_pspec (G_OBJECT (buffer), buffer_properties[PROP_STYLE_SCHEME]);
@@ -1991,29 +1672,33 @@ gtk_source_buffer_set_style_scheme (GtkSourceBuffer *buffer,
GtkSourceStyleScheme *
gtk_source_buffer_get_style_scheme (GtkSourceBuffer *buffer)
{
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
g_return_val_if_fail (GTK_SOURCE_IS_BUFFER (buffer), NULL);
- return buffer->priv->style_scheme;
+ return priv->style_scheme;
}
static void
add_source_mark (GtkSourceBuffer *buffer,
GtkSourceMark *mark)
{
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
const gchar *category;
GtkSourceMarksSequence *seq;
- _gtk_source_marks_sequence_add (buffer->priv->all_source_marks,
+ _gtk_source_marks_sequence_add (priv->all_source_marks,
GTK_TEXT_MARK (mark));
category = gtk_source_mark_get_category (mark);
- seq = g_hash_table_lookup (buffer->priv->source_marks, category);
+ seq = g_hash_table_lookup (priv->source_marks, category);
if (seq == NULL)
{
seq = _gtk_source_marks_sequence_new (GTK_TEXT_BUFFER (buffer));
- g_hash_table_insert (buffer->priv->source_marks,
+ g_hash_table_insert (priv->source_marks,
g_strdup (category),
seq);
}
@@ -2048,15 +1733,16 @@ gtk_source_buffer_real_mark_deleted (GtkTextBuffer *buffer,
if (GTK_SOURCE_IS_MARK (mark))
{
GtkSourceBuffer *source_buffer = GTK_SOURCE_BUFFER (buffer);
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (source_buffer);
const gchar *category;
GtkSourceMarksSequence *seq;
category = gtk_source_mark_get_category (GTK_SOURCE_MARK (mark));
- seq = g_hash_table_lookup (source_buffer->priv->source_marks, category);
+ seq = g_hash_table_lookup (priv->source_marks, category);
if (_gtk_source_marks_sequence_is_empty (seq))
{
- g_hash_table_remove (source_buffer->priv->source_marks, category);
+ g_hash_table_remove (priv->source_marks, category);
}
g_signal_emit (buffer, buffer_signals[SOURCE_MARK_UPDATED], 0, mark);
@@ -2068,22 +1754,6 @@ gtk_source_buffer_real_mark_deleted (GtkTextBuffer *buffer,
}
}
-static void
-gtk_source_buffer_real_undo (GtkSourceBuffer *buffer)
-{
- g_return_if_fail (gtk_source_undo_manager_can_undo (buffer->priv->undo_manager));
-
- gtk_source_undo_manager_undo (buffer->priv->undo_manager);
-}
-
-static void
-gtk_source_buffer_real_redo (GtkSourceBuffer *buffer)
-{
- g_return_if_fail (gtk_source_undo_manager_can_redo (buffer->priv->undo_manager));
-
- gtk_source_undo_manager_redo (buffer->priv->undo_manager);
-}
-
/**
* gtk_source_buffer_create_source_mark:
* @buffer: a #GtkSourceBuffer.
@@ -2139,9 +1809,11 @@ static GtkSourceMarksSequence *
get_marks_sequence (GtkSourceBuffer *buffer,
const gchar *category)
{
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
return category == NULL ?
- buffer->priv->all_source_marks :
- g_hash_table_lookup (buffer->priv->source_marks, category);
+ priv->all_source_marks :
+ g_hash_table_lookup (priv->source_marks, category);
}
GtkSourceMark *
@@ -2382,11 +2054,13 @@ gtk_source_buffer_remove_source_marks (GtkSourceBuffer *buffer,
gboolean
_gtk_source_buffer_has_source_marks (GtkSourceBuffer *buffer)
{
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
g_return_val_if_fail (GTK_SOURCE_IS_BUFFER (buffer), FALSE);
- if (buffer->priv->all_source_marks != NULL)
+ if (priv->all_source_marks != NULL)
{
- return !_gtk_source_marks_sequence_is_empty (buffer->priv->all_source_marks);
+ return !_gtk_source_marks_sequence_is_empty (priv->all_source_marks);
}
return FALSE;
@@ -2584,6 +2258,7 @@ gtk_source_buffer_iter_backward_to_context_class_toggle (GtkSourceBuffer *buffer
void
_gtk_source_buffer_save_and_clear_selection (GtkSourceBuffer *buffer)
{
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
GtkTextBuffer *buf;
g_return_if_fail (GTK_SOURCE_IS_BUFFER (buffer));
@@ -2599,13 +2274,13 @@ _gtk_source_buffer_save_and_clear_selection (GtkSourceBuffer *buffer)
GtkTextIter insert_iter;
GtkTextIter selection_bound_iter;
- g_assert (buffer->priv->tmp_insert_mark == NULL);
- g_assert (buffer->priv->tmp_selection_bound_mark == NULL);
+ g_assert (priv->tmp_insert_mark == NULL);
+ g_assert (priv->tmp_selection_bound_mark == NULL);
gtk_text_buffer_get_iter_at_mark (buf, &insert_iter, gtk_text_buffer_get_insert (buf));
gtk_text_buffer_get_iter_at_mark (buf, &selection_bound_iter, gtk_text_buffer_get_selection_bound (buf));
- buffer->priv->tmp_insert_mark = gtk_text_buffer_create_mark (buf, NULL, &insert_iter, FALSE);
- buffer->priv->tmp_selection_bound_mark = gtk_text_buffer_create_mark (buf, NULL, &selection_bound_iter, FALSE);
+ priv->tmp_insert_mark = gtk_text_buffer_create_mark (buf, NULL, &insert_iter, FALSE);
+ priv->tmp_selection_bound_mark = gtk_text_buffer_create_mark (buf, NULL, &selection_bound_iter, FALSE);
gtk_text_buffer_place_cursor (buf, &insert_iter);
}
@@ -2614,10 +2289,12 @@ _gtk_source_buffer_save_and_clear_selection (GtkSourceBuffer *buffer)
void
_gtk_source_buffer_restore_selection (GtkSourceBuffer *buffer)
{
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
g_return_if_fail (GTK_SOURCE_IS_BUFFER (buffer));
- if (buffer->priv->tmp_insert_mark != NULL &&
- buffer->priv->tmp_selection_bound_mark != NULL)
+ if (priv->tmp_insert_mark != NULL &&
+ priv->tmp_selection_bound_mark != NULL)
{
GtkTextBuffer *buf;
GtkTextIter insert_iter;
@@ -2625,15 +2302,15 @@ _gtk_source_buffer_restore_selection (GtkSourceBuffer *buffer)
buf = GTK_TEXT_BUFFER (buffer);
- gtk_text_buffer_get_iter_at_mark (buf, &insert_iter, buffer->priv->tmp_insert_mark);
- gtk_text_buffer_get_iter_at_mark (buf, &selection_bound_iter, buffer->priv->tmp_selection_bound_mark);
+ gtk_text_buffer_get_iter_at_mark (buf, &insert_iter, priv->tmp_insert_mark);
+ gtk_text_buffer_get_iter_at_mark (buf, &selection_bound_iter, priv->tmp_selection_bound_mark);
gtk_text_buffer_select_range (buf, &insert_iter, &selection_bound_iter);
- gtk_text_buffer_delete_mark (buf, buffer->priv->tmp_insert_mark);
- gtk_text_buffer_delete_mark (buf, buffer->priv->tmp_selection_bound_mark);
- buffer->priv->tmp_insert_mark = NULL;
- buffer->priv->tmp_selection_bound_mark = NULL;
+ gtk_text_buffer_delete_mark (buf, priv->tmp_insert_mark);
+ gtk_text_buffer_delete_mark (buf, priv->tmp_selection_bound_mark);
+ priv->tmp_insert_mark = NULL;
+ priv->tmp_selection_bound_mark = NULL;
}
}
@@ -3138,72 +2815,22 @@ gtk_source_buffer_sort_lines (GtkSourceBuffer *buffer,
g_free (lines);
}
-/**
- * gtk_source_buffer_set_undo_manager:
- * @buffer: a #GtkSourceBuffer.
- * @manager: (nullable): A #GtkSourceUndoManager or %NULL.
- *
- * Set the buffer undo manager. If @manager is %NULL the default undo manager
- * will be set.
- */
-void
-gtk_source_buffer_set_undo_manager (GtkSourceBuffer *buffer,
- GtkSourceUndoManager *manager)
-{
- g_return_if_fail (GTK_SOURCE_IS_BUFFER (buffer));
- g_return_if_fail (manager == NULL || GTK_SOURCE_IS_UNDO_MANAGER (manager));
-
- if (manager == NULL)
- {
- manager = g_object_new (GTK_SOURCE_TYPE_UNDO_MANAGER_DEFAULT,
- "buffer", buffer,
- "max-undo-levels", buffer->priv->max_undo_levels,
- NULL);
- }
- else
- {
- g_object_ref (manager);
- }
-
- set_undo_manager (buffer, manager);
- g_object_unref (manager);
-
- g_object_notify_by_pspec (G_OBJECT (buffer), buffer_properties[PROP_UNDO_MANAGER]);
-}
-
-/**
- * gtk_source_buffer_get_undo_manager:
- * @buffer: a #GtkSourceBuffer.
- *
- * Returns the #GtkSourceUndoManager associated with the buffer,
- * see gtk_source_buffer_set_undo_manager(). The returned object should not be
- * unreferenced by the user.
- *
- * Returns: (nullable) (transfer none): the #GtkSourceUndoManager associated
- * with the buffer, or %NULL.
- */
-GtkSourceUndoManager *
-gtk_source_buffer_get_undo_manager (GtkSourceBuffer *buffer)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_BUFFER (buffer), NULL);
-
- return buffer->priv->undo_manager;
-}
-
void
_gtk_source_buffer_add_search_context (GtkSourceBuffer *buffer,
GtkSourceSearchContext *search_context)
{
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
g_return_if_fail (GTK_SOURCE_IS_BUFFER (buffer));
g_return_if_fail (GTK_SOURCE_IS_SEARCH_CONTEXT (search_context));
g_return_if_fail (gtk_source_search_context_get_buffer (search_context) == buffer);
- if (g_list_find (buffer->priv->search_contexts, search_context) != NULL)
+ if (g_list_find (priv->search_contexts, search_context) != NULL)
{
return;
}
- buffer->priv->search_contexts = g_list_prepend (buffer->priv->search_contexts,
+ priv->search_contexts = g_list_prepend (priv->search_contexts,
search_context);
g_object_weak_ref (G_OBJECT (search_context),
@@ -3216,14 +2843,15 @@ sync_invalid_char_tag (GtkSourceBuffer *buffer,
GParamSpec *pspec,
gpointer data)
{
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
GtkSourceStyle *style = NULL;
- if (buffer->priv->style_scheme != NULL)
+ if (priv->style_scheme != NULL)
{
- style = gtk_source_style_scheme_get_style (buffer->priv->style_scheme, "def:error");
+ style = gtk_source_style_scheme_get_style (priv->style_scheme, "def:error");
}
- gtk_source_style_apply (style, buffer->priv->invalid_char_tag);
+ gtk_source_style_apply (style, priv->invalid_char_tag);
}
static void
@@ -3243,9 +2871,11 @@ _gtk_source_buffer_set_as_invalid_character (GtkSourceBuffer *buffer,
const GtkTextIter *start,
const GtkTextIter *end)
{
- if (buffer->priv->invalid_char_tag == NULL)
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
+ if (priv->invalid_char_tag == NULL)
{
- buffer->priv->invalid_char_tag = gtk_text_buffer_create_tag (GTK_TEXT_BUFFER (buffer),
+ priv->invalid_char_tag = gtk_text_buffer_create_tag (GTK_TEXT_BUFFER (buffer),
"invalid-char-style",
NULL);
@@ -3260,11 +2890,11 @@ _gtk_source_buffer_set_as_invalid_character (GtkSourceBuffer *buffer,
/* Make sure the 'error' tag has the priority over
* syntax highlighting tags.
*/
- text_tag_set_highest_priority (buffer->priv->invalid_char_tag,
+ text_tag_set_highest_priority (priv->invalid_char_tag,
GTK_TEXT_BUFFER (buffer));
gtk_text_buffer_apply_tag (GTK_TEXT_BUFFER (buffer),
- buffer->priv->invalid_char_tag,
+ priv->invalid_char_tag,
start,
end);
}
@@ -3272,19 +2902,20 @@ _gtk_source_buffer_set_as_invalid_character (GtkSourceBuffer *buffer,
gboolean
_gtk_source_buffer_has_invalid_chars (GtkSourceBuffer *buffer)
{
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
GtkTextIter start;
g_return_val_if_fail (GTK_SOURCE_IS_BUFFER (buffer), FALSE);
- if (buffer->priv->invalid_char_tag == NULL)
+ if (priv->invalid_char_tag == NULL)
{
return FALSE;
}
gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
- if (gtk_text_iter_starts_tag (&start, buffer->priv->invalid_char_tag) ||
- gtk_text_iter_forward_to_tag_toggle (&start, buffer->priv->invalid_char_tag))
+ if (gtk_text_iter_starts_tag (&start, priv->invalid_char_tag) ||
+ gtk_text_iter_forward_to_tag_toggle (&start, priv->invalid_char_tag))
{
return TRUE;
}
@@ -3319,13 +2950,15 @@ void
gtk_source_buffer_set_implicit_trailing_newline (GtkSourceBuffer *buffer,
gboolean implicit_trailing_newline)
{
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
g_return_if_fail (GTK_SOURCE_IS_BUFFER (buffer));
implicit_trailing_newline = implicit_trailing_newline != FALSE;
- if (buffer->priv->implicit_trailing_newline != implicit_trailing_newline)
+ if (priv->implicit_trailing_newline != implicit_trailing_newline)
{
- buffer->priv->implicit_trailing_newline = implicit_trailing_newline;
+ priv->implicit_trailing_newline = implicit_trailing_newline;
g_object_notify_by_pspec (G_OBJECT (buffer), buffer_properties[PROP_IMPLICIT_TRAILING_NEWLINE]);
}
}
@@ -3340,9 +2973,11 @@ gtk_source_buffer_set_implicit_trailing_newline (GtkSourceBuffer *buffer,
gboolean
gtk_source_buffer_get_implicit_trailing_newline (GtkSourceBuffer *buffer)
{
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
g_return_val_if_fail (GTK_SOURCE_IS_BUFFER (buffer), TRUE);
- return buffer->priv->implicit_trailing_newline;
+ return priv->implicit_trailing_newline;
}
/**
@@ -3407,7 +3042,9 @@ gtk_source_buffer_create_source_tag (GtkSourceBuffer *buffer,
gboolean
_gtk_source_buffer_has_spaces_tag (GtkSourceBuffer *buffer)
{
+ GtkSourceBufferPrivate *priv = gtk_source_buffer_get_instance_private (buffer);
+
g_return_val_if_fail (GTK_SOURCE_IS_BUFFER (buffer), FALSE);
- return buffer->priv->has_draw_spaces_tag;
+ return priv->has_draw_spaces_tag;
}
diff --git a/gtksourceview/gtksourcebuffer.h b/gtksourceview/gtksourcebuffer.h
index 09143a87a689235ef8f72c9dda79d255db15975d..5f6b068b78865093edbef2778ebce12f530480bd 100644
--- a/gtksourceview/gtksourcebuffer.h
+++ b/gtksourceview/gtksourcebuffer.h
@@ -1,12 +1,11 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
- *
+/*
* This file is part of GtkSourceView
*
- * Copyright (C) 1999-2002 - Mikael Hermansson ,
- * Chris Phelps and
- * Jeroen Zwartepoorte
- * Copyright (C) 2003 - Paolo Maggi, Gustavo Giráldez
- * Copyright (C) 2014 - Sébastien Wilmet
+ * Copyright 1999-2002 - Mikael Hermansson ,
+ * Chris Phelps and
+ * Jeroen Zwartepoorte
+ * Copyright 2003 - Paolo Maggi, Gustavo Giráldez
+ * Copyright 2014 - Sébastien Wilmet
*
* GtkSourceView is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -22,27 +21,22 @@
* along with this library; if not, see .
*/
-#ifndef GTK_SOURCE_BUFFER_H
-#define GTK_SOURCE_BUFFER_H
+#pragma once
#if !defined (GTK_SOURCE_H_INSIDE) && !defined (GTK_SOURCE_COMPILATION)
#error "Only can be included directly."
#endif
#include
-#include
+
+#include "gtksourcetypes.h"
G_BEGIN_DECLS
-#define GTK_SOURCE_TYPE_BUFFER (gtk_source_buffer_get_type ())
-#define GTK_SOURCE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_SOURCE_TYPE_BUFFER, GtkSourceBuffer))
-#define GTK_SOURCE_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_SOURCE_TYPE_BUFFER, GtkSourceBufferClass))
-#define GTK_SOURCE_IS_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_SOURCE_TYPE_BUFFER))
-#define GTK_SOURCE_IS_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_SOURCE_TYPE_BUFFER))
-#define GTK_SOURCE_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_SOURCE_TYPE_BUFFER, GtkSourceBufferClass))
+#define GTK_SOURCE_TYPE_BUFFER (gtk_source_buffer_get_type())
-typedef struct _GtkSourceBufferClass GtkSourceBufferClass;
-typedef struct _GtkSourceBufferPrivate GtkSourceBufferPrivate;
+GTK_SOURCE_AVAILABLE_IN_ALL
+G_DECLARE_DERIVABLE_TYPE (GtkSourceBuffer, gtk_source_buffer, GTK_SOURCE, BUFFER, GtkTextBuffer)
/**
* GtkSourceBracketMatchType:
@@ -94,186 +88,113 @@ typedef enum _GtkSourceSortFlags
GTK_SOURCE_SORT_FLAGS_REMOVE_DUPLICATES = 1 << 2,
} GtkSourceSortFlags;
-struct _GtkSourceBuffer
-{
- GtkTextBuffer parent_instance;
-
- GtkSourceBufferPrivate *priv;
-};
-
struct _GtkSourceBufferClass
{
GtkTextBufferClass parent_class;
/* Signals */
- void (*undo) (GtkSourceBuffer *buffer);
- void (*redo) (GtkSourceBuffer *buffer);
-
void (*bracket_matched) (GtkSourceBuffer *buffer,
- GtkTextIter *iter,
- GtkSourceBracketMatchType state);
+ GtkTextIter *iter,
+ GtkSourceBracketMatchType state);
- /* Padding for future expansion */
- gpointer padding[20];
+ /*< private >*/
+ gpointer _reserved[20];
};
GTK_SOURCE_AVAILABLE_IN_ALL
-GType gtk_source_buffer_get_type (void) G_GNUC_CONST;
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-GtkSourceBuffer *gtk_source_buffer_new (GtkTextTagTable *table);
-
+GtkSourceBuffer *gtk_source_buffer_new (GtkTextTagTable *table);
GTK_SOURCE_AVAILABLE_IN_ALL
-GtkSourceBuffer *gtk_source_buffer_new_with_language (GtkSourceLanguage *language);
-
+GtkSourceBuffer *gtk_source_buffer_new_with_language (GtkSourceLanguage *language);
GTK_SOURCE_AVAILABLE_IN_ALL
-gboolean gtk_source_buffer_get_highlight_syntax (GtkSourceBuffer *buffer);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_buffer_set_highlight_syntax (GtkSourceBuffer *buffer,
- gboolean highlight);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-gboolean gtk_source_buffer_get_highlight_matching_brackets (GtkSourceBuffer *buffer);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_buffer_set_highlight_matching_brackets (GtkSourceBuffer *buffer,
- gboolean highlight);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-gint gtk_source_buffer_get_max_undo_levels (GtkSourceBuffer *buffer);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_buffer_set_max_undo_levels (GtkSourceBuffer *buffer,
- gint max_undo_levels);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-GtkSourceLanguage *gtk_source_buffer_get_language (GtkSourceBuffer *buffer);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_buffer_set_language (GtkSourceBuffer *buffer,
- GtkSourceLanguage *language);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-gboolean gtk_source_buffer_can_undo (GtkSourceBuffer *buffer);
-
+gboolean gtk_source_buffer_get_highlight_syntax (GtkSourceBuffer *buffer);
GTK_SOURCE_AVAILABLE_IN_ALL
-gboolean gtk_source_buffer_can_redo (GtkSourceBuffer *buffer);
-
+void gtk_source_buffer_set_highlight_syntax (GtkSourceBuffer *buffer,
+ gboolean highlight);
GTK_SOURCE_AVAILABLE_IN_ALL
-GtkSourceStyleScheme *gtk_source_buffer_get_style_scheme (GtkSourceBuffer *buffer);
-
+gboolean gtk_source_buffer_get_highlight_matching_brackets (GtkSourceBuffer *buffer);
GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_buffer_set_style_scheme (GtkSourceBuffer *buffer,
- GtkSourceStyleScheme *scheme);
-
+void gtk_source_buffer_set_highlight_matching_brackets (GtkSourceBuffer *buffer,
+ gboolean highlight);
GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_buffer_ensure_highlight (GtkSourceBuffer *buffer,
- const GtkTextIter *start,
- const GtkTextIter *end);
-
+GtkSourceLanguage *gtk_source_buffer_get_language (GtkSourceBuffer *buffer);
GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_buffer_undo (GtkSourceBuffer *buffer);
-
+void gtk_source_buffer_set_language (GtkSourceBuffer *buffer,
+ GtkSourceLanguage *language);
GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_buffer_redo (GtkSourceBuffer *buffer);
-
+GtkSourceStyleScheme *gtk_source_buffer_get_style_scheme (GtkSourceBuffer *buffer);
GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_buffer_begin_not_undoable_action (GtkSourceBuffer *buffer);
-
+void gtk_source_buffer_set_style_scheme (GtkSourceBuffer *buffer,
+ GtkSourceStyleScheme *scheme);
GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_buffer_end_not_undoable_action (GtkSourceBuffer *buffer);
-
+void gtk_source_buffer_ensure_highlight (GtkSourceBuffer *buffer,
+ const GtkTextIter *start,
+ const GtkTextIter *end);
GTK_SOURCE_AVAILABLE_IN_ALL
-GtkSourceMark *gtk_source_buffer_create_source_mark (GtkSourceBuffer *buffer,
- const gchar *name,
- const gchar *category,
- const GtkTextIter *where);
-
+GtkSourceMark *gtk_source_buffer_create_source_mark (GtkSourceBuffer *buffer,
+ const gchar *name,
+ const gchar *category,
+ const GtkTextIter *where);
GTK_SOURCE_AVAILABLE_IN_ALL
-gboolean gtk_source_buffer_forward_iter_to_source_mark (GtkSourceBuffer *buffer,
- GtkTextIter *iter,
- const gchar *category);
-
+gboolean gtk_source_buffer_forward_iter_to_source_mark (GtkSourceBuffer *buffer,
+ GtkTextIter *iter,
+ const gchar *category);
GTK_SOURCE_AVAILABLE_IN_ALL
-gboolean gtk_source_buffer_backward_iter_to_source_mark (GtkSourceBuffer *buffer,
- GtkTextIter *iter,
- const gchar *category);
-
+gboolean gtk_source_buffer_backward_iter_to_source_mark (GtkSourceBuffer *buffer,
+ GtkTextIter *iter,
+ const gchar *category);
GTK_SOURCE_AVAILABLE_IN_ALL
-GSList *gtk_source_buffer_get_source_marks_at_iter (GtkSourceBuffer *buffer,
- GtkTextIter *iter,
- const gchar *category);
-
+GSList *gtk_source_buffer_get_source_marks_at_iter (GtkSourceBuffer *buffer,
+ GtkTextIter *iter,
+ const gchar *category);
GTK_SOURCE_AVAILABLE_IN_ALL
-GSList *gtk_source_buffer_get_source_marks_at_line (GtkSourceBuffer *buffer,
- gint line,
- const gchar *category);
-
+GSList *gtk_source_buffer_get_source_marks_at_line (GtkSourceBuffer *buffer,
+ gint line,
+ const gchar *category);
GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_buffer_remove_source_marks (GtkSourceBuffer *buffer,
- const GtkTextIter *start,
- const GtkTextIter *end,
- const gchar *category);
-
+void gtk_source_buffer_remove_source_marks (GtkSourceBuffer *buffer,
+ const GtkTextIter *start,
+ const GtkTextIter *end,
+ const gchar *category);
GTK_SOURCE_AVAILABLE_IN_ALL
-gboolean gtk_source_buffer_iter_has_context_class (GtkSourceBuffer *buffer,
- const GtkTextIter *iter,
- const gchar *context_class);
-
+gboolean gtk_source_buffer_iter_has_context_class (GtkSourceBuffer *buffer,
+ const GtkTextIter *iter,
+ const gchar *context_class);
GTK_SOURCE_AVAILABLE_IN_ALL
-gchar **gtk_source_buffer_get_context_classes_at_iter (GtkSourceBuffer *buffer,
- const GtkTextIter *iter);
-
+gchar **gtk_source_buffer_get_context_classes_at_iter (GtkSourceBuffer *buffer,
+ const GtkTextIter *iter);
GTK_SOURCE_AVAILABLE_IN_ALL
-gboolean gtk_source_buffer_iter_forward_to_context_class_toggle (GtkSourceBuffer *buffer,
- GtkTextIter *iter,
- const gchar *context_class);
-
+gboolean gtk_source_buffer_iter_forward_to_context_class_toggle (GtkSourceBuffer *buffer,
+ GtkTextIter *iter,
+ const gchar *context_class);
GTK_SOURCE_AVAILABLE_IN_ALL
-gboolean gtk_source_buffer_iter_backward_to_context_class_toggle
- (GtkSourceBuffer *buffer,
- GtkTextIter *iter,
- const gchar *context_class);
-
+gboolean gtk_source_buffer_iter_backward_to_context_class_toggle (GtkSourceBuffer *buffer,
+ GtkTextIter *iter,
+ const gchar *context_class);
GTK_SOURCE_AVAILABLE_IN_3_12
-void gtk_source_buffer_change_case (GtkSourceBuffer *buffer,
- GtkSourceChangeCaseType case_type,
- GtkTextIter *start,
- GtkTextIter *end);
-
+void gtk_source_buffer_change_case (GtkSourceBuffer *buffer,
+ GtkSourceChangeCaseType case_type,
+ GtkTextIter *start,
+ GtkTextIter *end);
GTK_SOURCE_AVAILABLE_IN_3_16
-void gtk_source_buffer_join_lines (GtkSourceBuffer *buffer,
- GtkTextIter *start,
- GtkTextIter *end);
-
+void gtk_source_buffer_join_lines (GtkSourceBuffer *buffer,
+ GtkTextIter *start,
+ GtkTextIter *end);
GTK_SOURCE_AVAILABLE_IN_3_18
-void gtk_source_buffer_sort_lines (GtkSourceBuffer *buffer,
- GtkTextIter *start,
- GtkTextIter *end,
- GtkSourceSortFlags flags,
- gint column);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-GtkSourceUndoManager *gtk_source_buffer_get_undo_manager (GtkSourceBuffer *buffer);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_buffer_set_undo_manager (GtkSourceBuffer *buffer,
- GtkSourceUndoManager *manager);
-
+void gtk_source_buffer_sort_lines (GtkSourceBuffer *buffer,
+ GtkTextIter *start,
+ GtkTextIter *end,
+ GtkSourceSortFlags flags,
+ gint column);
GTK_SOURCE_AVAILABLE_IN_3_14
-void gtk_source_buffer_set_implicit_trailing_newline (GtkSourceBuffer *buffer,
- gboolean implicit_trailing_newline);
-
+void gtk_source_buffer_set_implicit_trailing_newline (GtkSourceBuffer *buffer,
+ gboolean implicit_trailing_newline);
GTK_SOURCE_AVAILABLE_IN_3_14
-gboolean gtk_source_buffer_get_implicit_trailing_newline (GtkSourceBuffer *buffer);
-
+gboolean gtk_source_buffer_get_implicit_trailing_newline (GtkSourceBuffer *buffer);
GTK_SOURCE_AVAILABLE_IN_ALL
-GtkTextTag *gtk_source_buffer_create_source_tag (GtkSourceBuffer *buffer,
- const gchar *tag_name,
- const gchar *first_property_name,
- ...);
+GtkTextTag *gtk_source_buffer_create_source_tag (GtkSourceBuffer *buffer,
+ const gchar *tag_name,
+ const gchar *first_property_name,
+ ...);
-G_END_DECLS
-#endif /* GTK_SOURCE_BUFFER_H */
+G_END_DECLS
diff --git a/gtksourceview/gtksourcebufferinputstream-private.h b/gtksourceview/gtksourcebufferinputstream-private.h
new file mode 100644
index 0000000000000000000000000000000000000000..965f8c6ceb276316a418a372027764764f3ca761
--- /dev/null
+++ b/gtksourceview/gtksourcebufferinputstream-private.h
@@ -0,0 +1,46 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2010 - Ignacio Casal Quinteiro
+ * Copyright 2014 - Sébastien Wilmet
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ */
+
+#pragma once
+
+#include
+#include
+
+#include "gtksourcetypes-private.h"
+#include "gtksourcebuffer.h"
+#include "gtksourcefile.h"
+
+G_BEGIN_DECLS
+
+#define GTK_SOURCE_TYPE_BUFFER_INPUT_STREAM (_gtk_source_buffer_input_stream_get_type())
+
+GTK_SOURCE_INTERNAL
+G_DECLARE_FINAL_TYPE (GtkSourceBufferInputStream, _gtk_source_buffer_input_stream, GTK_SOURCE, BUFFER_INPUT_STREAM, GInputStream)
+
+GTK_SOURCE_INTERNAL
+GtkSourceBufferInputStream *_gtk_source_buffer_input_stream_new (GtkTextBuffer *buffer,
+ GtkSourceNewlineType type,
+ gboolean add_trailing_newline);
+GTK_SOURCE_INTERNAL
+gsize _gtk_source_buffer_input_stream_get_total_size (GtkSourceBufferInputStream *stream);
+GTK_SOURCE_INTERNAL
+gsize _gtk_source_buffer_input_stream_tell (GtkSourceBufferInputStream *stream);
+
+G_END_DECLS
diff --git a/gtksourceview/gtksourcebufferinputstream.c b/gtksourceview/gtksourcebufferinputstream.c
index 1174222cecdde613703aa99e9598a97c249dec97..c8c2d9058275a2c5d0ffdbc49f8ed38b78dc90b0 100644
--- a/gtksourceview/gtksourcebufferinputstream.c
+++ b/gtksourceview/gtksourcebufferinputstream.c
@@ -1,9 +1,8 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- */
/*
* This file is part of GtkSourceView
*
- * Copyright (C) 2010 - Ignacio Casal Quinteiro
- * Copyright (C) 2014 - Sébastien Wilmet
+ * Copyright 2010 - Ignacio Casal Quinteiro
+ * Copyright 2014 - Sébastien Wilmet
*
* GtkSourceView is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -19,14 +18,13 @@
* along with this library; if not, see .
*/
-#ifdef HAVE_CONFIG_H
-#include
-#endif
+#include "config.h"
#include
#include
#include
-#include "gtksourcebufferinputstream.h"
+
+#include "gtksourcebufferinputstream-private.h"
#include "gtksource-enumtypes.h"
/* NOTE: never use async methods on this stream, the stream is just
@@ -36,8 +34,10 @@
* thread.
*/
-struct _GtkSourceBufferInputStreamPrivate
+struct _GtkSourceBufferInputStream
{
+ GInputStream parent_instance;
+
GtkTextBuffer *buffer;
GtkTextMark *pos;
gint bytes_partial;
@@ -57,12 +57,12 @@ enum
PROP_ADD_TRAILING_NEWLINE
};
-G_DEFINE_TYPE_WITH_PRIVATE (GtkSourceBufferInputStream, _gtk_source_buffer_input_stream, G_TYPE_INPUT_STREAM);
+G_DEFINE_TYPE (GtkSourceBufferInputStream, _gtk_source_buffer_input_stream, G_TYPE_INPUT_STREAM)
static gsize
get_new_line_size (GtkSourceBufferInputStream *stream)
{
- switch (stream->priv->newline_type)
+ switch (stream->newline_type)
{
case GTK_SOURCE_NEWLINE_TYPE_CR:
case GTK_SOURCE_NEWLINE_TYPE_LF:
@@ -82,7 +82,7 @@ get_new_line_size (GtkSourceBufferInputStream *stream)
static const gchar *
get_new_line (GtkSourceBufferInputStream *stream)
{
- switch (stream->priv->newline_type)
+ switch (stream->newline_type)
{
case GTK_SOURCE_NEWLINE_TYPE_LF:
return "\n";
@@ -103,8 +103,8 @@ get_new_line (GtkSourceBufferInputStream *stream)
static gsize
read_line (GtkSourceBufferInputStream *stream,
- gchar *outbuf,
- gsize space_left)
+ gchar *outbuf,
+ gsize space_left)
{
GtkTextIter start, next, end;
gchar *buf;
@@ -113,14 +113,14 @@ read_line (GtkSourceBufferInputStream *stream,
const gchar *newline;
gboolean is_last;
- if (stream->priv->buffer == NULL)
+ if (stream->buffer == NULL)
{
return 0;
}
- gtk_text_buffer_get_iter_at_mark (stream->priv->buffer,
+ gtk_text_buffer_get_iter_at_mark (stream->buffer,
&start,
- stream->priv->pos);
+ stream->pos);
if (gtk_text_iter_is_end (&start))
{
@@ -142,7 +142,7 @@ read_line (GtkSourceBufferInputStream *stream,
/* the bytes of a line includes also the newline, so with the
offsets we remove the newline and we add the new newline size */
- bytes = gtk_text_iter_get_bytes_in_line (&start) - stream->priv->bytes_partial;
+ bytes = gtk_text_iter_get_bytes_in_line (&start) - stream->bytes_partial;
/* bytes_in_line includes the newlines, so we remove that assuming that
they are single byte characters */
@@ -200,7 +200,7 @@ read_line (GtkSourceBufferInputStream *stream,
/* Note: offset is one past what we wrote */
gtk_text_iter_forward_chars (&start, char_offset);
- stream->priv->bytes_partial += written;
+ stream->bytes_partial += written;
read = written;
}
else
@@ -215,12 +215,12 @@ read_line (GtkSourceBufferInputStream *stream,
}
start = next;
- stream->priv->bytes_partial = 0;
+ stream->bytes_partial = 0;
read = bytes_to_write;
}
- gtk_text_buffer_move_mark (stream->priv->buffer,
- stream->priv->pos,
+ gtk_text_buffer_move_mark (stream->buffer,
+ stream->pos,
&start);
g_free (buf);
@@ -229,10 +229,10 @@ read_line (GtkSourceBufferInputStream *stream,
static gssize
_gtk_source_buffer_input_stream_read (GInputStream *input_stream,
- void *buffer,
- gsize count,
- GCancellable *cancellable,
- GError **error)
+ void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error)
{
GtkSourceBufferInputStream *stream;
GtkTextIter iter;
@@ -252,21 +252,21 @@ _gtk_source_buffer_input_stream_read (GInputStream *input_stream,
return -1;
}
- if (stream->priv->buffer == NULL)
+ if (stream->buffer == NULL)
{
return 0;
}
/* Initialize the mark to the first char in the text buffer */
- if (!stream->priv->is_initialized)
+ if (!stream->is_initialized)
{
- gtk_text_buffer_get_start_iter (stream->priv->buffer, &iter);
- stream->priv->pos = gtk_text_buffer_create_mark (stream->priv->buffer,
+ gtk_text_buffer_get_start_iter (stream->buffer, &iter);
+ stream->pos = gtk_text_buffer_create_mark (stream->buffer,
NULL,
&iter,
FALSE);
- stream->priv->is_initialized = TRUE;
+ stream->is_initialized = TRUE;
}
space_left = count;
@@ -277,24 +277,24 @@ _gtk_source_buffer_input_stream_read (GInputStream *input_stream,
n = read_line (stream, (gchar *)buffer + read, space_left);
read += n;
space_left -= n;
- } while (space_left > 0 && n != 0 && stream->priv->bytes_partial == 0);
+ } while (space_left > 0 && n != 0 && stream->bytes_partial == 0);
/* Make sure that non-empty files are always terminated with \n (see bug #95676).
* Note that we strip the trailing \n when loading the file */
- gtk_text_buffer_get_iter_at_mark (stream->priv->buffer,
+ gtk_text_buffer_get_iter_at_mark (stream->buffer,
&iter,
- stream->priv->pos);
+ stream->pos);
if (gtk_text_iter_is_end (&iter) &&
!gtk_text_iter_is_start (&iter) &&
- stream->priv->add_trailing_newline)
+ stream->add_trailing_newline)
{
gssize newline_size;
newline_size = get_new_line_size (stream);
if (space_left >= newline_size &&
- !stream->priv->newline_added)
+ !stream->newline_added)
{
const gchar *newline;
@@ -303,7 +303,7 @@ _gtk_source_buffer_input_stream_read (GInputStream *input_stream,
memcpy ((gchar *)buffer + read, newline, newline_size);
read += newline_size;
- stream->priv->newline_added = TRUE;
+ stream->newline_added = TRUE;
}
}
@@ -312,17 +312,17 @@ _gtk_source_buffer_input_stream_read (GInputStream *input_stream,
static gboolean
_gtk_source_buffer_input_stream_close (GInputStream *input_stream,
- GCancellable *cancellable,
- GError **error)
+ GCancellable *cancellable,
+ GError **error)
{
GtkSourceBufferInputStream *stream = GTK_SOURCE_BUFFER_INPUT_STREAM (input_stream);
- stream->priv->newline_added = FALSE;
+ stream->newline_added = FALSE;
- if (stream->priv->is_initialized &&
- stream->priv->buffer != NULL)
+ if (stream->is_initialized &&
+ stream->buffer != NULL)
{
- gtk_text_buffer_delete_mark (stream->priv->buffer, stream->priv->pos);
+ gtk_text_buffer_delete_mark (stream->buffer, stream->pos);
}
return TRUE;
@@ -330,25 +330,25 @@ _gtk_source_buffer_input_stream_close (GInputStream *input_stream,
static void
_gtk_source_buffer_input_stream_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
GtkSourceBufferInputStream *stream = GTK_SOURCE_BUFFER_INPUT_STREAM (object);
switch (prop_id)
{
case PROP_BUFFER:
- g_assert (stream->priv->buffer == NULL);
- stream->priv->buffer = g_value_dup_object (value);
+ g_assert (stream->buffer == NULL);
+ stream->buffer = g_value_dup_object (value);
break;
case PROP_NEWLINE_TYPE:
- stream->priv->newline_type = g_value_get_enum (value);
+ stream->newline_type = g_value_get_enum (value);
break;
case PROP_ADD_TRAILING_NEWLINE:
- stream->priv->add_trailing_newline = g_value_get_boolean (value);
+ stream->add_trailing_newline = g_value_get_boolean (value);
break;
default:
@@ -359,24 +359,24 @@ _gtk_source_buffer_input_stream_set_property (GObject *object,
static void
_gtk_source_buffer_input_stream_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
{
GtkSourceBufferInputStream *stream = GTK_SOURCE_BUFFER_INPUT_STREAM (object);
switch (prop_id)
{
case PROP_BUFFER:
- g_value_set_object (value, stream->priv->buffer);
+ g_value_set_object (value, stream->buffer);
break;
case PROP_NEWLINE_TYPE:
- g_value_set_enum (value, stream->priv->newline_type);
+ g_value_set_enum (value, stream->newline_type);
break;
case PROP_ADD_TRAILING_NEWLINE:
- g_value_set_boolean (value, stream->priv->add_trailing_newline);
+ g_value_set_boolean (value, stream->add_trailing_newline);
break;
default:
@@ -390,7 +390,7 @@ _gtk_source_buffer_input_stream_dispose (GObject *object)
{
GtkSourceBufferInputStream *stream = GTK_SOURCE_BUFFER_INPUT_STREAM (object);
- g_clear_object (&stream->priv->buffer);
+ g_clear_object (&stream->buffer);
G_OBJECT_CLASS (_gtk_source_buffer_input_stream_parent_class)->dispose (object);
}
@@ -455,7 +455,7 @@ _gtk_source_buffer_input_stream_class_init (GtkSourceBufferInputStreamClass *kla
static void
_gtk_source_buffer_input_stream_init (GtkSourceBufferInputStream *stream)
{
- stream->priv = _gtk_source_buffer_input_stream_get_instance_private (stream);
+ stream = _gtk_source_buffer_input_stream_get_instance_private (stream);
}
/**
@@ -468,8 +468,8 @@ _gtk_source_buffer_input_stream_init (GtkSourceBufferInputStream *stream)
*/
GtkSourceBufferInputStream *
_gtk_source_buffer_input_stream_new (GtkTextBuffer *buffer,
- GtkSourceNewlineType type,
- gboolean add_trailing_newline)
+ GtkSourceNewlineType type,
+ gboolean add_trailing_newline)
{
g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
@@ -485,12 +485,12 @@ _gtk_source_buffer_input_stream_get_total_size (GtkSourceBufferInputStream *stre
{
g_return_val_if_fail (GTK_SOURCE_IS_BUFFER_INPUT_STREAM (stream), 0);
- if (stream->priv->buffer == NULL)
+ if (stream->buffer == NULL)
{
return 0;
}
- return gtk_text_buffer_get_char_count (stream->priv->buffer);
+ return gtk_text_buffer_get_char_count (stream->buffer);
}
gsize
@@ -501,8 +501,8 @@ _gtk_source_buffer_input_stream_tell (GtkSourceBufferInputStream *stream)
/* FIXME: is this potentially inefficient? If yes, we could keep
track of the offset internally, assuming the mark doesn't move
during the operation */
- if (!stream->priv->is_initialized ||
- stream->priv->buffer == NULL)
+ if (!stream->is_initialized ||
+ stream->buffer == NULL)
{
return 0;
}
@@ -510,9 +510,9 @@ _gtk_source_buffer_input_stream_tell (GtkSourceBufferInputStream *stream)
{
GtkTextIter iter;
- gtk_text_buffer_get_iter_at_mark (stream->priv->buffer,
+ gtk_text_buffer_get_iter_at_mark (stream->buffer,
&iter,
- stream->priv->pos);
+ stream->pos);
return gtk_text_iter_get_offset (&iter);
}
}
diff --git a/gtksourceview/gtksourcebufferinputstream.h b/gtksourceview/gtksourcebufferinputstream.h
deleted file mode 100644
index f98cb64c6de503f32a683c5c8cb5d0b5876363f2..0000000000000000000000000000000000000000
--- a/gtksourceview/gtksourcebufferinputstream.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- */
-/*
- * This file is part of GtkSourceView
- *
- * Copyright (C) 2010 - Ignacio Casal Quinteiro
- * Copyright (C) 2014 - Sébastien Wilmet
- *
- * GtkSourceView is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * GtkSourceView 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, see .
- */
-
-#ifndef GTK_SOURCE_BUFFER_INPUT_STREAM_H
-#define GTK_SOURCE_BUFFER_INPUT_STREAM_H
-
-#include
-#include
-#include "gtksourcetypes-private.h"
-#include "gtksourcebuffer.h"
-#include "gtksourcefile.h"
-
-G_BEGIN_DECLS
-
-#define GTK_SOURCE_TYPE_BUFFER_INPUT_STREAM (_gtk_source_buffer_input_stream_get_type ())
-#define GTK_SOURCE_BUFFER_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_SOURCE_TYPE_BUFFER_INPUT_STREAM, GtkSourceBufferInputStream))
-#define GTK_SOURCE_BUFFER_INPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_SOURCE_TYPE_BUFFER_INPUT_STREAM, GtkSourceBufferInputStreamClass))
-#define GTK_SOURCE_IS_BUFFER_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_SOURCE_TYPE_BUFFER_INPUT_STREAM))
-#define GTK_SOURCE_IS_BUFFER_INPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_SOURCE_TYPE_BUFFER_INPUT_STREAM))
-#define GTK_SOURCE_BUFFER_INPUT_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_SOURCE_TYPE_BUFFER_INPUT_STREAM, GtkSourceBufferInputStreamClass))
-
-typedef struct _GtkSourceBufferInputStreamClass GtkSourceBufferInputStreamClass;
-typedef struct _GtkSourceBufferInputStreamPrivate GtkSourceBufferInputStreamPrivate;
-
-struct _GtkSourceBufferInputStream
-{
- GInputStream parent;
-
- GtkSourceBufferInputStreamPrivate *priv;
-};
-
-struct _GtkSourceBufferInputStreamClass
-{
- GInputStreamClass parent_class;
-};
-
-GTK_SOURCE_INTERNAL
-GType _gtk_source_buffer_input_stream_get_type (void) G_GNUC_CONST;
-
-GTK_SOURCE_INTERNAL
-GtkSourceBufferInputStream
- *_gtk_source_buffer_input_stream_new (GtkTextBuffer *buffer,
- GtkSourceNewlineType type,
- gboolean add_trailing_newline);
-
-GTK_SOURCE_INTERNAL
-gsize _gtk_source_buffer_input_stream_get_total_size (GtkSourceBufferInputStream *stream);
-
-GTK_SOURCE_INTERNAL
-gsize _gtk_source_buffer_input_stream_tell (GtkSourceBufferInputStream *stream);
-
-G_END_DECLS
-
-#endif /* GTK_SOURCE_BUFFER_INPUT_STREAM_H */
diff --git a/gtksourceview/gtksourcebufferinternal.h b/gtksourceview/gtksourcebufferinternal-private.h
similarity index 62%
rename from gtksourceview/gtksourcebufferinternal.h
rename to gtksourceview/gtksourcebufferinternal-private.h
index 856d320ea6ba5b67af66e15ab3d5310162dd1ba7..287d061dc7078b01aaa5777662a63526582b7891 100644
--- a/gtksourceview/gtksourcebufferinternal.h
+++ b/gtksourceview/gtksourcebufferinternal-private.h
@@ -1,8 +1,7 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- */
/*
* This file is part of GtkSourceView
*
- * Copyright (C) 2016 - Sébastien Wilmet
+ * Copyright 2016 - Sébastien Wilmet
*
* GtkSourceView is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -18,8 +17,7 @@
* along with this library; if not, see .
*/
-#ifndef GTK_SOURCE_BUFFER_INTERNAL_H
-#define GTK_SOURCE_BUFFER_INTERNAL_H
+#pragma once
#include
#include "gtksourcetypes.h"
@@ -27,21 +25,15 @@
G_BEGIN_DECLS
-#define GTK_SOURCE_TYPE_BUFFER_INTERNAL (_gtk_source_buffer_internal_get_type ())
+#define GTK_SOURCE_TYPE_BUFFER_INTERNAL (_gtk_source_buffer_internal_get_type())
G_GNUC_INTERNAL
-G_DECLARE_FINAL_TYPE (GtkSourceBufferInternal, _gtk_source_buffer_internal,
- GTK_SOURCE, BUFFER_INTERNAL,
- GObject)
+G_DECLARE_FINAL_TYPE (GtkSourceBufferInternal, _gtk_source_buffer_internal, GTK_SOURCE, BUFFER_INTERNAL, GObject)
G_GNUC_INTERNAL
-GtkSourceBufferInternal *
- _gtk_source_buffer_internal_get_from_buffer (GtkSourceBuffer *buffer);
-
+GtkSourceBufferInternal *_gtk_source_buffer_internal_get_from_buffer (GtkSourceBuffer *buffer);
G_GNUC_INTERNAL
-void _gtk_source_buffer_internal_emit_search_start (GtkSourceBufferInternal *buffer_internal,
- GtkSourceSearchContext *search_context);
+void _gtk_source_buffer_internal_emit_search_start (GtkSourceBufferInternal *buffer_internal,
+ GtkSourceSearchContext *search_context);
G_END_DECLS
-
-#endif /* GTK_SOURCE_BUFFER_INTERNAL_H */
diff --git a/gtksourceview/gtksourcebufferinternal.c b/gtksourceview/gtksourcebufferinternal.c
index a41d17c8b97605e7dd37ffd669f7aa2e90b475b2..3bcd870621186505e82053b9d0317d1317c3b06b 100644
--- a/gtksourceview/gtksourcebufferinternal.c
+++ b/gtksourceview/gtksourcebufferinternal.c
@@ -1,8 +1,7 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- */
/*
* This file is part of GtkSourceView
*
- * Copyright (C) 2016 - Sébastien Wilmet
+ * Copyright 2016 - Sébastien Wilmet
*
* GtkSourceView is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -18,11 +17,9 @@
* along with this library; if not, see .
*/
-#ifdef HAVE_CONFIG_H
-#include
-#endif
+#include "config.h"
-#include "gtksourcebufferinternal.h"
+#include "gtksourcebufferinternal-private.h"
#include "gtksourcebuffer.h"
#include "gtksource-marshal.h"
#include "gtksourcesearchcontext.h"
@@ -113,7 +110,7 @@ _gtk_source_buffer_internal_get_from_buffer (GtkSourceBuffer *buffer)
void
_gtk_source_buffer_internal_emit_search_start (GtkSourceBufferInternal *buffer_internal,
- GtkSourceSearchContext *search_context)
+ GtkSourceSearchContext *search_context)
{
g_return_if_fail (GTK_SOURCE_IS_BUFFER_INTERNAL (buffer_internal));
g_return_if_fail (GTK_SOURCE_IS_SEARCH_CONTEXT (search_context));
diff --git a/gtksourceview/gtksourcebufferoutputstream-private.h b/gtksourceview/gtksourcebufferoutputstream-private.h
new file mode 100644
index 0000000000000000000000000000000000000000..39e40fd6d3bc519d2b04598e1ee59f657019e141
--- /dev/null
+++ b/gtksourceview/gtksourcebufferoutputstream-private.h
@@ -0,0 +1,48 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2010 - Ignacio Casal Quinteiro
+ * Copyright 2014 - Sébastien Wilmet
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ */
+
+#pragma once
+
+#include
+
+#include "gtksourcetypes.h"
+#include "gtksourcetypes-private.h"
+#include "gtksourcebuffer.h"
+#include "gtksourcefile.h"
+
+G_BEGIN_DECLS
+
+#define GTK_SOURCE_TYPE_BUFFER_OUTPUT_STREAM (gtk_source_buffer_output_stream_get_type())
+
+GTK_SOURCE_INTERNAL
+G_DECLARE_FINAL_TYPE (GtkSourceBufferOutputStream, gtk_source_buffer_output_stream, GTK_SOURCE, BUFFER_OUTPUT_STREAM, GOutputStream)
+
+GTK_SOURCE_INTERNAL
+GtkSourceBufferOutputStream *gtk_source_buffer_output_stream_new (GtkSourceBuffer *buffer,
+ GSList *candidate_encodings,
+ gboolean remove_trailing_newline);
+GTK_SOURCE_INTERNAL
+GtkSourceNewlineType gtk_source_buffer_output_stream_detect_newline_type (GtkSourceBufferOutputStream *stream);
+GTK_SOURCE_INTERNAL
+const GtkSourceEncoding *gtk_source_buffer_output_stream_get_guessed (GtkSourceBufferOutputStream *stream);
+GTK_SOURCE_INTERNAL
+guint gtk_source_buffer_output_stream_get_num_fallbacks (GtkSourceBufferOutputStream *stream);
+
+G_END_DECLS
diff --git a/gtksourceview/gtksourcebufferoutputstream.c b/gtksourceview/gtksourcebufferoutputstream.c
index 77a2a113ff516a8b3007c1951ec5ef8f6331c795..b3f8e1dd5aab073d5edb12d04ee125786bcf927b 100644
--- a/gtksourceview/gtksourcebufferoutputstream.c
+++ b/gtksourceview/gtksourcebufferoutputstream.c
@@ -1,9 +1,8 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- */
/*
* This file is part of GtkSourceView
*
- * Copyright (C) 2010 - Ignacio Casal Quinteiro
- * Copyright (C) 2014 - Sébastien Wilmet
+ * Copyright 2010 - Ignacio Casal Quinteiro
+ * Copyright 2014 - Sébastien Wilmet
*
* GtkSourceView is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -19,14 +18,13 @@
* along with this library; if not, see .
*/
-#ifdef HAVE_CONFIG_H
-#include
-#endif
+#include "config.h"
-#include "gtksourcebufferoutputstream.h"
#include
#include
#include
+
+#include "gtksourcebufferoutputstream-private.h"
#include "gtksourcebuffer.h"
#include "gtksourcebuffer-private.h"
#include "gtksourceencoding.h"
@@ -57,8 +55,10 @@
#define MAX_UNICHAR_LEN 6
-struct _GtkSourceBufferOutputStreamPrivate
+struct _GtkSourceBufferOutputStream
{
+ GOutputStream parent_instance;
+
GtkSourceBuffer *source_buffer;
GtkTextIter pos;
@@ -94,39 +94,37 @@ enum
PROP_REMOVE_TRAILING_NEWLINE
};
-G_DEFINE_TYPE_WITH_PRIVATE (GtkSourceBufferOutputStream, gtk_source_buffer_output_stream, G_TYPE_OUTPUT_STREAM)
-
-static gssize gtk_source_buffer_output_stream_write (GOutputStream *stream,
- const void *buffer,
- gsize count,
- GCancellable *cancellable,
- GError **error);
+G_DEFINE_TYPE (GtkSourceBufferOutputStream, gtk_source_buffer_output_stream, G_TYPE_OUTPUT_STREAM)
+static gssize gtk_source_buffer_output_stream_write (GOutputStream *stream,
+ const void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error);
static gboolean gtk_source_buffer_output_stream_close (GOutputStream *stream,
- GCancellable *cancellable,
- GError **error);
-
+ GCancellable *cancellable,
+ GError **error);
static gboolean gtk_source_buffer_output_stream_flush (GOutputStream *stream,
- GCancellable *cancellable,
- GError **error);
+ GCancellable *cancellable,
+ GError **error);
static void
gtk_source_buffer_output_stream_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
GtkSourceBufferOutputStream *stream = GTK_SOURCE_BUFFER_OUTPUT_STREAM (object);
switch (prop_id)
{
case PROP_BUFFER:
- g_assert (stream->priv->source_buffer == NULL);
- stream->priv->source_buffer = g_value_dup_object (value);
+ g_assert (stream->source_buffer == NULL);
+ stream->source_buffer = g_value_dup_object (value);
break;
case PROP_REMOVE_TRAILING_NEWLINE:
- stream->priv->remove_trailing_newline = g_value_get_boolean (value);
+ stream->remove_trailing_newline = g_value_get_boolean (value);
break;
default:
@@ -137,20 +135,20 @@ gtk_source_buffer_output_stream_set_property (GObject *object,
static void
gtk_source_buffer_output_stream_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
{
GtkSourceBufferOutputStream *stream = GTK_SOURCE_BUFFER_OUTPUT_STREAM (object);
switch (prop_id)
{
case PROP_BUFFER:
- g_value_set_object (value, stream->priv->source_buffer);
+ g_value_set_object (value, stream->source_buffer);
break;
case PROP_REMOVE_TRAILING_NEWLINE:
- g_value_set_boolean (value, stream->priv->remove_trailing_newline);
+ g_value_set_boolean (value, stream->remove_trailing_newline);
break;
default:
@@ -164,8 +162,8 @@ gtk_source_buffer_output_stream_dispose (GObject *object)
{
GtkSourceBufferOutputStream *stream = GTK_SOURCE_BUFFER_OUTPUT_STREAM (object);
- g_clear_object (&stream->priv->source_buffer);
- g_clear_object (&stream->priv->charset_conv);
+ g_clear_object (&stream->source_buffer);
+ g_clear_object (&stream->charset_conv);
G_OBJECT_CLASS (gtk_source_buffer_output_stream_parent_class)->dispose (object);
}
@@ -175,9 +173,9 @@ gtk_source_buffer_output_stream_finalize (GObject *object)
{
GtkSourceBufferOutputStream *stream = GTK_SOURCE_BUFFER_OUTPUT_STREAM (object);
- g_free (stream->priv->buffer);
- g_free (stream->priv->iconv_buffer);
- g_slist_free (stream->priv->encodings);
+ g_free (stream->buffer);
+ g_free (stream->iconv_buffer);
+ g_slist_free (stream->encodings);
G_OBJECT_CLASS (gtk_source_buffer_output_stream_parent_class)->finalize (object);
}
@@ -187,18 +185,18 @@ gtk_source_buffer_output_stream_constructed (GObject *object)
{
GtkSourceBufferOutputStream *stream = GTK_SOURCE_BUFFER_OUTPUT_STREAM (object);
- if (stream->priv->source_buffer == NULL)
+ if (stream->source_buffer == NULL)
{
g_critical ("This should never happen, a problem happened constructing the Buffer Output Stream!");
return;
}
- gtk_source_buffer_begin_not_undoable_action (stream->priv->source_buffer);
+ gtk_text_buffer_begin_irreversible_action (GTK_TEXT_BUFFER (stream->source_buffer));
- gtk_text_buffer_set_text (GTK_TEXT_BUFFER (stream->priv->source_buffer), "", 0);
- gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (stream->priv->source_buffer), FALSE);
+ gtk_text_buffer_set_text (GTK_TEXT_BUFFER (stream->source_buffer), "", 0);
+ gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (stream->source_buffer), FALSE);
- gtk_source_buffer_end_not_undoable_action (stream->priv->source_buffer);
+ gtk_text_buffer_end_irreversible_action (GTK_TEXT_BUFFER (stream->source_buffer));
G_OBJECT_CLASS (gtk_source_buffer_output_stream_parent_class)->constructed (object);
}
@@ -243,44 +241,42 @@ gtk_source_buffer_output_stream_class_init (GtkSourceBufferOutputStreamClass *kl
static void
gtk_source_buffer_output_stream_init (GtkSourceBufferOutputStream *stream)
{
- stream->priv = gtk_source_buffer_output_stream_get_instance_private (stream);
-
- stream->priv->buffer = NULL;
- stream->priv->buflen = 0;
+ stream->buffer = NULL;
+ stream->buflen = 0;
- stream->priv->charset_conv = NULL;
- stream->priv->encodings = NULL;
- stream->priv->current_encoding = NULL;
+ stream->charset_conv = NULL;
+ stream->encodings = NULL;
+ stream->current_encoding = NULL;
- stream->priv->error_offset = -1;
+ stream->error_offset = -1;
- stream->priv->is_initialized = FALSE;
- stream->priv->is_closed = FALSE;
- stream->priv->is_utf8 = FALSE;
- stream->priv->use_first = FALSE;
+ stream->is_initialized = FALSE;
+ stream->is_closed = FALSE;
+ stream->is_utf8 = FALSE;
+ stream->use_first = FALSE;
}
static const GtkSourceEncoding *
get_encoding (GtkSourceBufferOutputStream *stream)
{
- if (stream->priv->current_encoding == NULL)
+ if (stream->current_encoding == NULL)
{
- stream->priv->current_encoding = stream->priv->encodings;
+ stream->current_encoding = stream->encodings;
}
else
{
- stream->priv->current_encoding = g_slist_next (stream->priv->current_encoding);
+ stream->current_encoding = g_slist_next (stream->current_encoding);
}
- if (stream->priv->current_encoding != NULL)
+ if (stream->current_encoding != NULL)
{
- return stream->priv->current_encoding->data;
+ return stream->current_encoding->data;
}
- stream->priv->use_first = TRUE;
- stream->priv->current_encoding = stream->priv->encodings;
+ stream->use_first = TRUE;
+ stream->current_encoding = stream->encodings;
- return stream->priv->current_encoding->data;
+ return stream->current_encoding->data;
}
static gboolean
@@ -357,21 +353,21 @@ try_convert (GCharsetConverter *converter,
static GCharsetConverter *
guess_encoding (GtkSourceBufferOutputStream *stream,
- const void *inbuf,
- gsize inbuf_size)
+ const void *inbuf,
+ gsize inbuf_size)
{
GCharsetConverter *conv = NULL;
if (inbuf == NULL || inbuf_size == 0)
{
- stream->priv->is_utf8 = TRUE;
+ stream->is_utf8 = TRUE;
return NULL;
}
- if (stream->priv->encodings != NULL &&
- stream->priv->encodings->next == NULL)
+ if (stream->encodings != NULL &&
+ stream->encodings->next == NULL)
{
- stream->priv->use_first = TRUE;
+ stream->use_first = TRUE;
}
/* We just check the first block */
@@ -392,7 +388,7 @@ guess_encoding (GtkSourceBufferOutputStream *stream,
DEBUG ({
g_print ("trying charset: %s\n",
- gtk_source_encoding_get_charset (stream->priv->current_encoding->data));
+ gtk_source_encoding_get_charset (stream->current_encoding->data));
});
if (enc == gtk_source_encoding_get_utf8 ())
@@ -401,9 +397,9 @@ guess_encoding (GtkSourceBufferOutputStream *stream,
const gchar *end;
if (g_utf8_validate (inbuf, inbuf_size, &end) ||
- stream->priv->use_first)
+ stream->use_first)
{
- stream->priv->is_utf8 = TRUE;
+ stream->is_utf8 = TRUE;
break;
}
@@ -411,7 +407,7 @@ guess_encoding (GtkSourceBufferOutputStream *stream,
remainder = inbuf_size - (end - (gchar *)inbuf);
if (remainder < 6)
{
- stream->priv->is_utf8 = TRUE;
+ stream->is_utf8 = TRUE;
break;
}
@@ -423,7 +419,7 @@ guess_encoding (GtkSourceBufferOutputStream *stream,
NULL);
/* If we tried all encodings we use the first one */
- if (stream->priv->use_first)
+ if (stream->use_first)
{
break;
}
@@ -475,8 +471,8 @@ get_newline_type (GtkTextIter *end)
GtkSourceBufferOutputStream *
gtk_source_buffer_output_stream_new (GtkSourceBuffer *buffer,
- GSList *candidate_encodings,
- gboolean remove_trailing_newline)
+ GSList *candidate_encodings,
+ gboolean remove_trailing_newline)
{
GtkSourceBufferOutputStream *stream;
@@ -485,7 +481,7 @@ gtk_source_buffer_output_stream_new (GtkSourceBuffer *buffer,
"remove-trailing-newline", remove_trailing_newline,
NULL);
- stream->priv->encodings = g_slist_copy (candidate_encodings);
+ stream->encodings = g_slist_copy (candidate_encodings);
return stream;
}
@@ -499,14 +495,14 @@ gtk_source_buffer_output_stream_detect_newline_type (GtkSourceBufferOutputStream
g_return_val_if_fail (GTK_SOURCE_IS_BUFFER_OUTPUT_STREAM (stream),
GTK_SOURCE_NEWLINE_TYPE_DEFAULT);
- if (stream->priv->source_buffer == NULL)
+ if (stream->source_buffer == NULL)
{
return GTK_SOURCE_NEWLINE_TYPE_DEFAULT;
}
type = GTK_SOURCE_NEWLINE_TYPE_DEFAULT;
- gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (stream->priv->source_buffer),
+ gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (stream->source_buffer),
&iter);
if (gtk_text_iter_ends_line (&iter) || gtk_text_iter_forward_to_line_end (&iter))
@@ -522,11 +518,11 @@ gtk_source_buffer_output_stream_get_guessed (GtkSourceBufferOutputStream *stream
{
g_return_val_if_fail (GTK_SOURCE_IS_BUFFER_OUTPUT_STREAM (stream), NULL);
- if (stream->priv->current_encoding != NULL)
+ if (stream->current_encoding != NULL)
{
- return stream->priv->current_encoding->data;
+ return stream->current_encoding->data;
}
- else if (stream->priv->is_utf8 || !stream->priv->is_initialized)
+ else if (stream->is_utf8 || !stream->is_initialized)
{
/* If it is not initialized we assume that we are trying to
* convert the empty string.
@@ -542,7 +538,7 @@ gtk_source_buffer_output_stream_get_num_fallbacks (GtkSourceBufferOutputStream *
{
g_return_val_if_fail (GTK_SOURCE_IS_BUFFER_OUTPUT_STREAM (stream), 0);
- return stream->priv->n_fallback_errors;
+ return stream->n_fallback_errors;
}
static void
@@ -550,31 +546,31 @@ apply_error_tag (GtkSourceBufferOutputStream *stream)
{
GtkTextIter start;
- if (stream->priv->error_offset == -1 ||
- stream->priv->source_buffer == NULL)
+ if (stream->error_offset == -1 ||
+ stream->source_buffer == NULL)
{
return;
}
- gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (stream->priv->source_buffer),
- &start, stream->priv->error_offset);
+ gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (stream->source_buffer),
+ &start, stream->error_offset);
- _gtk_source_buffer_set_as_invalid_character (stream->priv->source_buffer,
+ _gtk_source_buffer_set_as_invalid_character (stream->source_buffer,
&start,
- &stream->priv->pos);
+ &stream->pos);
- stream->priv->error_offset = -1;
+ stream->error_offset = -1;
}
static void
insert_fallback (GtkSourceBufferOutputStream *stream,
- const gchar *buffer)
+ const gchar *buffer)
{
guint8 out[4];
guint8 v;
const gchar hex[] = "0123456789ABCDEF";
- if (stream->priv->source_buffer == NULL)
+ if (stream->source_buffer == NULL)
{
return;
}
@@ -588,30 +584,30 @@ insert_fallback (GtkSourceBufferOutputStream *stream,
out[2] = hex[(v & 0x0f) >> 0];
out[3] = '\0';
- gtk_text_buffer_insert (GTK_TEXT_BUFFER (stream->priv->source_buffer),
- &stream->priv->pos, (const gchar *)out, 3);
+ gtk_text_buffer_insert (GTK_TEXT_BUFFER (stream->source_buffer),
+ &stream->pos, (const gchar *)out, 3);
- ++stream->priv->n_fallback_errors;
+ ++stream->n_fallback_errors;
}
static void
validate_and_insert (GtkSourceBufferOutputStream *stream,
- gchar *buffer,
- gsize count,
- gboolean owned)
+ gchar *buffer,
+ gsize count,
+ gboolean owned)
{
GtkTextBuffer *text_buffer;
GtkTextIter *iter;
gsize len;
gchar *free_text = NULL;
- if (stream->priv->source_buffer == NULL)
+ if (stream->source_buffer == NULL)
{
return;
}
- text_buffer = GTK_TEXT_BUFFER (stream->priv->source_buffer);
- iter = &stream->priv->pos;
+ text_buffer = GTK_TEXT_BUFFER (stream->source_buffer);
+ iter = &stream->pos;
len = count;
while (len != 0)
@@ -637,10 +633,10 @@ validate_and_insert (GtkSourceBufferOutputStream *stream,
if (ptr && *ptr == '\r' && ptr - buffer == (glong)len - 1)
{
- stream->priv->buffer = g_new (gchar, 2);
- stream->priv->buffer[0] = '\r';
- stream->priv->buffer[1] = '\0';
- stream->priv->buflen = 1;
+ stream->buffer = g_new (gchar, 2);
+ stream->buffer[0] = '\r';
+ stream->buffer[1] = '\0';
+ stream->buflen = 1;
/* Decrease also the len so in the check
nvalid == len we get out of this method */
@@ -701,16 +697,16 @@ validate_and_insert (GtkSourceBufferOutputStream *stream,
if ((len < MAX_UNICHAR_LEN) &&
(g_utf8_get_char_validated (buffer, len) == (gunichar)-2))
{
- stream->priv->buffer = g_strndup (end, len);
- stream->priv->buflen = len;
+ stream->buffer = g_strndup (end, len);
+ stream->buflen = len;
break;
}
/* we need the start of the chunk of invalid chars */
- if (stream->priv->error_offset == -1)
+ if (stream->error_offset == -1)
{
- stream->priv->error_offset = gtk_text_iter_get_offset (&stream->priv->pos);
+ stream->error_offset = gtk_text_iter_get_offset (&stream->pos);
}
insert_fallback (stream, buffer);
@@ -727,12 +723,12 @@ remove_trailing_newline (GtkSourceBufferOutputStream *stream)
GtkTextIter end;
GtkTextIter start;
- if (stream->priv->source_buffer == NULL)
+ if (stream->source_buffer == NULL)
{
return;
}
- gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (stream->priv->source_buffer), &end);
+ gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (stream->source_buffer), &end);
start = end;
gtk_text_iter_set_line_offset (&start, 0);
@@ -745,7 +741,7 @@ remove_trailing_newline (GtkSourceBufferOutputStream *stream)
gtk_text_iter_forward_to_line_end (&start);
}
- gtk_text_buffer_delete (GTK_TEXT_BUFFER (stream->priv->source_buffer),
+ gtk_text_buffer_delete (GTK_TEXT_BUFFER (stream->source_buffer),
&start,
&end);
}
@@ -754,30 +750,30 @@ remove_trailing_newline (GtkSourceBufferOutputStream *stream)
static void
end_append_text_to_document (GtkSourceBufferOutputStream *stream)
{
- if (stream->priv->source_buffer == NULL)
+ if (stream->source_buffer == NULL)
{
return;
}
- if (stream->priv->remove_trailing_newline)
+ if (stream->remove_trailing_newline)
{
remove_trailing_newline (stream);
}
- gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (stream->priv->source_buffer),
+ gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (stream->source_buffer),
FALSE);
- gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (stream->priv->source_buffer));
- gtk_source_buffer_end_not_undoable_action (stream->priv->source_buffer);
+ gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (stream->source_buffer));
+ gtk_text_buffer_end_irreversible_action (GTK_TEXT_BUFFER (stream->source_buffer));
}
static gboolean
convert_text (GtkSourceBufferOutputStream *stream,
- const gchar *inbuf,
- gsize inbuf_len,
- gchar **outbuf,
- gsize *outbuf_len,
- GError **error)
+ const gchar *inbuf,
+ gsize inbuf_len,
+ gchar **outbuf,
+ gsize *outbuf_len,
+ GError **error)
{
gchar *out, *dest;
gsize in_left, out_left, outbuf_size, res;
@@ -802,7 +798,7 @@ convert_text (GtkSourceBufferOutputStream *stream,
/* If we reached here is because we need to convert the text,
so we convert it using iconv.
See that if inbuf is NULL the data will be flushed */
- res = g_iconv (stream->priv->iconv,
+ res = g_iconv (stream->iconv,
(gchar **)&inbuf, &in_left,
&out, &out_left);
@@ -815,8 +811,8 @@ convert_text (GtkSourceBufferOutputStream *stream,
{
case EINVAL:
/* Incomplete text, do not report an error */
- stream->priv->iconv_buffer = g_strndup (inbuf, in_left);
- stream->priv->iconv_buflen = in_left;
+ stream->iconv_buffer = g_strndup (inbuf, in_left);
+ stream->iconv_buflen = in_left;
done = TRUE;
break;
@@ -875,10 +871,10 @@ convert_text (GtkSourceBufferOutputStream *stream,
static gssize
gtk_source_buffer_output_stream_write (GOutputStream *stream,
- const void *buffer,
- gsize count,
- GCancellable *cancellable,
- GError **error)
+ const void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error)
{
GtkSourceBufferOutputStream *ostream;
gchar *text;
@@ -888,19 +884,19 @@ gtk_source_buffer_output_stream_write (GOutputStream *stream,
ostream = GTK_SOURCE_BUFFER_OUTPUT_STREAM (stream);
if (g_cancellable_set_error_if_cancelled (cancellable, error) ||
- ostream->priv->source_buffer == NULL)
+ ostream->source_buffer == NULL)
{
return -1;
}
- if (!ostream->priv->is_initialized)
+ if (!ostream->is_initialized)
{
- ostream->priv->charset_conv = guess_encoding (ostream, buffer, count);
+ ostream->charset_conv = guess_encoding (ostream, buffer, count);
/* If we still have the previous case is that we didn't guess
anything */
- if (ostream->priv->charset_conv == NULL &&
- !ostream->priv->is_utf8)
+ if (ostream->charset_conv == NULL &&
+ !ostream->is_utf8)
{
g_set_error_literal (error, GTK_SOURCE_FILE_LOADER_ERROR,
GTK_SOURCE_FILE_LOADER_ERROR_ENCODING_AUTO_DETECTION_FAILED,
@@ -910,18 +906,18 @@ gtk_source_buffer_output_stream_write (GOutputStream *stream,
}
/* Do not initialize iconv if we are not going to convert anything */
- if (!ostream->priv->is_utf8)
+ if (!ostream->is_utf8)
{
gchar *from_charset;
/* Initialize iconv */
- g_object_get (G_OBJECT (ostream->priv->charset_conv),
+ g_object_get (G_OBJECT (ostream->charset_conv),
"from-charset", &from_charset,
NULL);
- ostream->priv->iconv = g_iconv_open ("UTF-8", from_charset);
+ ostream->iconv = g_iconv_open ("UTF-8", from_charset);
- if (ostream->priv->iconv == (GIConv)-1)
+ if (ostream->iconv == (GIConv)-1)
{
if (errno == EINVAL)
{
@@ -937,7 +933,7 @@ gtk_source_buffer_output_stream_write (GOutputStream *stream,
}
g_free (from_charset);
- g_clear_object (&ostream->priv->charset_conv);
+ g_clear_object (&ostream->charset_conv);
return -1;
}
@@ -950,29 +946,29 @@ gtk_source_buffer_output_stream_write (GOutputStream *stream,
* as only one action, for the features that rely on the user
* action.
*/
- gtk_source_buffer_begin_not_undoable_action (ostream->priv->source_buffer);
- gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (ostream->priv->source_buffer));
+ gtk_text_buffer_begin_irreversible_action (GTK_TEXT_BUFFER (ostream->source_buffer));
+ gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (ostream->source_buffer));
- gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (ostream->priv->source_buffer),
- &ostream->priv->pos);
+ gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (ostream->source_buffer),
+ &ostream->pos);
- ostream->priv->is_initialized = TRUE;
+ ostream->is_initialized = TRUE;
}
- if (ostream->priv->buflen > 0)
+ if (ostream->buflen > 0)
{
- len = ostream->priv->buflen + count;
+ len = ostream->buflen + count;
text = g_malloc (len + 1);
- memcpy (text, ostream->priv->buffer, ostream->priv->buflen);
- memcpy (text + ostream->priv->buflen, buffer, count);
+ memcpy (text, ostream->buffer, ostream->buflen);
+ memcpy (text + ostream->buflen, buffer, count);
text[len] = '\0';
- g_free (ostream->priv->buffer);
+ g_free (ostream->buffer);
- ostream->priv->buffer = NULL;
- ostream->priv->buflen = 0;
+ ostream->buffer = NULL;
+ ostream->buflen = 0;
freetext = TRUE;
}
@@ -982,14 +978,14 @@ gtk_source_buffer_output_stream_write (GOutputStream *stream,
len = count;
}
- if (!ostream->priv->is_utf8)
+ if (!ostream->is_utf8)
{
gchar *outbuf;
gsize outbuf_len;
/* check if iconv was correctly initializated, this shouldn't
happen but better be safe */
- if (ostream->priv->iconv == NULL)
+ if (ostream->iconv == NULL)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED,
_("Invalid object, not initialized"));
@@ -1003,16 +999,16 @@ gtk_source_buffer_output_stream_write (GOutputStream *stream,
}
/* manage the previous conversion buffer */
- if (ostream->priv->iconv_buflen > 0)
+ if (ostream->iconv_buflen > 0)
{
gchar *text2;
gsize len2;
- len2 = len + ostream->priv->iconv_buflen;
+ len2 = len + ostream->iconv_buflen;
text2 = g_malloc (len2 + 1);
- memcpy (text2, ostream->priv->iconv_buffer, ostream->priv->iconv_buflen);
- memcpy (text2 + ostream->priv->iconv_buflen, text, len);
+ memcpy (text2, ostream->iconv_buffer, ostream->iconv_buflen);
+ memcpy (text2 + ostream->iconv_buflen, text, len);
text2[len2] = '\0';
@@ -1024,10 +1020,10 @@ gtk_source_buffer_output_stream_write (GOutputStream *stream,
text = text2;
len = len2;
- g_free (ostream->priv->iconv_buffer);
+ g_free (ostream->iconv_buffer);
- ostream->priv->iconv_buffer = NULL;
- ostream->priv->iconv_buflen = 0;
+ ostream->iconv_buffer = NULL;
+ ostream->iconv_buflen = 0;
freetext = TRUE;
}
@@ -1064,21 +1060,21 @@ gtk_source_buffer_output_stream_write (GOutputStream *stream,
static gboolean
gtk_source_buffer_output_stream_flush (GOutputStream *stream,
- GCancellable *cancellable,
- GError **error)
+ GCancellable *cancellable,
+ GError **error)
{
GtkSourceBufferOutputStream *ostream;
ostream = GTK_SOURCE_BUFFER_OUTPUT_STREAM (stream);
- if (ostream->priv->is_closed ||
- ostream->priv->source_buffer == NULL)
+ if (ostream->is_closed ||
+ ostream->source_buffer == NULL)
{
return TRUE;
}
/* if we have converted something flush residual data, validate and insert */
- if (ostream->priv->iconv != NULL)
+ if (ostream->iconv != NULL)
{
gchar *outbuf;
gsize outbuf_len;
@@ -1094,65 +1090,65 @@ gtk_source_buffer_output_stream_flush (GOutputStream *stream,
}
}
- if (ostream->priv->buflen > 0 && *ostream->priv->buffer != '\r')
+ if (ostream->buflen > 0 && *ostream->buffer != '\r')
{
/* If we reached here is because the last insertion was a half
correct char, which has to be inserted as fallback */
gchar *text;
- if (ostream->priv->error_offset == -1)
+ if (ostream->error_offset == -1)
{
- ostream->priv->error_offset = gtk_text_iter_get_offset (&ostream->priv->pos);
+ ostream->error_offset = gtk_text_iter_get_offset (&ostream->pos);
}
- text = ostream->priv->buffer;
- while (ostream->priv->buflen != 0)
+ text = ostream->buffer;
+ while (ostream->buflen != 0)
{
insert_fallback (ostream, text);
++text;
- --ostream->priv->buflen;
+ --ostream->buflen;
}
- g_free (ostream->priv->buffer);
- ostream->priv->buffer = NULL;
+ g_free (ostream->buffer);
+ ostream->buffer = NULL;
}
- else if (ostream->priv->buflen == 1 && *ostream->priv->buffer == '\r')
+ else if (ostream->buflen == 1 && *ostream->buffer == '\r')
{
/* The previous chars can be invalid */
apply_error_tag (ostream);
/* See special case above, flush this */
- gtk_text_buffer_insert (GTK_TEXT_BUFFER (ostream->priv->source_buffer),
- &ostream->priv->pos,
+ gtk_text_buffer_insert (GTK_TEXT_BUFFER (ostream->source_buffer),
+ &ostream->pos,
"\r",
1);
- g_free (ostream->priv->buffer);
- ostream->priv->buffer = NULL;
- ostream->priv->buflen = 0;
+ g_free (ostream->buffer);
+ ostream->buffer = NULL;
+ ostream->buflen = 0;
}
- if (ostream->priv->iconv_buflen > 0 )
+ if (ostream->iconv_buflen > 0 )
{
/* If we reached here is because the last insertion was a half
correct char, which has to be inserted as fallback */
gchar *text;
- if (ostream->priv->error_offset == -1)
+ if (ostream->error_offset == -1)
{
- ostream->priv->error_offset = gtk_text_iter_get_offset (&ostream->priv->pos);
+ ostream->error_offset = gtk_text_iter_get_offset (&ostream->pos);
}
- text = ostream->priv->iconv_buffer;
- while (ostream->priv->iconv_buflen != 0)
+ text = ostream->iconv_buffer;
+ while (ostream->iconv_buflen != 0)
{
insert_fallback (ostream, text);
++text;
- --ostream->priv->iconv_buflen;
+ --ostream->iconv_buflen;
}
- g_free (ostream->priv->iconv_buffer);
- ostream->priv->iconv_buffer = NULL;
+ g_free (ostream->iconv_buffer);
+ ostream->iconv_buffer = NULL;
}
apply_error_tag (ostream);
@@ -1162,24 +1158,24 @@ gtk_source_buffer_output_stream_flush (GOutputStream *stream,
static gboolean
gtk_source_buffer_output_stream_close (GOutputStream *stream,
- GCancellable *cancellable,
- GError **error)
+ GCancellable *cancellable,
+ GError **error)
{
GtkSourceBufferOutputStream *ostream = GTK_SOURCE_BUFFER_OUTPUT_STREAM (stream);
- if (!ostream->priv->is_closed && ostream->priv->is_initialized)
+ if (!ostream->is_closed && ostream->is_initialized)
{
end_append_text_to_document (ostream);
- if (ostream->priv->iconv != NULL)
+ if (ostream->iconv != NULL)
{
- g_iconv_close (ostream->priv->iconv);
+ g_iconv_close (ostream->iconv);
}
- ostream->priv->is_closed = TRUE;
+ ostream->is_closed = TRUE;
}
- if (ostream->priv->buflen > 0 || ostream->priv->iconv_buflen > 0)
+ if (ostream->buflen > 0 || ostream->iconv_buflen > 0)
{
g_set_error (error,
G_IO_ERROR,
diff --git a/gtksourceview/gtksourcebufferoutputstream.h b/gtksourceview/gtksourcebufferoutputstream.h
deleted file mode 100644
index f1a16fd9e2551644df911eda0e2fef36185e81d5..0000000000000000000000000000000000000000
--- a/gtksourceview/gtksourcebufferoutputstream.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- */
-/*
- * This file is part of GtkSourceView
- *
- * Copyright (C) 2010 - Ignacio Casal Quinteiro
- * Copyright (C) 2014 - Sébastien Wilmet
- *
- * GtkSourceView is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * GtkSourceView 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, see .
- */
-
-#ifndef GTK_SOURCE_BUFFER_OUTPUT_STREAM_H
-#define GTK_SOURCE_BUFFER_OUTPUT_STREAM_H
-
-#include
-#include "gtksourcetypes.h"
-#include "gtksourcetypes-private.h"
-#include "gtksourcebuffer.h"
-#include "gtksourcefile.h"
-
-G_BEGIN_DECLS
-
-#define GTK_SOURCE_TYPE_BUFFER_OUTPUT_STREAM (gtk_source_buffer_output_stream_get_type ())
-#define GTK_SOURCE_BUFFER_OUTPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_SOURCE_TYPE_BUFFER_OUTPUT_STREAM, GtkSourceBufferOutputStream))
-#define GTK_SOURCE_BUFFER_OUTPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_SOURCE_TYPE_BUFFER_OUTPUT_STREAM, GtkSourceBufferOutputStreamClass))
-#define GTK_SOURCE_IS_BUFFER_OUTPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_SOURCE_TYPE_BUFFER_OUTPUT_STREAM))
-#define GTK_SOURCE_IS_BUFFER_OUTPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_SOURCE_TYPE_BUFFER_OUTPUT_STREAM))
-#define GTK_SOURCE_BUFFER_OUTPUT_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_SOURCE_TYPE_BUFFER_OUTPUT_STREAM, GtkSourceBufferOutputStreamClass))
-
-typedef struct _GtkSourceBufferOutputStreamClass GtkSourceBufferOutputStreamClass;
-typedef struct _GtkSourceBufferOutputStreamPrivate GtkSourceBufferOutputStreamPrivate;
-
-struct _GtkSourceBufferOutputStream
-{
- GOutputStream parent;
-
- GtkSourceBufferOutputStreamPrivate *priv;
-};
-
-struct _GtkSourceBufferOutputStreamClass
-{
- GOutputStreamClass parent_class;
-};
-
-GTK_SOURCE_INTERNAL
-GType gtk_source_buffer_output_stream_get_type (void) G_GNUC_CONST;
-
-GTK_SOURCE_INTERNAL
-GtkSourceBufferOutputStream
- *gtk_source_buffer_output_stream_new (GtkSourceBuffer *buffer,
- GSList *candidate_encodings,
- gboolean remove_trailing_newline);
-
-GTK_SOURCE_INTERNAL
-GtkSourceNewlineType gtk_source_buffer_output_stream_detect_newline_type
- (GtkSourceBufferOutputStream *stream);
-
-GTK_SOURCE_INTERNAL
-const GtkSourceEncoding *gtk_source_buffer_output_stream_get_guessed (GtkSourceBufferOutputStream *stream);
-
-GTK_SOURCE_INTERNAL
-guint gtk_source_buffer_output_stream_get_num_fallbacks
- (GtkSourceBufferOutputStream *stream);
-
-G_END_DECLS
-
-#endif /* GTK_SOURCE_BUFFER_OUTPUT_STREAM_H */
diff --git a/gtksourceview/gtksourcecompletion-private.h b/gtksourceview/gtksourcecompletion-private.h
index 05fafb637187104dc6d8fba6852f784db23f36ab..bae3bdfe6bd0dcd6d0e98c43f00a4aae8eefe46f 100644
--- a/gtksourceview/gtksourcecompletion-private.h
+++ b/gtksourceview/gtksourcecompletion-private.h
@@ -1,8 +1,7 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
- *
+/*
* This file is part of GtkSourceView
*
- * Copyright (C) 2009 - Jesse van den Kieboom
+ * Copyright 2020 Christian Hergert
*
* GtkSourceView is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -16,16 +15,29 @@
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, see .
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
*/
-#ifndef GTK_SOURCE_COMPLETION_PIVATE_H
-#define GTK_SOURCE_COMPLETION_PIVATE_H
+#pragma once
#include
-#include
-G_GNUC_INTERNAL
-GtkSourceCompletion *gtk_source_completion_new (GtkSourceView *source_view);
+#include "gtksourcecompletion.h"
+#include "gtksourcecompletionlist-private.h"
+
+G_BEGIN_DECLS
-#endif /* GTK_SOURCE_COMPLETION_PIVATE_H */
+GtkSourceCompletion *_gtk_source_completion_new (GtkSourceView *view);
+GtkSourceCompletionList *_gtk_source_completion_get_display (GtkSourceCompletion *self);
+void _gtk_source_completion_set_font_desc (GtkSourceCompletion *self,
+ const PangoFontDescription *font_desc);
+void _gtk_source_completion_activate (GtkSourceCompletion *self,
+ GtkSourceCompletionContext *context,
+ GtkSourceCompletionProvider *provider,
+ GtkSourceCompletionProposal *proposal);
+gboolean _gtk_source_completion_get_select_on_show (GtkSourceCompletion *self);
+void _gtk_source_completion_css_changed (GtkSourceCompletion *self,
+ GtkCssStyleChange *change);
+G_END_DECLS
diff --git a/gtksourceview/gtksourcecompletion.c b/gtksourceview/gtksourcecompletion.c
index 15cdf27abd488bd886e8d8bf6c147b76b859b8c9..1e1f47dd990fb4e6f9c9c6f641935d5259f76ff9 100644
--- a/gtksourceview/gtksourcecompletion.c
+++ b/gtksourceview/gtksourcecompletion.c
@@ -1,10 +1,7 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- */
/*
* This file is part of GtkSourceView
*
- * Copyright (C) 2007 -2009 Jesús Barbero Rodríguez
- * Copyright (C) 2009 - Jesse van den Kieboom
- * Copyright (C) 2013 - Sébastien Wilmet
+ * Copyright 2020 Christian Hergert
*
* GtkSourceView is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -18,3140 +15,1577 @@
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, see .
- */
-
-/**
- * SECTION:completion
- * @title: GtkSourceCompletion
- * @short_description: Main Completion Object
- *
- * The completion system helps the user when he/she writes some text,
- * such as words, command names, functions, and suchlike. Proposals can
- * be shown, to complete the text the user is writing. Each proposal can
- * contain an additional piece of information (for example
- * documentation), that is displayed when the "Details" button is
- * clicked.
- *
- * Proposals are created via a #GtkSourceCompletionProvider. There can
- * be for example a provider to complete words (see
- * #GtkSourceCompletionWords), another provider for the completion of
- * function names, etc. To add a provider, call
- * gtk_source_completion_add_provider().
- *
- * When the completion is activated, a #GtkSourceCompletionContext object is
- * created. The providers are asked whether they match the context, with
- * gtk_source_completion_provider_match(). If a provider doesn't match the
- * context, it will not be visible in the completion window. On the
- * other hand, if the provider matches the context, its proposals will
- * be displayed.
- *
- * When several providers match, they are all shown in the completion
- * window, but one can switch between providers: see the
- * #GtkSourceCompletion::move-page signal. It is also possible to
- * activate the first proposals with key bindings, see the
- * #GtkSourceCompletion:accelerators property.
*
- * The #GtkSourceCompletionProposal interface represents a proposal.
- * The #GtkSourceCompletionItem class is a simple implementation of this
- * interface.
- *
- * If a proposal contains extra information (see
- * gtk_source_completion_provider_get_info_widget()), it will be
- * displayed in a #GtkSourceCompletionInfo window, which appears when
- * the "Details" button is clicked.
- *
- * A #GtkSourceCompletionInfo window can also be used to display
- * calltips. When no proposals are available, it can be useful to
- * display extra information like a function prototype (number of
- * parameters, types of parameters, etc).
- *
- * Each #GtkSourceView object is associated with a #GtkSourceCompletion
- * instance. This instance can be obtained with
- * gtk_source_view_get_completion(). The #GtkSourceView class contains also the
- * #GtkSourceView::show-completion signal.
- *
- * A same #GtkSourceCompletionProvider object can be used for several
- * #GtkSourceCompletion's.
- *
- * # GtkSourceCompletion as GtkBuildable
- *
- * The GtkSourceCompletion implementation of the #GtkBuildable interface exposes
- * the info window object (see gtk_source_completion_get_info_window()) with the
- * internal-child "info_window".
- *
- * An example of a UI definition fragment with GtkSourceCompletion:
- * |[
- *
- * ]|
- */
-
-/* Idea to improve the code: use a composite widget template. This class is not
- * a GtkWidget, so some refactoring needs to be done, to have a subclass of
- * GtkSourceCompletionInfo for the main completion window.
+ * SPDX-License-Identifier: LGPL-2.1-or-later
*/
-#ifdef HAVE_CONFIG_H
-#include
-#endif
+#include "config.h"
-#include "gtksourcecompletion.h"
+#include "gtksourcebindinggroup-private.h"
#include "gtksourcecompletion-private.h"
-#include
-#include "gtksourcecompletionmodel.h"
-#include "gtksourcecompletioncontext.h"
-#include "gtksourcecompletioninfo.h"
+#include "gtksourcecompletioncontext-private.h"
+#include "gtksourcecompletionlist-private.h"
#include "gtksourcecompletionproposal.h"
#include "gtksourcecompletionprovider.h"
-#include "gtksourcecompletioncontainer.h"
#include "gtksourcebuffer.h"
-#include "gtksource-marshal.h"
-#include "gtksourceview.h"
+#include "gtksourcesignalgroup-private.h"
+#include "gtksourceview-private.h"
-enum
-{
- SHOW,
- HIDE,
- POPULATE_CONTEXT,
+#define DEFAULT_PAGE_SIZE 5
- /* Actions */
- ACTIVATE_PROPOSAL,
- MOVE_CURSOR,
- MOVE_PAGE,
+struct _GtkSourceCompletion
+{
+ GObject parent_instance;
- N_SIGNALS
-};
+ /* The GtkSourceView that we are providing results for. This can be
+ * used by providers to get a reference.
+ */
+ GtkSourceView *view;
-enum
-{
- PROP_0,
- PROP_VIEW,
- PROP_REMEMBER_INFO_VISIBILITY,
- PROP_SELECT_ON_SHOW,
- PROP_SHOW_HEADERS,
- PROP_SHOW_ICONS,
- PROP_ACCELERATORS,
- PROP_AUTO_COMPLETE_DELAY,
- PROP_PROVIDER_PAGE_SIZE,
- PROP_PROPOSAL_PAGE_SIZE
-};
+ /* A cancellable that we'll monitor to cancel anything that is currently
+ * in-flight. This is reset to a new GCancellable after each time
+ * g_cancellable_cancel() is called.
+ */
+ GCancellable *cancellable;
-struct _GtkSourceCompletionPrivate
-{
- GtkSourceCompletionInfo *main_window;
- GtkSourceCompletionInfo *info_window;
+ /* An array of providers that have been registered. These will be queried
+ * when input is provided for completion.
+ */
+ GPtrArray *providers;
- /* Bottom bar, containing the "Details" button and the selection image
- * and label. */
- GtkWidget *bottom_bar;
+ /* If we are currently performing a completion, the context is stored
+ * here. It will be cleared as soon as it's no longer valid to
+ * (re)display.
+ */
+ GtkSourceCompletionContext *context;
- /* Image and label in the bottom bar, on the right, for showing which
- * provider(s) are selected. */
- GtkImage *selection_image;
- GtkLabel *selection_label;
+ /* The signal group is used to track changes to the context while it is
+ * our current context. That includes handling notification of the first
+ * result so that we can show the window, etc.
+ */
+ GtkSourceSignalGroup *context_signals;
- /* The default widget for the info window */
- GtkLabel *default_info;
+ /* Signals to changes in the underlying GtkTextBuffer that we use to
+ * determine where and how we can do completion.
+ */
+ GtkSourceSignalGroup *buffer_signals;
- /* The "Details" button, for showing the info window */
- GtkToggleButton *info_button;
+ /* We need to track various events on the view to ensure that we don't
+ * activate at incorrect times.
+ */
+ GtkSourceSignalGroup *view_signals;
- /* List of proposals */
- GtkTreeView *tree_view_proposals;
+ /* The display popover for results */
+ GtkSourceCompletionList *display;
- GtkCellRenderer *cell_renderer_proposal;
+ /* The completion mark for alignment */
+ GtkTextMark *completion_mark;
- /* Completion management */
+ /* Our current event while processing so that we can get access to it
+ * from a callback back into the completion instance.
+ */
+ const GdkKeyEvent *current_event;
- GtkSourceCompletionModel *model_proposals;
+ /* Our cached font description to apply to views. */
+ PangoFontDescription *font_desc;
- GList *providers;
+ /* If we have a queued update to refilter after deletions, this will be
+ * set to the GSource id.
+ */
+ guint queued_update;
- GtkSourceCompletionContext *context;
- GList *active_providers;
- GList *running_providers;
+ /* This value is incremented/decremented based on if we need to suppress
+ * visibility of the completion window (and avoid doing queries).
+ */
+ guint block_count;
- guint show_timed_out_id;
+ /* Re-entrancy protection for gtk_source_completion_show(). */
+ guint showing;
- GtkTextBuffer *buffer;
+ /* The number of rows to display. This is propagated to the window if/when
+ * the window is created.
+ */
+ guint page_size;
- GList *auto_completion_selection;
- GtkSourceCompletionContext *auto_completion_context;
+ /* If we're currently being displayed */
+ guint shown : 1;
- /* Number of times the interactive completion is blocked */
- guint block_interactive_num;
+ /* If we have a completion actively in play */
+ guint waiting_for_results : 1;
- /* Properties */
+ /* If we should refilter after the in-flight context completes */
+ guint needs_refilter : 1;
- /* Weak reference to the view. You must check if view != NULL before
- * using it.
- */
- GtkSourceView *view;
- guint num_accelerators;
- guint auto_complete_delay;
- guint proposal_page_size;
- guint provider_page_size;
+ /* If the first item is automatically selected */
+ guint select_on_show : 1;
+ /* If we remember to re-show the info window */
guint remember_info_visibility : 1;
- guint select_on_show : 1;
- guint show_headers : 1;
+
+ /* If icon column is visible */
guint show_icons : 1;
+
+ guint disposed : 1;
};
-static guint signals[N_SIGNALS];
+G_DEFINE_TYPE (GtkSourceCompletion, gtk_source_completion, G_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_BUFFER,
+ PROP_PAGE_SIZE,
+ PROP_REMEMBER_INFO_VISIBILITY,
+ PROP_SELECT_ON_SHOW,
+ PROP_SHOW_ICONS,
+ PROP_VIEW,
+ N_PROPS
+};
-static void gtk_source_completion_buildable_interface_init (GtkBuildableIface *iface);
+enum {
+ ACTIVATE,
+ PROVIDER_ADDED,
+ PROVIDER_REMOVED,
+ SHOW,
+ HIDE,
+ N_SIGNALS
+};
-G_DEFINE_TYPE_WITH_CODE (GtkSourceCompletion, gtk_source_completion, G_TYPE_OBJECT,
- G_ADD_PRIVATE (GtkSourceCompletion)
- G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
- gtk_source_completion_buildable_interface_init))
+static GParamSpec *properties [N_PROPS];
+static guint signals [N_SIGNALS];
static void
-scroll_to_iter (GtkSourceCompletion *completion,
- GtkTreeIter *iter)
+display_show (GtkSourceCompletionList *display)
{
- GtkTreePath *path;
- GtkTreeIter prev_iter = *iter;
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST (display));
+
+ gtk_widget_show (GTK_WIDGET (display));
+ gtk_widget_grab_focus (GTK_WIDGET (display));
+}
- path = gtk_tree_model_get_path (GTK_TREE_MODEL (completion->priv->model_proposals),
- iter);
+static void
+display_hide (GtkSourceCompletionList *display)
+{
+ GtkWidget *view;
- gtk_tree_view_scroll_to_cell (completion->priv->tree_view_proposals,
- path, NULL,
- FALSE, 0, 0);
- gtk_tree_path_free (path);
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST (display));
- if (gtk_source_completion_model_iter_previous (completion->priv->model_proposals, &prev_iter) &&
- gtk_source_completion_model_iter_is_header (completion->priv->model_proposals, &prev_iter))
- {
- /* If we want to scroll to the first proposal of a provider,
- * it's better to show the header too, if there is a header.
- * We first scroll to the proposal, and then to the
- * header, so we are sure that the proposal is visible.
- */
+ gtk_widget_hide (GTK_WIDGET (display));
- path = gtk_tree_model_get_path (GTK_TREE_MODEL (completion->priv->model_proposals),
- &prev_iter);
+ view = gtk_widget_get_ancestor (GTK_WIDGET (display), GTK_SOURCE_TYPE_VIEW);
- gtk_tree_view_scroll_to_cell (completion->priv->tree_view_proposals,
- path, NULL,
- FALSE, 0, 0);
- gtk_tree_path_free (path);
+ if (view != NULL)
+ {
+ gtk_widget_grab_focus (view);
}
}
-/* Returns %TRUE if a proposal is selected.
- * Call g_object_unref() on @provider and @proposal when no longer needed.
- */
static gboolean
-get_selected_proposal (GtkSourceCompletion *completion,
- GtkSourceCompletionProvider **provider,
- GtkSourceCompletionProposal **proposal)
+gtk_source_completion_is_blocked (GtkSourceCompletion *self)
{
- GtkTreeIter iter;
- GtkTreeSelection *selection;
+ GtkTextBuffer *buffer;
- selection = gtk_tree_view_get_selection (completion->priv->tree_view_proposals);
+ g_assert (GTK_SOURCE_IS_COMPLETION (self));
- if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
- {
- return FALSE;
- }
+ return self->block_count > 0 ||
+ self->view == NULL ||
+ self->providers->len == 0 ||
+ !gtk_widget_get_visible (GTK_WIDGET (self->view)) ||
+ !gtk_widget_has_focus (GTK_WIDGET (self->view)) ||
+ !(buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (self->view))) ||
+ gtk_text_buffer_get_has_selection (buffer) ||
+ !GTK_SOURCE_IS_VIEW (self->view);
+}
- if (gtk_source_completion_model_iter_is_header (completion->priv->model_proposals, &iter))
- {
- return FALSE;
- }
+static PangoFontDescription *
+create_font_description (GtkSourceCompletion *self)
+{
+ PangoFontDescription *font_desc;
+ PangoContext *context;
- if (provider != NULL)
+ g_assert (GTK_SOURCE_IS_COMPLETION (self));
+
+ if (self->view == NULL)
{
- gtk_tree_model_get (GTK_TREE_MODEL (completion->priv->model_proposals), &iter,
- GTK_SOURCE_COMPLETION_MODEL_COLUMN_PROVIDER, provider,
- -1);
+ return NULL;
}
- if (proposal != NULL)
+ context = gtk_widget_get_pango_context (GTK_WIDGET (self->view));
+ font_desc = pango_font_description_copy (pango_context_get_font_description (context));
+
+ /*
+ * Work around issue where when a proposal provides "markup" and
+ * the weight is set in the font description, the markup will not
+ * have it's weight respected. This seems to be happening because the
+ * weight mask is getting set in pango_font_description_from_string()
+ * even if the the value is set to normal. That matter is complicated
+ * because PangoAttrFontDesc and PangoAttrWeight will both have the
+ * same starting offset in the PangoLayout.
+ * https://bugzilla.gnome.org/show_bug.cgi?id=755968
+ */
+ if (PANGO_WEIGHT_NORMAL == pango_font_description_get_weight (font_desc))
{
- gtk_tree_model_get (GTK_TREE_MODEL (completion->priv->model_proposals), &iter,
- GTK_SOURCE_COMPLETION_MODEL_COLUMN_PROPOSAL, proposal,
- -1);
+ pango_font_description_unset_fields (font_desc, PANGO_FONT_MASK_WEIGHT);
}
- return TRUE;
+ return g_steal_pointer (&font_desc);
}
-/* Returns %TRUE if the first proposal is selected. */
-static gboolean
-check_first_selected (GtkSourceCompletion *completion)
+gboolean
+_gtk_source_completion_get_select_on_show (GtkSourceCompletion *self)
{
- GtkTreeSelection *selection;
- GtkTreeIter iter;
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION (self), FALSE);
- if (get_selected_proposal (completion, NULL, NULL) ||
- !completion->priv->select_on_show)
- {
- return FALSE;
- }
+ return self->select_on_show;
+}
- if (!gtk_source_completion_model_first_proposal (completion->priv->model_proposals, &iter))
- {
- return FALSE;
- }
+static void
+gtk_source_completion_set_select_on_show (GtkSourceCompletion *self,
+ gboolean select_on_show)
+{
+ g_assert (GTK_SOURCE_IS_COMPLETION (self));
- selection = gtk_tree_view_get_selection (completion->priv->tree_view_proposals);
- gtk_tree_selection_select_iter (selection, &iter);
- scroll_to_iter (completion, &iter);
+ select_on_show = !!select_on_show;
- return TRUE;
+ if (self->select_on_show != select_on_show)
+ {
+ self->select_on_show = select_on_show;
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SELECT_ON_SHOW]);
+ }
}
static void
-get_iter_at_insert (GtkSourceCompletion *completion,
- GtkTextIter *iter)
+gtk_source_completion_complete_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
{
- gtk_text_buffer_get_iter_at_mark (completion->priv->buffer,
- iter,
- gtk_text_buffer_get_insert (completion->priv->buffer));
-}
+ GtkSourceCompletionContext *context = (GtkSourceCompletionContext *)object;
+ GtkSourceCompletionList *list;
+ GtkSourceCompletion *self = user_data;
+ GError *error = NULL;
-static GList *
-select_providers (GList *providers,
- GtkSourceCompletionContext *context)
-{
- GtkTextIter context_iter;
- GList *selection = NULL;
- GList *l;
+ g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (context));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (GTK_SOURCE_IS_COMPLETION (self));
- if (!gtk_source_completion_context_get_iter (context, &context_iter))
+ if (self->context == context)
{
- return NULL;
+ self->waiting_for_results = FALSE;
}
- for (l = providers; l != NULL; l = l->next)
+ if (!_gtk_source_completion_context_complete_finish (context, result, &error))
{
- GtkSourceCompletionProvider *provider = l->data;
+ g_debug ("Completion failed to complete: %s", error->message);
+ goto cleanup;
+ }
- gboolean good_activation = (gtk_source_completion_provider_get_activation (provider) &
- gtk_source_completion_context_get_activation (context)) != 0;
+ if (context != self->context)
+ goto cleanup;
- if (good_activation &&
- gtk_source_completion_provider_match (provider, context))
- {
- selection = g_list_prepend (selection, provider);
- }
+ if (self->needs_refilter)
+ {
+ /*
+ * At this point, we've gotten our new results for the context. But we had
+ * new content come in since we fired that request. So we need to ask the
+ * providers to further reduce the list based on updated query text.
+ */
+ self->needs_refilter = FALSE;
+ _gtk_source_completion_context_refilter (context);
}
- return g_list_reverse (selection);
+ list = _gtk_source_completion_get_display (self);
+
+ if (!gtk_source_completion_context_get_empty (context))
+ display_show (list);
+ else
+ display_hide (list);
+
+cleanup:
+ g_clear_error (&error);
+ g_clear_object (&self);
}
-static gint
-minimum_auto_complete_delay (GtkSourceCompletion *completion,
- GList *providers)
+static void
+_gtk_source_completion_set_context (GtkSourceCompletion *self,
+ GtkSourceCompletionContext *context)
{
- gint min_delay = completion->priv->auto_complete_delay;
+ g_assert (GTK_SOURCE_IS_COMPLETION (self));
+ g_assert (!context || GTK_SOURCE_IS_COMPLETION_CONTEXT (context));
- while (providers != NULL)
+ if (g_set_object (&self->context, context))
{
- GtkSourceCompletionProvider *provider = providers->data;
- gint delay = gtk_source_completion_provider_get_interactive_delay (provider);
-
- if (0 <= delay && delay < min_delay)
- {
- min_delay = delay;
- }
-
- providers = g_list_next (providers);
+ g_clear_handle_id (&self->queued_update, g_source_remove);
+ gtk_source_signal_group_set_target (self->context_signals, context);
}
-
- return min_delay;
}
static void
-reset_completion (GtkSourceCompletion *completion)
+gtk_source_completion_cancel (GtkSourceCompletion *self)
{
- if (completion->priv->show_timed_out_id != 0)
- {
- g_source_remove (completion->priv->show_timed_out_id);
- completion->priv->show_timed_out_id = 0;
- }
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION (self));
- if (completion->priv->context != NULL)
+ /* Nothing can re-use in-flight results now */
+ self->waiting_for_results = FALSE;
+ self->needs_refilter = FALSE;
+
+ if (self->context != NULL)
{
- /* Inform providers of cancellation through the context */
- _gtk_source_completion_context_cancel (completion->priv->context);
+ g_cancellable_cancel (self->cancellable);
+ g_clear_object (&self->cancellable);
+
+ _gtk_source_completion_set_context (self, NULL);
- g_clear_object (&completion->priv->context);
+ if (self->display != NULL)
+ {
+ _gtk_source_completion_list_set_context (self->display, NULL);
+ gtk_widget_hide (GTK_WIDGET (self->display));
+ }
}
+}
- g_list_free (completion->priv->running_providers);
- g_list_free (completion->priv->active_providers);
- completion->priv->running_providers = NULL;
- completion->priv->active_providers = NULL;
+static inline gboolean
+is_symbol_char (gunichar ch)
+{
+ return ch == '_' || g_unichar_isalnum (ch);
}
-/* A separator is a character like (, a space etc. An _ is not a separator. */
static gboolean
-is_separator (const gunichar ch)
+gtk_source_completion_compute_bounds (GtkSourceCompletion *self,
+ GtkTextIter *begin,
+ GtkTextIter *end)
{
- if (g_unichar_isprint (ch) &&
- (g_unichar_isalnum (ch) || ch == g_utf8_get_char ("_")))
+ GtkTextBuffer *buffer;
+ GtkTextMark *insert;
+ gunichar ch = 0;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION (self));
+ g_assert (begin != NULL);
+ g_assert (end != NULL);
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (self->view));
+ insert = gtk_text_buffer_get_insert (buffer);
+ gtk_text_buffer_get_iter_at_mark (buffer, end, insert);
+
+ *begin = *end;
+
+ do
{
- return FALSE;
+ if (!gtk_text_iter_backward_char (begin))
+ break;
+ ch = gtk_text_iter_get_char (begin);
}
+ while (is_symbol_char (ch));
- return TRUE;
+ if (ch && !is_symbol_char (ch))
+ {
+ gtk_text_iter_forward_char (begin);
+ }
+
+ return !gtk_text_iter_equal (begin, end);
}
-/* Assigns @start_word to the start position of the word, and @end_word to the
- * end position.
- */
static void
-get_word_iter (GtkTextBuffer *buffer,
- GtkTextIter *start_word,
- GtkTextIter *end_word)
+gtk_source_completion_start (GtkSourceCompletion *self,
+ GtkSourceCompletionActivation activation)
{
- gtk_text_buffer_get_iter_at_mark (buffer,
- end_word,
- gtk_text_buffer_get_insert (buffer));
+ g_autoptr(GtkSourceCompletionContext) context = NULL;
+ GtkTextBuffer *buffer;
+ GtkTextIter begin;
+ GtkTextIter end;
- *start_word = *end_word;
+ g_assert (GTK_SOURCE_IS_COMPLETION (self));
+ g_assert (self->context == NULL);
- while (gtk_text_iter_backward_char (start_word))
- {
- gunichar ch = gtk_text_iter_get_char (start_word);
+ g_clear_handle_id (&self->queued_update, g_source_remove);
- if (is_separator (ch))
- {
- gtk_text_iter_forward_char (start_word);
+ if (!gtk_source_completion_compute_bounds (self, &begin, &end))
+ {
+ if (activation == GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE)
return;
- }
+ begin = end;
}
-}
-static void
-replace_current_word (GtkTextBuffer *buffer,
- const gchar *new_text)
-{
- GtkTextIter word_start;
- GtkTextIter word_end;
+ context = _gtk_source_completion_context_new (self);
+ for (guint i = 0; i < self->providers->len; i++)
+ _gtk_source_completion_context_add_provider (context, g_ptr_array_index (self->providers, i));
+ _gtk_source_completion_set_context (self, context);
- get_word_iter (buffer, &word_start, &word_end);
+ self->waiting_for_results = TRUE;
+ self->needs_refilter = FALSE;
- gtk_text_buffer_begin_user_action (buffer);
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (self->view));
+ gtk_text_buffer_move_mark (buffer, self->completion_mark, &begin);
- gtk_text_buffer_delete (buffer, &word_start, &word_end);
+ _gtk_source_completion_context_complete_async (context,
+ activation,
+ &begin,
+ &end,
+ self->cancellable,
+ gtk_source_completion_complete_cb,
+ g_object_ref (self));
- if (new_text != NULL)
+ if (self->display != NULL)
{
- gtk_text_buffer_insert (buffer, &word_start, new_text, -1);
- }
+ _gtk_source_completion_list_set_context (self->display, context);
- gtk_text_buffer_end_user_action (buffer);
+ if (!gtk_source_completion_context_get_empty (context))
+ display_show (self->display);
+ else
+ display_hide (self->display);
+ }
}
static void
-update_window_position (GtkSourceCompletion *completion)
+gtk_source_completion_update (GtkSourceCompletion *self,
+ GtkSourceCompletionActivation activation)
{
- GtkSourceCompletionProvider *provider;
- GtkSourceCompletionProposal *proposal;
+ GtkTextBuffer *buffer;
+ GtkTextMark *insert;
+ GtkTextIter begin;
+ GtkTextIter end;
GtkTextIter iter;
- gboolean iter_set = FALSE;
- if (completion->priv->view == NULL)
- {
- return;
- }
+ g_assert (GTK_SOURCE_IS_COMPLETION (self));
+ g_assert (self->context != NULL);
+ g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (self->context));
- /* The model can be modified while there is no completion context, for
- * example when the headers are shown or hidden. This triggers a signal
- * to update the window position, but if there is no completion context,
- * no need to update the window position (the window is normally hidden
- * in this case). When a new population is done, this function will be
- * called again, so no problem.
+ /*
+ * First, find the boundary for the word we are trying to complete. We might
+ * be able to refine a previous query instead of making a new one which can
+ * save on a lot of backend work.
*/
- if (completion->priv->context == NULL)
- {
- return;
- }
+ gtk_source_completion_compute_bounds (self, &begin, &end);
- if (get_selected_proposal (completion, &provider, &proposal))
+ if (_gtk_source_completion_context_can_refilter (self->context, &begin, &end))
{
- GtkTextIter context_iter;
- gboolean valid_context;
+ GtkSourceCompletionList *display = _gtk_source_completion_get_display (self);
- valid_context = gtk_source_completion_context_get_iter (completion->priv->context,
- &context_iter);
+ /*
+ * Make sure we update providers that have already delivered results
+ * even though some of them won't be ready yet.
+ */
+ _gtk_source_completion_context_refilter (self->context);
- if (valid_context &&
- gtk_source_completion_provider_get_start_iter (provider,
- completion->priv->context,
- proposal,
- &iter))
+ /*
+ * If we're waiting for the results still to come in, then just mark
+ * that we need to do post-processing rather than trying to refilter now.
+ */
+ if (self->waiting_for_results)
{
- iter_set = TRUE;
+ self->needs_refilter = TRUE;
+ return;
}
- g_object_unref (provider);
- g_object_unref (proposal);
+ if (!gtk_source_completion_context_get_empty (self->context))
+ display_show (display);
+ else
+ display_hide (display);
+
+ return;
}
- if (!iter_set)
+ if (!gtk_source_completion_context_get_bounds (self->context, &begin, &end) ||
+ gtk_text_iter_equal (&begin, &end))
{
- GtkTextIter end_word;
- get_word_iter (completion->priv->buffer, &iter, &end_word);
+ if (activation == GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE)
+ {
+ gtk_source_completion_hide (self);
+ return;
+ }
+
+ goto reset;
}
- gtk_source_completion_info_move_to_iter (completion->priv->main_window,
- GTK_TEXT_VIEW (completion->priv->view),
- &iter);
-}
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (self->view));
+ insert = gtk_text_buffer_get_insert (buffer);
+ gtk_text_buffer_get_iter_at_mark (buffer, &iter, insert);
-static void
-set_info_widget (GtkSourceCompletion *completion,
- GtkWidget *new_widget)
-{
- GtkWidget *cur_widget = gtk_bin_get_child (GTK_BIN (completion->priv->info_window));
+ /*
+ * If our completion prefix bounds match the prefix that we looked
+ * at previously, we can possibly refilter the previous context instead
+ * of creating a new context.
+ */
- if (cur_widget == new_widget)
+ /*
+ * The context uses GtkTextMark which should have been advanced as
+ * the user continued to type. So if @end matches @iter (our insert
+ * location), then we can possibly update the previous context by
+ * further refining the query to a subset of the result.
+ */
+ if (gtk_text_iter_equal (&iter, &end))
{
+ gtk_source_completion_show (self);
return;
}
- if (cur_widget != NULL)
- {
- gtk_container_remove (GTK_CONTAINER (completion->priv->info_window), cur_widget);
- }
-
- gtk_container_add (GTK_CONTAINER (completion->priv->info_window), new_widget);
+reset:
+ gtk_source_completion_cancel (self);
+ gtk_source_completion_start (self, activation);
}
static void
-update_proposal_info_state (GtkSourceCompletion *completion)
+gtk_source_completion_real_hide (GtkSourceCompletion *self)
{
- GtkSourceCompletionProvider *provider = NULL;
- GtkSourceCompletionProposal *proposal = NULL;
- GtkWidget *info_widget;
+ g_assert (GTK_SOURCE_IS_COMPLETION (self));
- if (!get_selected_proposal (completion, &provider, &proposal))
+ if (self->display != NULL)
{
- gtk_widget_set_sensitive (GTK_WIDGET (completion->priv->info_button), FALSE);
- return;
+ gtk_widget_hide (GTK_WIDGET (self->display));
}
+}
- info_widget = gtk_source_completion_provider_get_info_widget (provider, proposal);
+static void
+gtk_source_completion_real_show (GtkSourceCompletion *self)
+{
+ GtkSourceCompletionList *display;
- if (info_widget != NULL)
- {
- set_info_widget (completion, info_widget);
- gtk_widget_set_sensitive (GTK_WIDGET (completion->priv->info_button), TRUE);
+ g_assert (GTK_SOURCE_IS_COMPLETION (self));
- gtk_source_completion_provider_update_info (provider,
- proposal,
- completion->priv->info_window);
+ display = _gtk_source_completion_get_display (self);
+
+ if (self->context == NULL)
+ {
+ gtk_source_completion_start (self, GTK_SOURCE_COMPLETION_ACTIVATION_USER_REQUESTED);
}
else
{
- gchar *text = gtk_source_completion_proposal_get_info (proposal);
+ gtk_source_completion_update (self, GTK_SOURCE_COMPLETION_ACTIVATION_USER_REQUESTED);
+ }
- if (text != NULL)
- {
- set_info_widget (completion, GTK_WIDGET (completion->priv->default_info));
- gtk_widget_set_sensitive (GTK_WIDGET (completion->priv->info_button), TRUE);
+ _gtk_source_completion_list_set_context (display, self->context);
- gtk_label_set_markup (completion->priv->default_info, text);
- g_free (text);
- }
- else
- {
- gtk_widget_set_sensitive (GTK_WIDGET (completion->priv->info_button), FALSE);
- }
- }
+ if (!gtk_source_completion_context_get_empty (self->context))
+ display_show (display);
+ else
+ display_hide (display);
+}
+
+static gboolean
+gtk_source_completion_queued_update_cb (gpointer user_data)
+{
+ GtkSourceCompletion *self = user_data;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION (self));
+
+ self->queued_update = 0;
- g_object_unref (provider);
- g_object_unref (proposal);
+ if (self->context != NULL)
+ gtk_source_completion_update (self, GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+gtk_source_completion_queue_update (GtkSourceCompletion *self)
+{
+ g_assert (GTK_SOURCE_IS_COMPLETION (self));
+
+ g_clear_handle_id (&self->queued_update, g_source_remove);
+
+ /*
+ * We hit this code path when the user has deleted text. We want to
+ * introduce just a bit of delay so that deleting under heavy key
+ * repeat will not stall doing lots of refiltering.
+ */
+
+ self->queued_update =
+ g_timeout_add_full (G_PRIORITY_LOW,
+ 16.7*2 + 1,
+ gtk_source_completion_queued_update_cb,
+ self,
+ NULL);
}
static void
-update_info_window_visibility (GtkSourceCompletion *completion)
+gtk_source_completion_notify_context_empty_cb (GtkSourceCompletion *self,
+ GParamSpec *pspec,
+ GtkSourceCompletionContext *context)
{
- if (gtk_widget_get_sensitive (GTK_WIDGET (completion->priv->info_button)) &&
- gtk_toggle_button_get_active (completion->priv->info_button))
+ g_assert (GTK_SOURCE_IS_COMPLETION (self));
+ g_assert (pspec != NULL);
+ g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (context));
+
+ if (context != self->context)
+ return;
+
+ if (gtk_source_completion_context_get_empty (context))
{
- gtk_widget_show (GTK_WIDGET (completion->priv->info_window));
+ if (self->display != NULL)
+ display_hide (self->display);
}
else
{
- gtk_widget_hide (GTK_WIDGET (completion->priv->info_window));
+ GtkSourceCompletionList *display = _gtk_source_completion_get_display (self);
+ display_show (display);
}
}
static void
-update_proposal_info (GtkSourceCompletion *completion)
+gtk_source_completion_buffer_delete_range_after_cb (GtkSourceCompletion *self,
+ GtkTextIter *begin,
+ GtkTextIter *end,
+ GtkTextBuffer *buffer)
{
- update_proposal_info_state (completion);
- update_info_window_visibility (completion);
-}
+ g_assert (GTK_SOURCE_IS_COMPLETION (self));
+ g_assert (GTK_SOURCE_IS_VIEW (self->view));
+ g_assert (begin != NULL);
+ g_assert (end != NULL);
+ g_assert (GTK_IS_TEXT_BUFFER (buffer));
-static void
-gtk_source_completion_show_default (GtkSourceCompletion *completion)
-{
- if (completion->priv->view == NULL)
+ if (self->context != NULL)
{
- return;
- }
+ if (!gtk_source_completion_is_blocked (self))
+ {
+ GtkTextIter b, e;
- gtk_widget_show (GTK_WIDGET (completion->priv->main_window));
+ gtk_source_completion_context_get_bounds (self->context, &b, &e);
- /* Do the autosize when the widget is visible. It doesn't work if it is
- * done before.
- */
- gtk_tree_view_columns_autosize (completion->priv->tree_view_proposals);
+ /*
+ * If they just backspaced all of the text, then we want to just hide
+ * the completion window since that can get a bit intrusive.
+ */
+ if (gtk_text_iter_equal (&b, &e))
+ {
+ g_clear_handle_id (&self->queued_update, g_source_remove);
+ gtk_source_completion_cancel (self);
+ return;
+ }
- if (!completion->priv->remember_info_visibility)
- {
- gtk_toggle_button_set_active (completion->priv->info_button, FALSE);
+ gtk_source_completion_queue_update (self);
+ }
}
-
- update_proposal_info (completion);
-
- gtk_widget_grab_focus (GTK_WIDGET (completion->priv->view));
}
static void
-gtk_source_completion_hide_default (GtkSourceCompletion *completion)
-{
- gtk_widget_hide (GTK_WIDGET (completion->priv->info_window));
- gtk_widget_hide (GTK_WIDGET (completion->priv->main_window));
-}
+gtk_source_completion_view_move_cursor_cb (GtkSourceCompletion *self,
+ GtkMovementStep step,
+ gint count,
+ gboolean extend_selection,
+ GtkSourceView *view)
+{
+ g_assert (GTK_SOURCE_IS_COMPLETION (self));
+ g_assert (GTK_SOURCE_IS_VIEW (view));
+
+ /* TODO: Should we keep the context alive while we begin a new one?
+ * Or rather, how can we avoid the hide/show of the widget that
+ * could result in flicker?
+ */
-static void
-gtk_source_completion_proposals_size_allocate (GtkSourceCompletion *completion,
- GtkAllocation *allocation,
- GtkWidget *widget)
-{
- GtkTreeViewColumn *column;
- gint cell_offset = 0;
- gint column_offset;
- gint focus_padding;
- gint horizontal_separator;
- gint x_offset = 0;
-
- if (!gtk_widget_get_realized (GTK_WIDGET (completion->priv->tree_view_proposals)))
+ if (self->display != NULL &&
+ gtk_widget_get_visible (GTK_WIDGET (self->display)))
{
- return;
+ gtk_source_completion_cancel (self);
}
+}
- gtk_widget_style_get (GTK_WIDGET (completion->priv->tree_view_proposals),
- "focus-padding", &focus_padding,
- "horizontal-separator", &horizontal_separator,
- NULL);
-
- column = gtk_tree_view_get_column (completion->priv->tree_view_proposals, 1);
- column_offset = gtk_tree_view_column_get_x_offset (column);
- gtk_tree_view_column_cell_get_position (column,
- completion->priv->cell_renderer_proposal,
- &cell_offset,
- NULL);
-
- x_offset = column_offset + cell_offset + horizontal_separator + focus_padding;
-
- gtk_tree_view_convert_bin_window_to_widget_coords (completion->priv->tree_view_proposals,
- x_offset,
- 0,
- &x_offset,
- NULL);
- gtk_widget_translate_coordinates (GTK_WIDGET (completion->priv->tree_view_proposals),
- GTK_WIDGET (completion->priv->main_window),
- x_offset,
- 0,
- &x_offset,
- NULL);
-
- _gtk_source_completion_info_set_xoffset (completion->priv->main_window, -x_offset);
+static gboolean
+is_single_char (const gchar *text,
+ gint len)
+{
+ if (len == 1)
+ return TRUE;
+ else if (len > 6)
+ return FALSE;
+ else
+ return g_utf8_strlen (text, len) == 1;
}
static void
-gtk_source_completion_activate_proposal (GtkSourceCompletion *completion)
+gtk_source_completion_buffer_insert_text_after_cb (GtkSourceCompletion *self,
+ GtkTextIter *iter,
+ const gchar *text,
+ gint len,
+ GtkTextBuffer *buffer)
{
- GtkSourceCompletionProvider *provider = NULL;
- GtkSourceCompletionProposal *proposal = NULL;
- GtkTextIter insert_iter;
- GtkTextIter context_iter;
- gboolean valid_context;
- gboolean activated;
-
- if (completion->priv->view == NULL)
+ GtkSourceCompletionActivation activation = GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE;
+ GtkTextIter begin;
+ GtkTextIter end;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION (self));
+ g_assert (iter != NULL);
+ g_assert (text != NULL);
+ g_assert (len > 0);
+ g_assert (GTK_IS_TEXT_BUFFER (buffer));
+
+ g_clear_handle_id (&self->queued_update, g_source_remove);
+
+ if (gtk_source_completion_is_blocked (self) || !is_single_char (text, len))
{
+ gtk_source_completion_cancel (self);
return;
}
- if (!get_selected_proposal (completion, &provider, &proposal))
+ if (!gtk_source_completion_compute_bounds (self, &begin, &end))
{
+ GtkTextIter cur = end;
+
+ if (gtk_text_iter_backward_char (&cur))
+ {
+ gunichar ch = gtk_text_iter_get_char (&cur);
+
+ for (guint i = 0; i < self->providers->len; i++)
+ {
+ GtkSourceCompletionProvider *provider = g_ptr_array_index (self->providers, i);
+
+ if (gtk_source_completion_provider_is_trigger (provider, &end, ch))
+ {
+ /*
+ * We got a trigger, but we failed to continue the bounds of a previous
+ * completion. We need to cancel the previous completion (if any) first
+ * and then try to start a new completion due to trigger.
+ */
+ gtk_source_completion_cancel (self);
+ activation = GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE;
+ goto do_completion;
+ }
+ }
+ }
+
+ gtk_source_completion_cancel (self);
return;
}
- get_iter_at_insert (completion, &insert_iter);
+do_completion:
- gtk_source_completion_block_interactive (completion);
-
- activated = gtk_source_completion_provider_activate_proposal (provider, proposal, &insert_iter);
-
- valid_context = (completion->priv->context != NULL &&
- gtk_source_completion_context_get_iter (completion->priv->context,
- &context_iter));
-
- if (!activated && valid_context)
- {
- GtkTextIter start_iter;
- gchar *text = gtk_source_completion_proposal_get_text (proposal);
-
- gboolean has_start = gtk_source_completion_provider_get_start_iter (provider,
- completion->priv->context,
- proposal,
- &start_iter);
-
- if (has_start)
- {
- gtk_text_buffer_begin_user_action (completion->priv->buffer);
- gtk_text_buffer_delete (completion->priv->buffer, &start_iter, &insert_iter);
- gtk_text_buffer_insert (completion->priv->buffer, &start_iter, text, -1);
- gtk_text_buffer_end_user_action (completion->priv->buffer);
- }
- else
- {
- replace_current_word (completion->priv->buffer, text);
- }
-
- g_free (text);
- }
-
- gtk_source_completion_unblock_interactive (completion);
-
- gtk_source_completion_hide (completion);
-
- g_object_unref (provider);
- g_object_unref (proposal);
-}
-
-static void
-update_info_position (GtkSourceCompletion *completion)
-{
- GdkDisplay *display;
- GdkMonitor *monitor;
- GdkWindow *window;
- GdkRectangle geom;
- gint x, y;
- gint width, height;
- gint info_width;
-
- gtk_window_get_position (GTK_WINDOW (completion->priv->main_window), &x, &y);
- gtk_window_get_size (GTK_WINDOW (completion->priv->main_window), &width, &height);
- gtk_window_get_size (GTK_WINDOW (completion->priv->info_window), &info_width, NULL);
-
- display = gtk_widget_get_display (GTK_WIDGET (completion->priv->main_window));
- window = gtk_widget_get_window (GTK_WIDGET (completion->priv->main_window));
- monitor = gdk_display_get_monitor_at_window (display, window);
- gdk_monitor_get_geometry (monitor, &geom);
-
- /* Determine on which side to place it */
- if (x + width + info_width >= geom.width)
- {
- x -= info_width;
- }
- else
- {
- x += width;
- }
-
- gtk_window_move (GTK_WINDOW (completion->priv->info_window), x, y);
-}
-
-static GtkSourceCompletionProvider *
-get_visible_provider (GtkSourceCompletion *completion)
-{
- GList *visible = gtk_source_completion_model_get_visible_providers (completion->priv->model_proposals);
-
- if (visible != NULL)
- {
- return GTK_SOURCE_COMPLETION_PROVIDER (visible->data);
- }
- else
- {
- return NULL;
- }
-}
-
-static void
-get_num_visible_providers (GtkSourceCompletion *completion,
- guint *num,
- guint *current)
-{
- GList *providers = gtk_source_completion_model_get_providers (completion->priv->model_proposals);
- GtkSourceCompletionProvider *visible = get_visible_provider (completion);
-
- *num = g_list_length (providers);
- *current = 0;
-
- if (visible != NULL)
- {
- gint idx = g_list_index (providers, visible);
- g_return_if_fail (idx != -1);
-
- *current = idx + 1;
- }
-
- g_list_free (providers);
-}
-
-static void
-update_selection_label (GtkSourceCompletion *completion)
-{
- guint pos;
- guint num;
- gchar *name;
- gchar *selection_text;
- GtkSourceCompletionProvider *visible;
-
- get_num_visible_providers (completion, &num, &pos);
-
- if (num <= 1)
- {
- /* At most one provider. All the proposals are shown. */
- gtk_image_clear (completion->priv->selection_image);
- gtk_widget_hide (GTK_WIDGET (completion->priv->selection_label));
- return;
- }
-
- visible = get_visible_provider (completion);
-
- if (visible == NULL)
- {
- /* Translators: "All" is used as a label in the status bar of the
- popup, telling that all completion pages are shown. */
- name = g_strdup_printf("%s", _("All"));
-
- gtk_image_clear (completion->priv->selection_image);
- }
- else
- {
- gchar *temp_name = gtk_source_completion_provider_get_name (visible);
- name = g_markup_escape_text (temp_name, -1);
- g_free (temp_name);
-
- gtk_image_set_from_pixbuf (completion->priv->selection_image,
- gtk_source_completion_provider_get_icon (visible));
- }
-
- selection_text = g_strdup_printf ("%s (%d/%d)", name, pos + 1, num + 1);
- gtk_label_set_markup (completion->priv->selection_label, selection_text);
- gtk_widget_show (GTK_WIDGET (completion->priv->selection_label));
-
- g_free (selection_text);
- g_free (name);
-}
-
-static gboolean
-get_next_iter (GtkSourceCompletion *completion,
- gint num,
- GtkTreeIter *iter)
-{
- GtkTreeSelection *selection;
- gboolean has_selection;
-
- selection = gtk_tree_view_get_selection (completion->priv->tree_view_proposals);
- has_selection = gtk_tree_selection_get_selected (selection, NULL, iter);
-
- if (!has_selection)
- {
- return gtk_source_completion_model_first_proposal (completion->priv->model_proposals,
- iter);
- }
-
- while (num > 0)
- {
- if (!gtk_source_completion_model_next_proposal (completion->priv->model_proposals, iter))
- {
- return gtk_source_completion_model_last_proposal (completion->priv->model_proposals,
- iter);
- }
-
- num--;
- }
-
- return TRUE;
-}
-
-static gboolean
-get_previous_iter (GtkSourceCompletion *completion,
- gint num,
- GtkTreeIter *iter)
-{
- GtkTreeSelection *selection;
- gboolean has_selection;
-
- selection = gtk_tree_view_get_selection (completion->priv->tree_view_proposals);
- has_selection = gtk_tree_selection_get_selected (selection, NULL, iter);
-
- if (!has_selection)
- {
- return gtk_source_completion_model_last_proposal (completion->priv->model_proposals,
- iter);
- }
-
- while (num > 0)
- {
- if (!gtk_source_completion_model_previous_proposal (completion->priv->model_proposals,
- iter))
- {
- return gtk_source_completion_model_first_proposal (completion->priv->model_proposals,
- iter);
- }
-
- num--;
- }
-
- return TRUE;
-}
-
-static void
-gtk_source_completion_move_cursor (GtkSourceCompletion *completion,
- GtkScrollStep step,
- gint num)
-{
- GtkTreeIter iter;
- gboolean ok;
-
- if (step == GTK_SCROLL_ENDS)
- {
- if (num > 0)
- {
- ok = gtk_source_completion_model_last_proposal (completion->priv->model_proposals,
- &iter);
- }
- else
- {
- ok = gtk_source_completion_model_first_proposal (completion->priv->model_proposals,
- &iter);
- }
- }
- else
- {
- if (step == GTK_SCROLL_PAGES)
- {
- num *= completion->priv->proposal_page_size;
- }
-
- if (num > 0)
- {
- ok = get_next_iter (completion, num, &iter);
- }
- else
- {
- ok = get_previous_iter (completion, -1 * num, &iter);
- }
- }
-
- if (ok)
- {
- GtkTreeSelection *selection;
-
- selection = gtk_tree_view_get_selection (completion->priv->tree_view_proposals);
- gtk_tree_selection_select_iter (selection, &iter);
-
- scroll_to_iter (completion, &iter);
- }
-}
-
-static GList *
-get_last_provider (GtkSourceCompletion *completion)
-{
- GList *providers = gtk_source_completion_model_get_providers (completion->priv->model_proposals);
- GList *ret;
-
- g_return_val_if_fail (providers != NULL, NULL);
-
- if (providers->next == NULL)
- {
- ret = NULL;
- }
- else
- {
- ret = g_list_copy (g_list_last (providers));
- }
-
- g_list_free (providers);
- return ret;
-}
-
-static GList *
-providers_cycle_forward (GList *all_providers,
- GList *position,
- gint num)
-{
- GList *l = position;
- gint i;
-
- if (all_providers == NULL || all_providers->next == NULL)
- {
- return NULL;
- }
-
- for (i = 0; i < num; i++)
- {
- l = l == NULL ? all_providers : l->next;
- }
-
- return l;
-}
-
-static GList *
-providers_cycle_backward (GList *all_providers,
- GList *position,
- gint num)
-{
- gint i;
- GList *l = position;
- GList *end = g_list_last (all_providers);
-
- if (all_providers == NULL || all_providers->next == NULL)
- {
- return NULL;
- }
-
- for (i = 0; i < num; i++)
- {
- l = l == NULL ? end : l->prev;
- }
-
- return l;
-}
-
-static GList *
-get_next_provider (GtkSourceCompletion *completion,
- gint num)
-{
- GList *providers;
- GList *visible_providers;
- GList *position;
- GList *ret;
-
- providers = gtk_source_completion_model_get_providers (completion->priv->model_proposals);
- visible_providers = gtk_source_completion_model_get_visible_providers (completion->priv->model_proposals);
-
- if (visible_providers == NULL)
- {
- position = NULL;
- }
- else
- {
- position = g_list_find (providers, visible_providers->data);
- }
-
- position = providers_cycle_forward (providers, position, num);
-
- if (position == NULL)
- {
- ret = NULL;
- }
- else
- {
- ret = g_list_append (NULL, position->data);
- }
-
- g_list_free (providers);
-
- return ret;
-}
-
-static GList *
-get_previous_provider (GtkSourceCompletion *completion,
- gint num)
-{
- GList *providers;
- GList *visible_providers;
- GList *position;
- GList *ret;
-
- providers = gtk_source_completion_model_get_providers (completion->priv->model_proposals);
- visible_providers = gtk_source_completion_model_get_visible_providers (completion->priv->model_proposals);
-
- if (visible_providers == NULL)
- {
- position = NULL;
- }
- else
- {
- position = g_list_find (providers, visible_providers->data);
- }
-
- position = providers_cycle_backward (providers, position, num);
-
- if (position == NULL)
- {
- ret = NULL;
- }
- else
- {
- ret = g_list_append (NULL, position->data);
- }
-
- g_list_free (providers);
-
- return ret;
-}
-
-static void
-gtk_source_completion_move_page (GtkSourceCompletion *completion,
- GtkScrollStep step,
- gint num)
-{
- GList *visible_providers = NULL;
-
- if (step == GTK_SCROLL_ENDS)
- {
- if (num > 0)
- {
- visible_providers = get_last_provider (completion);
- }
- else
- {
- visible_providers = NULL;
- }
- }
- else
- {
- if (step == GTK_SCROLL_PAGES)
- {
- num *= completion->priv->provider_page_size;
- }
-
- if (num > 0)
- {
- visible_providers = get_next_provider (completion, num);
- }
- else
- {
- visible_providers = get_previous_provider (completion, -1 * num);
- }
- }
-
- gtk_tree_view_set_model (completion->priv->tree_view_proposals, NULL);
- gtk_tree_view_columns_autosize (completion->priv->tree_view_proposals);
-
- gtk_source_completion_model_set_visible_providers (completion->priv->model_proposals,
- visible_providers);
-
- gtk_tree_view_set_model (completion->priv->tree_view_proposals,
- GTK_TREE_MODEL (completion->priv->model_proposals));
-
- update_selection_label (completion);
- check_first_selected (completion);
-
- g_list_free (visible_providers);
-}
-
-/* Begins at 0. Returns -1 if no accelerators available for @iter. */
-static gint
-get_accel_at_iter (GtkSourceCompletion *completion,
- GtkTreeIter *iter)
-{
- GtkTreeIter it;
- guint accel;
-
- if (gtk_source_completion_model_iter_is_header (completion->priv->model_proposals, iter))
- {
- return -1;
- }
-
- if (!gtk_source_completion_model_first_proposal (completion->priv->model_proposals, &it))
- {
- g_return_val_if_reached (-1);
- }
-
- for (accel = 0; accel < completion->priv->num_accelerators; accel++)
- {
- if (gtk_source_completion_model_iter_equal (completion->priv->model_proposals,
- iter,
- &it))
- {
- return accel;
- }
-
- if (!gtk_source_completion_model_next_proposal (completion->priv->model_proposals, &it))
- {
- return -1;
- }
- }
-
- return -1;
-}
-
-static void
-render_proposal_accelerator_func (GtkTreeViewColumn *column,
- GtkCellRenderer *cell,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- GtkSourceCompletion *completion)
-{
- gint accel = get_accel_at_iter (completion, iter);
- gchar *text = NULL;
-
- if (accel != -1)
- {
- text = g_strdup_printf ("%d", (accel + 1) % 10);
- }
-
- g_object_set (cell, "markup", text, NULL);
- g_free (text);
-}
-
-static gboolean
-activate_by_accelerator (GtkSourceCompletion *completion,
- gint num)
-{
- GtkTreeSelection *selection;
- GtkTreeIter iter;
- gint i;
-
- if (completion->priv->num_accelerators == 0)
- {
- return FALSE;
- }
-
- num = num == 0 ? 9 : num - 1;
-
- if (num < 0 || completion->priv->num_accelerators <= (guint)num)
- {
- return FALSE;
- }
-
- if (!gtk_source_completion_model_first_proposal (completion->priv->model_proposals, &iter))
- {
- return FALSE;
- }
-
- for (i = 0; i < num; i++)
- {
- if (!gtk_source_completion_model_next_proposal (completion->priv->model_proposals, &iter))
- {
- return FALSE;
- }
- }
-
- selection = gtk_tree_view_get_selection (completion->priv->tree_view_proposals);
- gtk_tree_selection_select_iter (selection, &iter);
- gtk_source_completion_activate_proposal (completion);
-
- return TRUE;
-}
-
-static void
-selection_changed_cb (GtkTreeSelection *selection,
- GtkSourceCompletion *completion)
-{
- update_proposal_info (completion);
-
- if (get_selected_proposal (completion, NULL, NULL))
- {
- update_window_position (completion);
- }
-}
-
-static gboolean
-gtk_source_completion_configure_event (GtkWidget *widget,
- GdkEventConfigure *event,
- GtkSourceCompletion *completion)
-{
- update_info_position (completion);
- return FALSE;
-}
-
-static gboolean
-hide_completion_cb (GtkSourceCompletion *completion)
-{
- gtk_source_completion_hide (completion);
- return FALSE;
-}
-
-static gboolean
-view_key_press_event_cb (GtkSourceView *view,
- GdkEventKey *event,
- GtkSourceCompletion *completion)
-{
- static gboolean mnemonic_keyval_set = FALSE;
- static guint mnemonic_keyval = GDK_KEY_VoidSymbol;
- GdkModifierType mod;
- GtkBindingSet *binding_set;
-
- if (!gtk_widget_get_visible (GTK_WIDGET (completion->priv->main_window)))
- {
- return FALSE;
- }
-
- if (G_UNLIKELY (!mnemonic_keyval_set))
- {
- const gchar *label_text = gtk_button_get_label (GTK_BUTTON (completion->priv->info_button));
- GtkWidget *label = gtk_label_new_with_mnemonic (label_text);
- g_object_ref_sink (label);
-
- mnemonic_keyval = gtk_label_get_mnemonic_keyval (GTK_LABEL (label));
- mnemonic_keyval_set = TRUE;
-
- g_object_unref (label);
- }
-
- mod = gtk_accelerator_get_default_mod_mask () & event->state;
-
- /* Handle info button mnemonic */
- if ((mod & GDK_MOD1_MASK) != 0 &&
- event->keyval == mnemonic_keyval &&
- gtk_widget_get_sensitive (GTK_WIDGET (completion->priv->info_button)))
- {
- gtk_toggle_button_set_active (completion->priv->info_button,
- !gtk_toggle_button_get_active (completion->priv->info_button));
- return TRUE;
- }
-
- if ((mod & GDK_MOD1_MASK) != 0 &&
- GDK_KEY_0 <= event->keyval && event->keyval <= GDK_KEY_9)
- {
- if (activate_by_accelerator (completion, event->keyval - GDK_KEY_0))
- {
- return TRUE;
- }
- }
-
- binding_set = gtk_binding_set_by_class (GTK_SOURCE_COMPLETION_GET_CLASS (completion));
-
- if (gtk_binding_set_activate (binding_set,
- event->keyval,
- event->state,
- G_OBJECT (completion)))
- {
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-buffer_mark_set_cb (GtkTextBuffer *buffer,
- GtkTextIter *iter,
- GtkTextMark *mark,
- GtkSourceCompletion *completion)
-{
- if (mark == gtk_text_buffer_get_insert (buffer))
- {
- gtk_source_completion_hide (completion);
- }
-}
-
-static void
-update_transient_for_info (GObject *window,
- GParamSpec *spec,
- GtkSourceCompletion *completion)
-{
- gtk_window_set_transient_for (GTK_WINDOW (completion->priv->info_window),
- gtk_window_get_transient_for (GTK_WINDOW (completion->priv->main_window)));
-}
-
-static void
-replace_model (GtkSourceCompletion *completion)
-{
- if (completion->priv->model_proposals != NULL)
- {
- g_object_unref (completion->priv->model_proposals);
- }
-
- completion->priv->model_proposals = gtk_source_completion_model_new ();
-
- gtk_source_completion_model_set_show_headers (completion->priv->model_proposals,
- completion->priv->show_headers);
-}
-
-/* Takes ownership of @providers and @context. */
-static void
-update_completion (GtkSourceCompletion *completion,
- GList *providers,
- GtkSourceCompletionContext *context)
-{
- GList *item;
- GtkTextIter context_iter;
- gboolean valid_context;
-
- /* Copy the parameters, because they can be freed by reset_completion(). */
- GList *providers_copy = g_list_copy (providers);
- GtkSourceCompletionContext *context_copy = g_object_ref_sink (context);
-
- /* Make sure to first cancel any running completion */
- reset_completion (completion);
-
- completion->priv->context = context_copy;
- completion->priv->running_providers = g_list_copy (providers_copy);
- completion->priv->active_providers = g_list_copy (providers_copy);
-
- /* Create a new CompletionModel */
- gtk_tree_view_set_model (completion->priv->tree_view_proposals, NULL);
- gtk_tree_view_columns_autosize (completion->priv->tree_view_proposals);
-
- replace_model (completion);
-
- valid_context = gtk_source_completion_context_get_iter (context_copy, &context_iter);
-
- if (valid_context)
- {
- for (item = providers_copy; item != NULL; item = g_list_next (item))
- {
- GtkSourceCompletionProvider *provider = item->data;
- gtk_source_completion_provider_populate (provider, context_copy);
- }
- }
-
- g_list_free (providers_copy);
-}
-
-static gboolean
-auto_completion_final (GtkSourceCompletion *completion)
-{
- /* Store and set to NULL because update_completion will cancel the last
- completion, which will also remove the timeout source which in turn
- would free these guys */
- GtkSourceCompletionContext *context = completion->priv->auto_completion_context;
- GList *selection = completion->priv->auto_completion_selection;
-
- completion->priv->auto_completion_context = NULL;
- completion->priv->auto_completion_selection = NULL;
-
- update_completion (completion, selection, context);
-
- g_list_free (selection);
- g_object_unref (context);
- return G_SOURCE_REMOVE;
-}
-
-static void
-auto_completion_destroy (GtkSourceCompletion *completion)
-{
- if (completion->priv->auto_completion_context != NULL)
- {
- g_object_unref (completion->priv->auto_completion_context);
- completion->priv->auto_completion_context = NULL;
- }
-
- g_list_free (completion->priv->auto_completion_selection);
- completion->priv->auto_completion_selection = NULL;
-}
-
-static void
-start_interactive_completion (GtkSourceCompletion *completion,
- GtkTextIter *iter)
-{
- GtkSourceCompletionContext *context;
- GList *providers;
- gint delay;
-
- reset_completion (completion);
-
- /* Create the context */
- context = gtk_source_completion_create_context (completion, iter);
- g_object_ref_sink (context);
-
- g_object_set (context,
- "activation",
- GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE,
- NULL);
-
- g_signal_emit (completion, signals[POPULATE_CONTEXT], 0, context);
-
- /* Select providers */
- providers = select_providers (completion->priv->providers, context);
-
- if (providers == NULL)
- {
- g_object_unref (context);
- return;
- }
-
- /* Create the timeout */
- delay = minimum_auto_complete_delay (completion, providers);
- completion->priv->auto_completion_context = context;
- completion->priv->auto_completion_selection = providers;
-
- completion->priv->show_timed_out_id =
- g_timeout_add_full (G_PRIORITY_DEFAULT,
- delay,
- (GSourceFunc)auto_completion_final,
- completion,
- (GDestroyNotify)auto_completion_destroy);
-}
-
-static void
-update_active_completion (GtkSourceCompletion *completion,
- GtkTextIter *new_iter)
-{
- GList *selected_providers;
-
- g_assert (completion->priv->context != NULL);
-
- g_object_set (completion->priv->context,
- "iter", new_iter,
- NULL);
-
- selected_providers = select_providers (completion->priv->providers,
- completion->priv->context);
-
- if (selected_providers != NULL)
- {
- update_completion (completion,
- selected_providers,
- completion->priv->context);
-
- g_list_free (selected_providers);
- }
- else
- {
- gtk_source_completion_hide (completion);
- }
-}
-
-static void
-buffer_delete_range_cb (GtkTextBuffer *buffer,
- GtkTextIter *start,
- GtkTextIter *end,
- GtkSourceCompletion *completion)
-{
- if (completion->priv->context != NULL)
- {
- update_active_completion (completion, start);
- }
-}
-
-static void
-buffer_insert_text_cb (GtkTextBuffer *buffer,
- GtkTextIter *location,
- gchar *text,
- gint len,
- GtkSourceCompletion *completion)
-{
- if (completion->priv->context != NULL)
- {
- update_active_completion (completion, location);
- }
+ if (self->context == NULL)
+ gtk_source_completion_start (self, activation);
else
- {
- start_interactive_completion (completion, location);
- }
+ gtk_source_completion_update (self, activation);
}
static void
-update_bottom_bar_visibility (GtkSourceCompletion *completion)
+gtk_source_completion_buffer_mark_set_cb (GtkSourceCompletion *self,
+ const GtkTextIter *iter,
+ GtkTextMark *mark,
+ GtkTextBuffer *buffer)
{
- GList *providers;
- guint nb_providers;
+ g_assert (GTK_SOURCE_IS_COMPLETION (self));
+ g_assert (GTK_IS_TEXT_MARK (mark));
+ g_assert (GTK_IS_TEXT_BUFFER (buffer));
- providers = gtk_source_completion_model_get_providers (completion->priv->model_proposals);
- nb_providers = g_list_length (providers);
- g_list_free (providers);
-
- if (nb_providers > 1)
- {
- gtk_widget_show (completion->priv->bottom_bar);
+ if (mark != gtk_text_buffer_get_insert (buffer))
return;
- }
-
- if (gtk_source_completion_model_has_info (completion->priv->model_proposals))
- {
- gtk_widget_show (completion->priv->bottom_bar);
- }
- else
- {
- gtk_widget_hide (completion->priv->bottom_bar);
- }
-}
-
-static void
-style_context_changed (GtkStyleContext *style_context,
- GtkSourceCompletion *completion)
-{
- PangoFontDescription *font_desc = NULL;
-
- gtk_style_context_save (style_context);
- gtk_style_context_set_state (style_context, GTK_STATE_FLAG_NORMAL);
-
- gtk_style_context_get (style_context,
- gtk_style_context_get_state (style_context),
- GTK_STYLE_PROPERTY_FONT, &font_desc,
- NULL);
-
- gtk_style_context_restore (style_context);
- /*
- * Work around issue where when a proposal provides "markup" and
- * the weight is set in the font description, the markup will not
- * have it's weight respected. This seems to be happening because the
- * weight mask is getting set in pango_font_description_from_string()
- * even if the the value is set to normal. That matter is complicated
- * because PangoAttrFontDesc and PangoAttrWeight will both have the
- * same starting offset in the PangoLayout.
- * https://bugzilla.gnome.org/show_bug.cgi?id=755968
- */
- if (PANGO_WEIGHT_NORMAL == pango_font_description_get_weight (font_desc))
+ if (_gtk_source_completion_context_iter_invalidates (self->context, iter))
{
- pango_font_description_unset_fields (font_desc, PANGO_FONT_MASK_WEIGHT);
+ gtk_source_completion_cancel (self);
}
-
- g_object_set (completion->priv->cell_renderer_proposal,
- "font-desc", font_desc,
- NULL);
-
- pango_font_description_free (font_desc);
}
-static void
-populating_done (GtkSourceCompletion *completion,
- GtkSourceCompletionContext *context)
+GtkSourceCompletion *
+_gtk_source_completion_new (GtkSourceView *view)
{
- if (gtk_source_completion_model_is_empty (completion->priv->model_proposals, TRUE))
- {
- gtk_source_completion_hide (completion);
- return;
- }
-
- gtk_tree_view_set_model (completion->priv->tree_view_proposals,
- GTK_TREE_MODEL (completion->priv->model_proposals));
-
- update_selection_label (completion);
- update_bottom_bar_visibility (completion);
-
- if (!check_first_selected (completion))
- {
- /* Update the window position only if the first proposal is not
- * selected, because if it is selected, the window position will
- * already be updated.
- */
- update_window_position (completion);
- }
-
- if (!gtk_widget_get_visible (GTK_WIDGET (completion->priv->main_window)))
- {
- g_signal_emit (completion, signals[SHOW], 0);
- }
+ return g_object_new (GTK_SOURCE_TYPE_COMPLETION,
+ "view", view,
+ NULL);
}
static void
-gtk_source_completion_dispose (GObject *object)
+gtk_source_completion_set_view (GtkSourceCompletion *self,
+ GtkSourceView *view)
{
- GtkSourceCompletion *completion = GTK_SOURCE_COMPLETION (object);
-
- reset_completion (completion);
-
- if (completion->priv->view != NULL)
- {
- g_object_remove_weak_pointer (G_OBJECT (completion->priv->view),
- (gpointer *)&completion->priv->view);
-
- completion->priv->view = NULL;
- }
-
- g_clear_object (&completion->priv->buffer);
- g_clear_object (&completion->priv->default_info);
- g_clear_object (&completion->priv->model_proposals);
+ g_assert (GTK_SOURCE_IS_COMPLETION (self));
+ g_assert (GTK_SOURCE_IS_VIEW (view));
- if (completion->priv->info_window != NULL)
+ if (g_set_weak_pointer (&self->view, view))
{
- gtk_widget_destroy (GTK_WIDGET (completion->priv->info_window));
- completion->priv->info_window = NULL;
+ gtk_source_signal_group_set_target (self->view_signals, view);
+ g_object_bind_property (view, "buffer",
+ self->buffer_signals, "target",
+ G_BINDING_SYNC_CREATE);
}
-
- if (completion->priv->main_window != NULL)
- {
- gtk_widget_destroy (GTK_WIDGET (completion->priv->main_window));
- completion->priv->main_window = NULL;
- }
-
- g_list_free_full (completion->priv->providers, g_object_unref);
- completion->priv->providers = NULL;
-
- G_OBJECT_CLASS (gtk_source_completion_parent_class)->dispose (object);
-}
-
-/* Unconditionnally block interactive completion, without taking into account
- * priv->block_interactive_num.
- * g_signal_handlers_block_by_func() has a counter too, so you may think that
- * block_interactive_num is useless. But it is useful when the buffer changes,
- * to keep the signal handler blocked on the new buffer.
- */
-static void
-block_interactive (GtkSourceCompletion *completion)
-{
- g_signal_handlers_block_by_func (completion->priv->buffer,
- buffer_insert_text_cb,
- completion);
-
- g_signal_handlers_block_by_func (completion->priv->buffer,
- buffer_delete_range_cb,
- completion);
}
static void
-connect_buffer (GtkSourceCompletion *completion)
+on_buffer_signals_bind (GtkSourceCompletion *self,
+ GtkSourceBuffer *buffer,
+ GtkSourceSignalGroup *signals_)
{
- GtkTextBuffer *new_buffer = NULL;
+ GtkTextIter where;
- if (completion->priv->view != NULL)
- {
- new_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (completion->priv->view));
- }
-
- if (completion->priv->buffer == new_buffer)
- {
- return;
- }
-
- if (completion->priv->buffer != NULL)
- {
- g_signal_handlers_disconnect_by_func (completion->priv->buffer,
- buffer_mark_set_cb,
- completion);
-
- g_signal_handlers_disconnect_by_func (completion->priv->buffer,
- gtk_source_completion_block_interactive,
- completion);
-
- g_signal_handlers_disconnect_by_func (completion->priv->buffer,
- gtk_source_completion_unblock_interactive,
- completion);
-
- g_signal_handlers_disconnect_by_func (completion->priv->buffer,
- buffer_delete_range_cb,
- completion);
-
- g_signal_handlers_disconnect_by_func (completion->priv->buffer,
- buffer_insert_text_cb,
- completion);
-
- reset_completion (completion);
-
- g_object_unref (completion->priv->buffer);
- }
-
- completion->priv->buffer = new_buffer;
+ g_assert (GTK_SOURCE_IS_COMPLETION (self));
+ g_assert (GTK_SOURCE_IS_BUFFER (buffer));
+ g_assert (GTK_SOURCE_IS_SIGNAL_GROUP (signals_));
- if (new_buffer == NULL)
- {
+ if (self->disposed)
return;
- }
-
- g_object_ref (completion->priv->buffer);
-
- g_signal_connect_object (new_buffer,
- "mark-set",
- G_CALLBACK (buffer_mark_set_cb),
- completion,
- G_CONNECT_AFTER);
-
- g_signal_connect_object (new_buffer,
- "undo",
- G_CALLBACK (gtk_source_completion_block_interactive),
- completion,
- G_CONNECT_SWAPPED);
-
- g_signal_connect_object (new_buffer,
- "undo",
- G_CALLBACK (gtk_source_completion_unblock_interactive),
- completion,
- G_CONNECT_SWAPPED | G_CONNECT_AFTER);
-
- g_signal_connect_object (new_buffer,
- "redo",
- G_CALLBACK (gtk_source_completion_block_interactive),
- completion,
- G_CONNECT_SWAPPED);
-
- g_signal_connect_object (new_buffer,
- "redo",
- G_CALLBACK (gtk_source_completion_unblock_interactive),
- completion,
- G_CONNECT_SWAPPED | G_CONNECT_AFTER);
-
- g_signal_connect_object (new_buffer,
- "delete-range",
- G_CALLBACK (buffer_delete_range_cb),
- completion,
- G_CONNECT_AFTER);
-
- g_signal_connect_object (new_buffer,
- "insert-text",
- G_CALLBACK (buffer_insert_text_cb),
- completion,
- G_CONNECT_AFTER);
-
- if (completion->priv->block_interactive_num > 0)
- {
- block_interactive (completion);
- }
-}
-
-static void
-connect_view (GtkSourceCompletion *completion,
- GtkSourceView *view)
-{
- g_assert (completion->priv->view == NULL);
- completion->priv->view = view;
-
- g_object_add_weak_pointer (G_OBJECT (view),
- (gpointer *)&completion->priv->view);
-
- g_signal_connect_object (completion->priv->view,
- "focus-out-event",
- G_CALLBACK (hide_completion_cb),
- completion,
- G_CONNECT_SWAPPED);
-
- g_signal_connect_object (completion->priv->view,
- "button-press-event",
- G_CALLBACK (hide_completion_cb),
- completion,
- G_CONNECT_SWAPPED);
-
- g_signal_connect_object (completion->priv->view,
- "key-press-event",
- G_CALLBACK (view_key_press_event_cb),
- completion,
- 0);
-
- g_signal_connect_object (completion->priv->view,
- "paste-clipboard",
- G_CALLBACK (gtk_source_completion_block_interactive),
- completion,
- G_CONNECT_SWAPPED);
-
- g_signal_connect_object (completion->priv->view,
- "paste-clipboard",
- G_CALLBACK (gtk_source_completion_unblock_interactive),
- completion,
- G_CONNECT_SWAPPED | G_CONNECT_AFTER);
-
- connect_buffer (completion);
-
- g_signal_connect_object (completion->priv->view,
- "notify::buffer",
- G_CALLBACK (connect_buffer),
- completion,
- G_CONNECT_SWAPPED);
-}
-
-static void
-gtk_source_completion_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkSourceCompletion *completion;
-
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION (object));
-
- completion = GTK_SOURCE_COMPLETION (object);
-
- switch (prop_id)
- {
- case PROP_VIEW:
- g_value_set_object (value, completion->priv->view);
- break;
- case PROP_REMEMBER_INFO_VISIBILITY:
- g_value_set_boolean (value, completion->priv->remember_info_visibility);
- break;
- case PROP_SELECT_ON_SHOW:
- g_value_set_boolean (value, completion->priv->select_on_show);
- break;
- case PROP_SHOW_HEADERS:
- g_value_set_boolean (value, completion->priv->show_headers);
- break;
- case PROP_SHOW_ICONS:
- g_value_set_boolean (value, completion->priv->show_icons);
- break;
- case PROP_ACCELERATORS:
- g_value_set_uint (value, completion->priv->num_accelerators);
- break;
- case PROP_AUTO_COMPLETE_DELAY:
- g_value_set_uint (value, completion->priv->auto_complete_delay);
- break;
- case PROP_PROPOSAL_PAGE_SIZE:
- g_value_set_uint (value, completion->priv->proposal_page_size);
- break;
- case PROP_PROVIDER_PAGE_SIZE:
- g_value_set_uint (value, completion->priv->provider_page_size);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_source_completion_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkSourceCompletion *completion;
-
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION (object));
-
- completion = GTK_SOURCE_COMPLETION (object);
-
- switch (prop_id)
- {
- case PROP_VIEW:
- connect_view (completion, g_value_get_object (value));
- break;
- case PROP_REMEMBER_INFO_VISIBILITY:
- completion->priv->remember_info_visibility = g_value_get_boolean (value);
- break;
- case PROP_SELECT_ON_SHOW:
- completion->priv->select_on_show = g_value_get_boolean (value);
- break;
- case PROP_SHOW_HEADERS:
- completion->priv->show_headers = g_value_get_boolean (value);
-
- if (completion->priv->model_proposals != NULL)
- {
- gtk_source_completion_model_set_show_headers (completion->priv->model_proposals,
- completion->priv->show_headers);
- }
- break;
- case PROP_SHOW_ICONS:
- completion->priv->show_icons = g_value_get_boolean (value);
- break;
- case PROP_ACCELERATORS:
- completion->priv->num_accelerators = g_value_get_uint (value);
- break;
- case PROP_AUTO_COMPLETE_DELAY:
- completion->priv->auto_complete_delay = g_value_get_uint (value);
- break;
- case PROP_PROPOSAL_PAGE_SIZE:
- completion->priv->proposal_page_size = g_value_get_uint (value);
- break;
- case PROP_PROVIDER_PAGE_SIZE:
- completion->priv->provider_page_size = g_value_get_uint (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static gboolean
-selection_func (GtkTreeSelection *selection,
- GtkTreeModel *model,
- GtkTreePath *path,
- gboolean path_currently_selected,
- GtkSourceCompletion *completion)
-{
- GtkTreeIter iter;
-
- gtk_tree_model_get_iter (model, &iter, path);
-
- if (gtk_source_completion_model_iter_is_header (completion->priv->model_proposals,
- &iter))
- {
- /* A header must never be selected */
- g_return_val_if_fail (!path_currently_selected, TRUE);
- return FALSE;
- }
- else
- {
- return TRUE;
- }
-}
-
-static void
-accelerators_notify_cb (GtkSourceCompletion *completion,
- GParamSpec *pspec,
- GtkTreeViewColumn *column)
-{
- gtk_tree_view_column_set_visible (column, completion->priv->num_accelerators > 0);
-}
-
-static void
-cell_icon_func (GtkTreeViewColumn *column,
- GtkCellRenderer *cell,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer data)
-{
- GdkPixbuf *pixbuf;
- gchar *icon_name;
- GIcon *gicon;
- gboolean set = FALSE;
-
- gtk_tree_model_get (model, iter,
- GTK_SOURCE_COMPLETION_MODEL_COLUMN_ICON, &pixbuf,
- GTK_SOURCE_COMPLETION_MODEL_COLUMN_ICON_NAME, &icon_name,
- GTK_SOURCE_COMPLETION_MODEL_COLUMN_GICON, &gicon,
- -1);
-
- if (pixbuf != NULL)
- {
- g_object_set (cell, "pixbuf", pixbuf, NULL);
- g_object_unref (pixbuf);
- set = TRUE;
- }
-
- if (icon_name != NULL)
- {
- g_object_set (cell, "icon-name", icon_name, NULL);
- g_free (icon_name);
- set = TRUE;
- }
- if (gicon != NULL)
- {
- g_object_set (cell, "gicon", gicon, NULL);
- g_object_unref (gicon);
- set = TRUE;
- }
+ gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &where);
+ self->completion_mark = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (buffer),
+ NULL,
+ &where,
+ TRUE);
- if (!set)
+ if (self->display != NULL)
{
- g_object_set (cell, "icon-name", NULL, NULL);
+ _gtk_source_assistant_set_mark (GTK_SOURCE_ASSISTANT (self->display),
+ self->completion_mark);
}
}
-static void
-init_tree_view (GtkSourceCompletion *completion,
- GtkBuilder *builder)
-{
- GtkTreeSelection *selection;
- GtkTreeViewColumn *column;
- GtkCellRenderer *cell_renderer;
- GtkStyleContext *style_context;
- GdkRGBA* background_color = NULL;
- GdkRGBA foreground_color;
-
- completion->priv->tree_view_proposals = GTK_TREE_VIEW (gtk_builder_get_object (builder, "tree_view_proposals"));
-
- g_signal_connect_swapped (completion->priv->tree_view_proposals,
- "row-activated",
- G_CALLBACK (gtk_source_completion_activate_proposal),
- completion);
-
- g_signal_connect_swapped (completion->priv->tree_view_proposals,
- "size-allocate",
- G_CALLBACK (gtk_source_completion_proposals_size_allocate),
- completion);
-
- /* Selection */
-
- selection = gtk_tree_view_get_selection (completion->priv->tree_view_proposals);
-
- gtk_tree_selection_set_select_function (selection,
- (GtkTreeSelectionFunc)selection_func,
- completion,
- NULL);
-
- g_signal_connect (selection,
- "changed",
- G_CALLBACK (selection_changed_cb),
- completion);
-
- /* Icon cell renderer */
-
- cell_renderer = GTK_CELL_RENDERER (gtk_builder_get_object (builder, "cell_renderer_icon"));
-
- column = GTK_TREE_VIEW_COLUMN (gtk_builder_get_object (builder, "tree_view_column_icon"));
-
- /* We use a cell function instead of plain attributes for the icon since
- * the pixbuf renderer will not renderer any icon if pixbuf is set to NULL.
- * See https://bugzilla.gnome.org/show_bug.cgi?id=753510
- */
- gtk_tree_view_column_set_cell_data_func (column,
- cell_renderer,
- cell_icon_func,
- NULL,
- NULL);
-
- gtk_tree_view_column_set_attributes (column, cell_renderer,
- "cell-background-set", GTK_SOURCE_COMPLETION_MODEL_COLUMN_IS_HEADER,
- NULL);
-
- style_context = gtk_widget_get_style_context (GTK_WIDGET (completion->priv->tree_view_proposals));
-
- gtk_style_context_save (style_context);
- gtk_style_context_set_state (style_context, GTK_STATE_FLAG_INSENSITIVE);
-
- gtk_style_context_get (style_context,
- gtk_style_context_get_state (style_context),
- "background-color", &background_color,
- NULL);
-
- gtk_style_context_get_color (style_context,
- gtk_style_context_get_state (style_context),
- &foreground_color);
-
- gtk_style_context_restore (style_context);
-
- g_object_set (cell_renderer,
- "cell-background-rgba", background_color,
- NULL);
-
- g_object_bind_property (completion, "show-icons",
- cell_renderer, "visible",
- G_BINDING_SYNC_CREATE);
-
- /* Proposal text cell renderer */
-
- cell_renderer = GTK_CELL_RENDERER (gtk_builder_get_object (builder, "cell_renderer_proposal"));
- completion->priv->cell_renderer_proposal = cell_renderer;
-
- column = GTK_TREE_VIEW_COLUMN (gtk_builder_get_object (builder, "tree_view_column_proposal"));
-
- gtk_tree_view_column_set_attributes (column, cell_renderer,
- "markup", GTK_SOURCE_COMPLETION_MODEL_COLUMN_MARKUP,
- "cell-background-set", GTK_SOURCE_COMPLETION_MODEL_COLUMN_IS_HEADER,
- "foreground-set", GTK_SOURCE_COMPLETION_MODEL_COLUMN_IS_HEADER,
- NULL);
-
- g_object_set (cell_renderer,
- "foreground-rgba", &foreground_color,
- "cell-background-rgba", background_color,
- NULL);
-
- /* Accelerators cell renderer */
-
- column = GTK_TREE_VIEW_COLUMN (gtk_builder_get_object (builder, "tree_view_column_accelerator"));
-
- cell_renderer = GTK_CELL_RENDERER (gtk_builder_get_object (builder, "cell_renderer_accelerator"));
+static void
+gtk_source_completion_dispose (GObject *object)
+{
+ GtkSourceCompletion *self = (GtkSourceCompletion *)object;
- gtk_tree_view_column_set_attributes (column,
- cell_renderer,
- "cell-background-set", GTK_SOURCE_COMPLETION_MODEL_COLUMN_IS_HEADER,
- NULL);
+ g_assert (GTK_SOURCE_IS_COMPLETION (self));
- g_object_set (cell_renderer,
- "foreground-rgba", &foreground_color,
- "cell-background-rgba", background_color,
- NULL);
+ self->disposed = TRUE;
- gtk_tree_view_column_set_cell_data_func (column,
- cell_renderer,
- (GtkTreeCellDataFunc)render_proposal_accelerator_func,
- completion,
- NULL);
+ gtk_source_signal_group_set_target (self->context_signals, NULL);
+ gtk_source_signal_group_set_target (self->buffer_signals, NULL);
+ gtk_source_signal_group_set_target (self->view_signals, NULL);
- g_signal_connect_object (completion,
- "notify::accelerators",
- G_CALLBACK (accelerators_notify_cb),
- column,
- 0);
+ if (self->display != NULL)
+ {
+ _gtk_source_assistant_destroy (GTK_SOURCE_ASSISTANT (self->display));
+ self->display = NULL;
+ }
- gdk_rgba_free (background_color);
-}
+ g_clear_object (&self->context);
+ g_clear_object (&self->cancellable);
-static void
-init_main_window (GtkSourceCompletion *completion,
- GtkBuilder *builder)
-{
- if (completion->priv->view == NULL)
+ if (self->providers->len > 0)
{
- return;
+ g_ptr_array_remove_range (self->providers, 0, self->providers->len);
}
- completion->priv->main_window = GTK_SOURCE_COMPLETION_INFO (gtk_builder_get_object (builder, "main_window"));
- completion->priv->info_button = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "info_button"));
- completion->priv->selection_image = GTK_IMAGE (gtk_builder_get_object (builder, "selection_image"));
- completion->priv->selection_label = GTK_LABEL (gtk_builder_get_object (builder, "selection_label"));
- completion->priv->bottom_bar = GTK_WIDGET (gtk_builder_get_object (builder, "bottom_bar"));
-
- gtk_container_set_border_width (GTK_CONTAINER (completion->priv->main_window), 0);
-
- gtk_window_set_attached_to (GTK_WINDOW (completion->priv->main_window),
- GTK_WIDGET (completion->priv->view));
-
- g_signal_connect (completion->priv->main_window,
- "configure-event",
- G_CALLBACK (gtk_source_completion_configure_event),
- completion);
-
- g_signal_connect_swapped (completion->priv->main_window,
- "size-allocate",
- G_CALLBACK (update_window_position),
- completion);
-
- g_signal_connect (completion->priv->main_window,
- "delete-event",
- G_CALLBACK (gtk_widget_hide_on_delete),
- NULL);
-
- g_signal_connect (completion->priv->main_window,
- "notify::transient-for",
- G_CALLBACK (update_transient_for_info),
- completion);
-
- g_signal_connect_swapped (completion->priv->info_button,
- "toggled",
- G_CALLBACK (update_info_window_visibility),
- completion);
+ G_OBJECT_CLASS (gtk_source_completion_parent_class)->dispose (object);
}
static void
-init_info_window (GtkSourceCompletion *completion)
+gtk_source_completion_finalize (GObject *object)
{
- completion->priv->info_window = gtk_source_completion_info_new ();
- g_object_ref_sink (completion->priv->info_window);
-
- gtk_window_set_attached_to (GTK_WINDOW (completion->priv->info_window),
- GTK_WIDGET (completion->priv->main_window));
-
- g_signal_connect_swapped (completion->priv->info_window,
- "size-allocate",
- G_CALLBACK (update_info_position),
- completion);
+ GtkSourceCompletion *self = (GtkSourceCompletion *)object;
- /* Default info widget */
+ g_clear_weak_pointer (&self->view);
- completion->priv->default_info = GTK_LABEL (gtk_label_new (NULL));
- g_object_ref_sink (completion->priv->default_info);
-
- gtk_widget_show (GTK_WIDGET (completion->priv->default_info));
+ G_OBJECT_CLASS (gtk_source_completion_parent_class)->finalize (object);
}
static void
-connect_style_context (GtkSourceCompletion *completion)
+gtk_source_completion_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
{
- GtkStyleContext *style_context;
+ GtkSourceCompletion *self = GTK_SOURCE_COMPLETION (object);
- if (completion->priv->view == NULL)
+ switch (prop_id)
{
- return;
- }
+ case PROP_REMEMBER_INFO_VISIBILITY:
+ g_value_set_boolean (value, self->remember_info_visibility);
+ break;
+
+ case PROP_SELECT_ON_SHOW:
+ g_value_set_boolean (value, _gtk_source_completion_get_select_on_show (self));
+ break;
- style_context = gtk_widget_get_style_context (GTK_WIDGET (completion->priv->view));
+ case PROP_SHOW_ICONS:
+ g_value_set_boolean (value, self->show_icons);
+ break;
- g_signal_connect_object (style_context,
- "changed",
- G_CALLBACK (style_context_changed),
- completion,
- G_CONNECT_AFTER);
+ case PROP_VIEW:
+ g_value_set_object (value, self->view);
+ break;
- style_context_changed (style_context, completion);
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
}
static void
-gtk_source_completion_constructed (GObject *object)
+gtk_source_completion_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
- GtkSourceCompletion *completion = GTK_SOURCE_COMPLETION (object);
- GError *error = NULL;
- GtkBuilder *builder = gtk_builder_new ();
- GtkSourceCompletionContainer *container = _gtk_source_completion_container_new ();
- g_object_ref_sink (container);
-
- gtk_builder_set_translation_domain (builder, GETTEXT_PACKAGE);
-
- /* GtkSourceCompletionContainer is a private type. */
- gtk_builder_expose_object (builder, "completion_container", G_OBJECT (container));
-
- gtk_builder_add_from_resource (builder,
- "/org/gnome/gtksourceview/ui/gtksourcecompletion.ui",
- &error);
+ GtkSourceCompletion *self = GTK_SOURCE_COMPLETION (object);
- if (error != NULL)
+ switch (prop_id)
{
- g_error ("Error while loading the completion UI: %s", error->message);
- }
+ case PROP_REMEMBER_INFO_VISIBILITY:
+ self->remember_info_visibility = g_value_get_boolean (value);
+ if (self->display != NULL)
+ {
+ _gtk_source_completion_list_set_remember_info_visibility (self->display,
+ self->remember_info_visibility);
+ }
+ g_object_notify_by_pspec (object, pspec);
+ break;
- init_tree_view (completion, builder);
- init_main_window (completion, builder);
- init_info_window (completion);
- connect_style_context (completion);
+ case PROP_SELECT_ON_SHOW:
+ gtk_source_completion_set_select_on_show (self, g_value_get_boolean (value));
+ break;
- g_object_unref (builder);
- g_object_unref (container);
+ case PROP_SHOW_ICONS:
+ self->show_icons = g_value_get_boolean (value);
+ if (self->display != NULL)
+ {
+ _gtk_source_completion_list_set_show_icons (self->display, self->show_icons);
+ }
+ g_object_notify_by_pspec (object, pspec);
+ break;
- G_OBJECT_CLASS (gtk_source_completion_parent_class)->constructed (object);
+ case PROP_VIEW:
+ gtk_source_completion_set_view (self, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
}
static void
gtk_source_completion_class_init (GtkSourceCompletionClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
- GtkBindingSet *binding_set;
+ object_class->dispose = gtk_source_completion_dispose;
+ object_class->finalize = gtk_source_completion_finalize;
object_class->get_property = gtk_source_completion_get_property;
object_class->set_property = gtk_source_completion_set_property;
- object_class->dispose = gtk_source_completion_dispose;
- object_class->constructed = gtk_source_completion_constructed;
-
- klass->show = gtk_source_completion_show_default;
- klass->hide = gtk_source_completion_hide_default;
-
- klass->move_cursor = gtk_source_completion_move_cursor;
- klass->move_page = gtk_source_completion_move_page;
- klass->activate_proposal = gtk_source_completion_activate_proposal;
-
- /**
- * GtkSourceCompletion:view:
- *
- * The #GtkSourceView bound to the completion object.
- */
- g_object_class_install_property (object_class,
- PROP_VIEW,
- g_param_spec_object ("view",
- "View",
- "The GtkSourceView bound to the completion",
- GTK_SOURCE_TYPE_VIEW,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS));
/**
- * GtkSourceCompletion:remember-info-visibility:
+ * GtkSourceCompletion:buffer:
*
- * Determines whether the visibility of the info window should be
- * saved when the completion is hidden, and restored when the completion
- * is shown again.
- */
- g_object_class_install_property (object_class,
- PROP_REMEMBER_INFO_VISIBILITY,
- g_param_spec_boolean ("remember-info-visibility",
- "Remember Info Visibility",
- "Remember the last info window visibility state",
- FALSE,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT |
- G_PARAM_STATIC_STRINGS));
- /**
- * GtkSourceCompletion:select-on-show:
+ * The #GtkTextBuffer for the #GtkSourceCompletion:view.
+ * This is a convenience property for providers.
*
- * Determines whether the first proposal should be selected when the
- * completion is first shown.
+ * Since: 5.0
*/
- g_object_class_install_property (object_class,
- PROP_SELECT_ON_SHOW,
- g_param_spec_boolean ("select-on-show",
- "Select on Show",
- "Select first proposal when completion is shown",
- TRUE,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT |
- G_PARAM_STATIC_STRINGS));
+ properties [PROP_BUFFER] =
+ g_param_spec_object ("buffer",
+ "Buffer",
+ "The buffer for the view",
+ GTK_TYPE_TEXT_VIEW,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
/**
- * GtkSourceCompletion:show-headers:
+ * GtkSourceCompletion:page-size:
*
- * Determines whether provider headers should be shown in the proposal
- * list. It can be useful to disable when there is only one provider.
- */
- g_object_class_install_property (object_class,
- PROP_SHOW_HEADERS,
- g_param_spec_boolean ("show-headers",
- "Show Headers",
- "Show provider headers when proposals from multiple providers are available",
- TRUE,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT |
- G_PARAM_STATIC_STRINGS));
-
- /**
- * GtkSourceCompletion:show-icons:
+ * The number of rows to display to the user before scrolling.
*
- * Determines whether provider and proposal icons should be shown in
- * the completion popup.
+ * Since: 5.0
*/
- g_object_class_install_property (object_class,
- PROP_SHOW_ICONS,
- g_param_spec_boolean ("show-icons",
- "Show Icons",
- "Show provider and proposal icons in the completion popup",
- TRUE,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT |
- G_PARAM_STATIC_STRINGS));
+ properties [PROP_PAGE_SIZE] =
+ g_param_spec_uint ("page-size",
+ "Number of Rows",
+ "Number of rows to display to the user",
+ 1, 32, DEFAULT_PAGE_SIZE,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
- * GtkSourceCompletion:accelerators:
+ * GtkSourceCompletion:remember-info-visibility:
*
- * Number of keyboard accelerators to show for the first proposals. For
- * example, to activate the first proposal, the user can press
- * Alt1.
+ * Determines whether the visibility of the info window should be saved when the
+ * completion is hidden, and restored when the completion is shown again.
*/
- g_object_class_install_property (object_class,
- PROP_ACCELERATORS,
- g_param_spec_uint ("accelerators",
- "Accelerators",
- "Number of proposal accelerators to show",
- 0,
- 10,
- 5,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT |
- G_PARAM_STATIC_STRINGS));
+ properties [PROP_REMEMBER_INFO_VISIBILITY] =
+ g_param_spec_boolean ("remember-info-visibility",
+ "Remember Info Visibility",
+ "Remember Info Visibility",
+ FALSE,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
- * GtkSourceCompletion:auto-complete-delay:
+ * GtkSourceCompletion:select-on-show:
*
- * Determines the popup delay (in milliseconds) at which the completion
- * will be shown for interactive completion.
+ * Determines whether the first proposal should be selected when the completion
+ * is first shown.
*/
- g_object_class_install_property (object_class,
- PROP_AUTO_COMPLETE_DELAY,
- g_param_spec_uint ("auto-complete-delay",
- "Auto Complete Delay",
- "Completion popup delay for interactive completion",
- 0,
- G_MAXUINT,
- 250,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT |
- G_PARAM_STATIC_STRINGS));
+ properties [PROP_SELECT_ON_SHOW] =
+ g_param_spec_boolean ("select-on-show",
+ "Select on Show",
+ "Select on Show",
+ FALSE,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
- * GtkSourceCompletion:provider-page-size:
- *
- * The scroll page size of the provider pages in the completion window.
+ * GtkSourceCompletion:show-icons:
*
- * See the #GtkSourceCompletion::move-page signal.
+ * The "show-icons" property denotes if icons should be displayed within
+ * the list of completions presented to the user.
*/
- g_object_class_install_property (object_class,
- PROP_PROVIDER_PAGE_SIZE,
- g_param_spec_uint ("provider-page-size",
- "Provider Page Size",
- "Provider scrolling page size",
- 1,
- G_MAXUINT,
- 5,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT |
- G_PARAM_STATIC_STRINGS));
+ properties [PROP_SHOW_ICONS] =
+ g_param_spec_boolean ("show-icons",
+ "Show Icons",
+ "If icons should be shown in the completion results",
+ TRUE,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
- * GtkSourceCompletion:proposal-page-size:
- *
- * The scroll page size of the proposals in the completion window. In
- * other words, when PageDown or
- * PageUp is pressed, the selected
- * proposal becomes the one which is located one page size backward or
- * forward.
+ * GtkSourceCompletion:view:
*
- * See also the #GtkSourceCompletion::move-cursor signal.
- */
- g_object_class_install_property (object_class,
- PROP_PROPOSAL_PAGE_SIZE,
- g_param_spec_uint ("proposal-page-size",
- "Proposal Page Size",
- "Proposal scrolling page size",
- 1,
- G_MAXUINT,
- 5,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT |
- G_PARAM_STATIC_STRINGS));
-
- /**
- * GtkSourceCompletion::show:
- * @completion: The #GtkSourceCompletion who emits the signal
+ * The "view" property is the #GtkTextView for which this #GtkSourceCompletion
+ * is providing completion features.
*
- * Emitted when the completion window is shown. The default handler
- * will actually show the window.
+ * Since: 5.0
*/
- signals[SHOW] =
- g_signal_new ("show",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (GtkSourceCompletionClass, show),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
- g_signal_set_va_marshaller (signals[SHOW],
- G_TYPE_FROM_CLASS (klass),
- g_cclosure_marshal_VOID__VOIDv);
+ properties [PROP_VIEW] =
+ g_param_spec_object ("view",
+ "View",
+ "The text view for which to provide completion",
+ GTK_SOURCE_TYPE_VIEW,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_properties (object_class, N_PROPS, properties);
/**
- * GtkSourceCompletion::hide:
- * @completion: The #GtkSourceCompletion who emits the signal
+ * GtkSourceCompletion::provider-added:
+ * @self: an #ideCompletion
+ * @provider: an #GtkSourceCompletionProvider
*
- * Emitted when the completion window is hidden. The default handler
- * will actually hide the window.
- */
- signals[HIDE] =
- g_signal_new ("hide",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (GtkSourceCompletionClass, hide),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
- g_signal_set_va_marshaller (signals[HIDE],
- G_TYPE_FROM_CLASS (klass),
- g_cclosure_marshal_VOID__VOIDv);
-
- /**
- * GtkSourceCompletion::populate-context:
- * @completion: The #GtkSourceCompletion who emits the signal
- * @context: The #GtkSourceCompletionContext for the current completion
+ * The "provided-added" signal is emitted when a new provider is
+ * added to the completion.
*
- * Emitted just before starting to populate the completion with providers.
- * You can use this signal to add additional attributes in the context.
+ * Since: 5.0
*/
- signals[POPULATE_CONTEXT] =
- g_signal_new ("populate-context",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (GtkSourceCompletionClass, populate_context),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE,
- 1,
- GTK_SOURCE_TYPE_COMPLETION_CONTEXT);
- g_signal_set_va_marshaller (signals[POPULATE_CONTEXT],
- G_TYPE_FROM_CLASS (klass),
- g_cclosure_marshal_VOID__OBJECTv);
-
- /* Actions */
+ signals [PROVIDER_ADDED] =
+ g_signal_new ("provider-added",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_SOURCE_TYPE_COMPLETION_PROVIDER);
+ g_signal_set_va_marshaller (signals [PROVIDER_ADDED],
+ G_TYPE_FROM_CLASS (klass),
+ g_cclosure_marshal_VOID__OBJECTv);
/**
- * GtkSourceCompletion::move-cursor:
- * @completion: The #GtkSourceCompletion who emits the signal
- * @step: The #GtkScrollStep by which to move the cursor
- * @num: The amount of steps to move the cursor
- *
- * The #GtkSourceCompletion::move-cursor signal is a keybinding
- * signal which gets emitted when the user initiates a cursor
- * movement.
- *
- * The Up, Down,
- * PageUp, PageDown,
- * Home and End keys are bound to the
- * normal behavior expected by those keys.
+ * GtkSourceCompletion::provider-removed:
+ * @self: an #ideCompletion
+ * @provider: an #GtkSourceCompletionProvider
*
- * When @step is equal to %GTK_SCROLL_PAGES, the page size is defined by
- * the #GtkSourceCompletion:proposal-page-size property. It is used for
- * the PageDown and PageUp keys.
+ * The "provided-removed" signal is emitted when a provider has
+ * been removed from the completion.
*
- * Applications should not connect to it, but may emit it with
- * g_signal_emit_by_name() if they need to control the cursor
- * programmatically.
+ * Since: 5.0
*/
- signals [MOVE_CURSOR] =
- g_signal_new ("move-cursor",
+ signals [PROVIDER_REMOVED] =
+ g_signal_new ("provider-removed",
G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (GtkSourceCompletionClass, move_cursor),
- NULL, NULL,
- _gtk_source_marshal_VOID__ENUM_INT,
- G_TYPE_NONE,
- 2,
- GTK_TYPE_SCROLL_STEP,
- G_TYPE_INT);
- g_signal_set_va_marshaller (signals [MOVE_CURSOR],
- G_TYPE_FROM_CLASS (klass),
- _gtk_source_marshal_VOID__ENUM_INTv);
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_SOURCE_TYPE_COMPLETION_PROVIDER);
+ g_signal_set_va_marshaller (signals [PROVIDER_REMOVED],
+ G_TYPE_FROM_CLASS (klass),
+ g_cclosure_marshal_VOID__OBJECTv);
/**
- * GtkSourceCompletion::move-page:
- * @completion: The #GtkSourceCompletion who emits the signal
- * @step: The #GtkScrollStep by which to move the page
- * @num: The amount of steps to move the page
- *
- * The #GtkSourceCompletion::move-page signal is a keybinding
- * signal which gets emitted when the user initiates a page
- * movement (i.e. switches between provider pages).
- *
- * ControlLeft
- * is for going to the previous provider.
- * ControlRight
- * is for going to the next provider.
- * ControlHome
- * is for displaying all the providers.
- * ControlEnd
- * is for going to the last provider.
+ * GtkSourceCompletion::hide:
+ * @self: an #GtkSourceCompletion
*
- * When @step is equal to #GTK_SCROLL_PAGES, the page size is defined by
- * the #GtkSourceCompletion:provider-page-size property.
+ * The "hide" signal is emitted when the completion window should
+ * be hidden.
*
- * Applications should not connect to it, but may emit it with
- * g_signal_emit_by_name() if they need to control the page selection
- * programmatically.
+ * Since: 5.0
*/
- signals [MOVE_PAGE] =
- g_signal_new ("move-page",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (GtkSourceCompletionClass, move_page),
- NULL, NULL,
- _gtk_source_marshal_VOID__ENUM_INT,
- G_TYPE_NONE,
- 2,
- GTK_TYPE_SCROLL_STEP,
- G_TYPE_INT);
- g_signal_set_va_marshaller (signals [MOVE_PAGE],
- G_TYPE_FROM_CLASS (klass),
- _gtk_source_marshal_VOID__ENUM_INTv);
+ signals [HIDE] =
+ g_signal_new_class_handler ("hide",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_CALLBACK (gtk_source_completion_real_hide),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ g_signal_set_va_marshaller (signals [HIDE],
+ G_TYPE_FROM_CLASS (klass),
+ g_cclosure_marshal_VOID__VOIDv);
/**
- * GtkSourceCompletion::activate-proposal:
- * @completion: The #GtkSourceCompletion who emits the signal
+ * GtkSourceCompletion::show:
+ * @self: an #GtkSourceCompletion
*
- * The #GtkSourceCompletion::activate-proposal signal is a
- * keybinding signal which gets emitted when the user initiates
- * a proposal activation.
+ * The "show" signal is emitted when the completion window should
+ * be shown.
*
- * Applications should not connect to it, but may emit it with
- * g_signal_emit_by_name() if they need to control the proposal
- * activation programmatically.
+ * Since: 5.0
*/
- signals [ACTIVATE_PROPOSAL] =
- g_signal_new ("activate-proposal",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (GtkSourceCompletionClass, activate_proposal),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
- g_signal_set_va_marshaller (signals [ACTIVATE_PROPOSAL],
- G_TYPE_FROM_CLASS (klass),
- g_cclosure_marshal_VOID__VOIDv);
-
- /* Key bindings */
- binding_set = gtk_binding_set_by_class (klass);
-
- gtk_binding_entry_add_signal (binding_set,
- GDK_KEY_Down,
- 0,
- "move-cursor",
- 2,
- GTK_TYPE_SCROLL_STEP, GTK_SCROLL_STEPS,
- G_TYPE_INT, 1);
-
- gtk_binding_entry_add_signal (binding_set,
- GDK_KEY_Page_Down,
- 0,
- "move-cursor",
- 2,
- GTK_TYPE_SCROLL_STEP, GTK_SCROLL_PAGES,
- G_TYPE_INT, 1);
-
- gtk_binding_entry_add_signal (binding_set,
- GDK_KEY_Up,
- 0,
- "move-cursor",
- 2,
- GTK_TYPE_SCROLL_STEP, GTK_SCROLL_STEPS,
- G_TYPE_INT, -1);
-
- gtk_binding_entry_add_signal (binding_set,
- GDK_KEY_Page_Up,
- 0,
- "move-cursor",
- 2,
- GTK_TYPE_SCROLL_STEP, GTK_SCROLL_PAGES,
- G_TYPE_INT, -1);
-
- gtk_binding_entry_add_signal (binding_set,
- GDK_KEY_Home,
- 0,
- "move-cursor",
- 2,
- GTK_TYPE_SCROLL_STEP, GTK_SCROLL_ENDS,
- G_TYPE_INT, -1);
-
- gtk_binding_entry_add_signal (binding_set,
- GDK_KEY_End,
- 0,
- "move-cursor",
- 2,
- GTK_TYPE_SCROLL_STEP, GTK_SCROLL_ENDS,
- G_TYPE_INT, 1);
-
- gtk_binding_entry_add_signal (binding_set,
- GDK_KEY_Escape,
- 0,
- "hide",
- 0);
-
- gtk_binding_entry_add_signal (binding_set,
- GDK_KEY_Return,
- 0,
- "activate-proposal",
- 0);
-
- gtk_binding_entry_add_signal (binding_set,
- GDK_KEY_Tab,
- 0,
- "activate-proposal",
- 0);
-
- gtk_binding_entry_add_signal (binding_set,
- GDK_KEY_Left,
- GDK_CONTROL_MASK,
- "move-page",
- 2,
- GTK_TYPE_SCROLL_STEP, GTK_SCROLL_STEPS,
- G_TYPE_INT, -1);
-
- gtk_binding_entry_add_signal (binding_set,
- GDK_KEY_Right,
- GDK_CONTROL_MASK,
- "move-page",
- 2,
- GTK_TYPE_SCROLL_STEP, GTK_SCROLL_STEPS,
- G_TYPE_INT, 1);
-
- gtk_binding_entry_add_signal (binding_set,
- GDK_KEY_Home,
- GDK_CONTROL_MASK,
- "move-page",
- 2,
- GTK_TYPE_SCROLL_STEP, GTK_SCROLL_ENDS,
- G_TYPE_INT, -1);
-
- gtk_binding_entry_add_signal (binding_set,
- GDK_KEY_End,
- GDK_CONTROL_MASK,
- "move-page",
- 2,
- GTK_TYPE_SCROLL_STEP, GTK_SCROLL_ENDS,
- G_TYPE_INT, 1);
-
- g_type_ensure (GTK_SOURCE_TYPE_COMPLETION_INFO);
+ signals [SHOW] =
+ g_signal_new_class_handler ("show",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_CALLBACK (gtk_source_completion_real_show),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ g_signal_set_va_marshaller (signals [SHOW],
+ G_TYPE_FROM_CLASS (klass),
+ g_cclosure_marshal_VOID__VOIDv);
}
static void
-gtk_source_completion_init (GtkSourceCompletion *completion)
+gtk_source_completion_init (GtkSourceCompletion *self)
{
- completion->priv = gtk_source_completion_get_instance_private (completion);
+ self->cancellable = g_cancellable_new ();
+ self->providers = g_ptr_array_new_with_free_func (g_object_unref);
+ self->buffer_signals = gtk_source_signal_group_new (GTK_TYPE_TEXT_BUFFER);
+ self->context_signals = gtk_source_signal_group_new (GTK_SOURCE_TYPE_COMPLETION_CONTEXT);
+ self->view_signals = gtk_source_signal_group_new (GTK_SOURCE_TYPE_VIEW);
+ self->page_size = DEFAULT_PAGE_SIZE;
+ self->show_icons = TRUE;
+
+ /*
+ * We want to be notified when the context switches from no results to
+ * having results (or vice-versa, when we've filtered to the point of
+ * no results).
+ */
+ gtk_source_signal_group_connect_object (self->context_signals,
+ "notify::empty",
+ G_CALLBACK (gtk_source_completion_notify_context_empty_cb),
+ self,
+ G_CONNECT_SWAPPED);
+
+ /*
+ * We need to know when the buffer inserts or deletes text so that we
+ * possibly start showing the results, or update our previous completion
+ * request.
+ */
+ g_signal_connect_object (self->buffer_signals,
+ "bind",
+ G_CALLBACK (on_buffer_signals_bind),
+ self,
+ G_CONNECT_SWAPPED);
+ gtk_source_signal_group_connect_object (self->buffer_signals,
+ "delete-range",
+ G_CALLBACK (gtk_source_completion_buffer_delete_range_after_cb),
+ self,
+ G_CONNECT_AFTER | G_CONNECT_SWAPPED);
+ gtk_source_signal_group_connect_object (self->buffer_signals,
+ "insert-text",
+ G_CALLBACK (gtk_source_completion_buffer_insert_text_after_cb),
+ self,
+ G_CONNECT_AFTER | G_CONNECT_SWAPPED);
+ gtk_source_signal_group_connect_object (self->buffer_signals,
+ "mark-set",
+ G_CALLBACK (gtk_source_completion_buffer_mark_set_cb),
+ self,
+ G_CONNECT_SWAPPED);
+
+ /*
+ * We track some events on the view that owns our GtkSourceCompletion instance so
+ * that we can hide the window when it definitely should not be displayed.
+ */
+ gtk_source_signal_group_connect_object (self->view_signals,
+ "move-cursor",
+ G_CALLBACK (gtk_source_completion_view_move_cursor_cb),
+ self,
+ G_CONNECT_AFTER | G_CONNECT_SWAPPED);
+ gtk_source_signal_group_connect_object (self->view_signals,
+ "paste-clipboard",
+ G_CALLBACK (gtk_source_completion_block_interactive),
+ self,
+ G_CONNECT_SWAPPED);
+ gtk_source_signal_group_connect_object (self->view_signals,
+ "paste-clipboard",
+ G_CALLBACK (gtk_source_completion_unblock_interactive),
+ self,
+ G_CONNECT_AFTER | G_CONNECT_SWAPPED);
}
-static GObject *
-gtk_source_completion_buildable_get_internal_child (GtkBuildable *buildable,
- GtkBuilder *builder,
- const gchar *childname)
+/**
+ * gtk_source_completion_get_view:
+ * @self: a #GtkSourceCompletion
+ *
+ * Gets the #GtkSourceView that owns the #GtkSourceCompletion.
+ *
+ * Returns: (transfer none): A #GtkSourceView
+ *
+ * Since: 5.0
+ */
+GtkSourceView *
+gtk_source_completion_get_view (GtkSourceCompletion *self)
{
- GtkSourceCompletion *completion = GTK_SOURCE_COMPLETION (buildable);
-
- if (g_strcmp0 (childname, "info_window") == 0)
- {
- return G_OBJECT (gtk_source_completion_get_info_window (completion));
- }
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION (self), NULL);
- return NULL;
+ return self->view;
}
-static void
-gtk_source_completion_buildable_interface_init (GtkBuildableIface *iface)
+/**
+ * gtk_source_completion_get_buffer:
+ * @self: a #GtkSourceCompletion
+ *
+ * Gets the connected #GtkSourceView's #GtkSourceBuffer
+ *
+ * Returns: (transfer none): A #GtkSourceBuffer
+ *
+ * Since: 5.0
+ */
+GtkSourceBuffer *
+gtk_source_completion_get_buffer (GtkSourceCompletion *self)
{
- iface->get_internal_child = gtk_source_completion_buildable_get_internal_child;
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION (self), NULL);
+
+ return GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (self->view)));
}
+/**
+ * gtk_source_completion_add_provider:
+ * @self: an #GtkSourceCompletion
+ * @provider: an #GtkSourceCompletionProvider
+ *
+ * Adds an #GtkSourceCompletionProvider to the list of providers to be queried
+ * for completion results.
+ *
+ * Since: 5.0
+ */
void
-_gtk_source_completion_add_proposals (GtkSourceCompletion *completion,
- GtkSourceCompletionContext *context,
- GtkSourceCompletionProvider *provider,
- GList *proposals,
- gboolean finished)
+gtk_source_completion_add_provider (GtkSourceCompletion *self,
+ GtkSourceCompletionProvider *provider)
{
- GList *item;
-
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION (completion));
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (context));
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION (self));
g_return_if_fail (GTK_SOURCE_IS_COMPLETION_PROVIDER (provider));
- g_return_if_fail (completion->priv->context == context);
-
- item = g_list_find (completion->priv->running_providers, provider);
- g_return_if_fail (item != NULL);
- gtk_source_completion_model_add_proposals (completion->priv->model_proposals,
- provider,
- proposals);
-
- if (finished)
- {
- /* Remove provider from list of running providers */
- completion->priv->running_providers =
- g_list_delete_link (completion->priv->running_providers,
- item);
-
- if (completion->priv->running_providers == NULL)
- {
- populating_done (completion, context);
- }
- }
+ g_ptr_array_add (self->providers, g_object_ref (provider));
+ g_signal_emit (self, signals [PROVIDER_ADDED], 0, provider);
}
/**
- * gtk_source_completion_start:
- * @completion: a #GtkSourceCompletion.
- * @providers: (element-type GtkSource.CompletionProvider) (nullable):
- * a list of #GtkSourceCompletionProvider, or %NULL.
- * @context: (transfer floating): The #GtkSourceCompletionContext
- * with which to start the completion.
- *
- * Starts a new completion with the specified #GtkSourceCompletionContext and
- * a list of potential candidate providers for completion.
- *
- * It can be convenient for showing a completion on-the-fly, without the need to
- * add or remove providers to the #GtkSourceCompletion.
+ * gtk_source_completion_remove_provider:
+ * @self: an #GtkSourceCompletion
+ * @provider: an #GtkSourceCompletionProvider
*
- * Another solution is to add providers with
- * gtk_source_completion_add_provider(), and implement
- * gtk_source_completion_provider_match() for each provider.
+ * Removes an #GtkSourceCompletionProvider previously added with
+ * gtk_source_completion_add_provider().
*
- * Returns: %TRUE if it was possible to the show completion window.
+ * Since: 5.0
*/
-gboolean
-gtk_source_completion_start (GtkSourceCompletion *completion,
- GList *providers,
- GtkSourceCompletionContext *context)
+void
+gtk_source_completion_remove_provider (GtkSourceCompletion *self,
+ GtkSourceCompletionProvider *provider)
{
- GList *selected_providers;
+ GtkSourceCompletionProvider *hold = NULL;
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION (completion), FALSE);
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (context), FALSE);
-
- if (completion->priv->view == NULL)
- {
- return FALSE;
- }
-
- /* Make sure to clear any active completion */
- reset_completion (completion);
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION (self));
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_PROVIDER (provider));
- /* We need to take owenership of the context right before doing
- anything so we don't leak it or get a crash emitting the signal */
- g_object_ref_sink (context);
+ hold = g_object_ref (provider);
- if (providers == NULL)
+ if (g_ptr_array_remove (self->providers, provider))
{
- g_object_unref (context);
-
- return FALSE;
+ g_signal_emit (self, signals [PROVIDER_REMOVED], 0, hold);
}
- /* Populate the context */
- g_signal_emit (completion, signals[POPULATE_CONTEXT], 0, context);
-
- /* From the providers, select the ones that match the context */
- selected_providers = select_providers (providers, context);
+ g_clear_object (&hold);
+}
- if (selected_providers == NULL)
- {
- g_object_unref (context);
- gtk_source_completion_hide (completion);
- return FALSE;
- }
+/**
+ * gtk_source_completion_show:
+ * @self: an #GtkSourceCompletion
+ *
+ * Emits the "show" signal.
+ *
+ * When the "show" signal is emitted, the completion window will be
+ * displayed if there are any results available.
+ *
+ * Since: 5.0
+ */
+void
+gtk_source_completion_show (GtkSourceCompletion *self)
+{
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION (self));
- update_completion (completion, selected_providers, context);
- g_list_free (selected_providers);
- g_object_unref (context);
+ if (gtk_source_completion_is_blocked (self))
+ return;
- return TRUE;
+ self->showing++;
+ if (self->showing == 1)
+ g_signal_emit (self, signals [SHOW], 0);
+ self->showing--;
}
/**
- * gtk_source_completion_get_providers:
- * @completion: a #GtkSourceCompletion.
+ * gtk_source_completion_hide:
+ * @self: an #GtkSourceCompletion
+ *
+ * Emits the "hide" signal.
*
- * Get list of providers registered on @completion. The returned list is owned
- * by the completion and should not be freed.
+ * When the "hide" signal is emitted, the completion window will be
+ * dismissed.
*
- * Returns: (element-type GtkSource.CompletionProvider) (transfer none):
- * list of #GtkSourceCompletionProvider.
+ * Since: 5.0
*/
-GList *
-gtk_source_completion_get_providers (GtkSourceCompletion *completion)
+void
+gtk_source_completion_hide (GtkSourceCompletion *self)
{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION (completion), NULL);
- return completion->priv->providers;
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION (self));
+
+ g_signal_emit (self, signals [HIDE], 0);
}
-GQuark
-gtk_source_completion_error_quark (void)
+void
+gtk_source_completion_block_interactive (GtkSourceCompletion *self)
{
- static GQuark quark = 0;
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION (self));
- if (G_UNLIKELY (quark == 0))
- {
- quark = g_quark_from_static_string ("gtk-source-completion-error-quark");
- }
+ self->block_count++;
- return quark;
+ gtk_source_completion_cancel (self);
}
-/**
- * gtk_source_completion_new:
- * @view: a #GtkSourceView.
- *
- * Creates a new #GtkSourceCompletion associated with @view.
- *
- * Returns: a new #GtkSourceCompletion.
- */
-GtkSourceCompletion *
-gtk_source_completion_new (GtkSourceView *view)
+void
+gtk_source_completion_unblock_interactive (GtkSourceCompletion *self)
{
- g_return_val_if_fail (GTK_SOURCE_IS_VIEW (view), NULL);
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION (self));
- return g_object_new (GTK_SOURCE_TYPE_COMPLETION,
- "view", view,
- NULL);
+ self->block_count--;
}
-/**
- * gtk_source_completion_add_provider:
- * @completion: a #GtkSourceCompletion.
- * @provider: a #GtkSourceCompletionProvider.
- * @error: a #GError.
- *
- * Add a new #GtkSourceCompletionProvider to the completion object. This will
- * add a reference @provider, so make sure to unref your own copy when you
- * no longer need it.
- *
- * Returns: %TRUE if @provider was successfully added, otherwise if @error
- * is provided, it will be set with the error and %FALSE is returned.
- */
-gboolean
-gtk_source_completion_add_provider (GtkSourceCompletion *completion,
- GtkSourceCompletionProvider *provider,
- GError **error)
+void
+gtk_source_completion_set_page_size (GtkSourceCompletion *self,
+ guint page_size)
{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION (completion), FALSE);
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_PROVIDER (provider), FALSE);
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION (self));
+ g_return_if_fail (page_size > 0);
+ g_return_if_fail (page_size <= 32);
- if (g_list_find (completion->priv->providers, provider) != NULL)
+ if (self->page_size != page_size)
{
- if (error != NULL)
- {
- g_set_error (error,
- GTK_SOURCE_COMPLETION_ERROR,
- GTK_SOURCE_COMPLETION_ERROR_ALREADY_BOUND,
- "Provider is already bound to this completion object");
- }
-
- return FALSE;
+ self->page_size = page_size;
+ if (self->display != NULL)
+ _gtk_source_completion_list_set_n_rows (self->display, page_size);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_PAGE_SIZE]);
}
+}
+
+guint
+gtk_source_completion_get_page_size (GtkSourceCompletion *self)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION (self), 0);
+
+ return self->page_size;
+}
+
+void
+_gtk_source_completion_activate (GtkSourceCompletion *self,
+ GtkSourceCompletionContext *context,
+ GtkSourceCompletionProvider *provider,
+ GtkSourceCompletionProposal *proposal)
+{
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION (self));
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (context));
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_PROVIDER (provider));
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_PROPOSAL (proposal));
+
+ self->block_count++;
+
+ gtk_source_completion_provider_activate (provider, context, proposal);
+ gtk_source_completion_hide (self);
+ g_clear_object (&self->context);
+ _gtk_source_completion_list_set_context (self->display, NULL);
+
+ self->block_count--;
+}
- completion->priv->providers = g_list_append (completion->priv->providers,
- g_object_ref (provider));
+GtkSourceCompletionList *
+_gtk_source_completion_get_display (GtkSourceCompletion *self)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION (self), NULL);
- if (error != NULL)
+ if (self->display == NULL)
{
- *error = NULL;
+ self->display = _gtk_source_completion_list_new ();
+ _gtk_source_completion_list_set_n_rows (self->display, self->page_size);
+ _gtk_source_completion_list_set_font_desc (self->display, self->font_desc);
+ _gtk_source_completion_list_set_show_icons (self->display, self->show_icons);
+ _gtk_source_completion_list_set_remember_info_visibility (self->display,
+ self->remember_info_visibility);
+ _gtk_source_assistant_set_mark (GTK_SOURCE_ASSISTANT (self->display),
+ self->completion_mark);
+ _gtk_source_view_add_assistant (self->view,
+ GTK_SOURCE_ASSISTANT (self->display));
+ _gtk_source_completion_list_set_context (self->display, self->context);
}
- return TRUE;
+ return self->display;
}
/**
- * gtk_source_completion_remove_provider:
- * @completion: a #GtkSourceCompletion.
- * @provider: a #GtkSourceCompletionProvider.
- * @error: a #GError.
+ * gtk_source_completion_fuzzy_match:
+ * @haystack: (nullable): the string to be searched.
+ * @casefold_needle: A g_utf8_casefold() version of the needle.
+ * @priority: (out) (allow-none): An optional location for the score of the match
*
- * Remove @provider from the completion.
+ * This helper function can do a fuzzy match for you giving a haystack and
+ * casefolded needle. Casefold your needle using g_utf8_casefold() before
+ * running the query.
*
- * Returns: %TRUE if @provider was successfully removed, otherwise if @error
- * is provided, it will be set with the error and %FALSE is returned.
+ * Score will be set with the score of the match upon success. Otherwise,
+ * it will be set to zero.
+ *
+ * Returns: %TRUE if @haystack matched @casefold_needle, otherwise %FALSE.
+ *
+ * Since: 5.0
*/
gboolean
-gtk_source_completion_remove_provider (GtkSourceCompletion *completion,
- GtkSourceCompletionProvider *provider,
- GError **error)
+gtk_source_completion_fuzzy_match (const char *haystack,
+ const char *casefold_needle,
+ guint *priority)
{
- GList *item;
-
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION (completion), FALSE);
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_PROVIDER (provider), FALSE);
-
- item = g_list_find (completion->priv->providers, provider);
-
- if (item == NULL)
- {
- if (error != NULL)
- {
- g_set_error (error,
- GTK_SOURCE_COMPLETION_ERROR,
- GTK_SOURCE_COMPLETION_ERROR_NOT_BOUND,
- "Provider is not bound to this completion object");
- }
+ gint real_score = 0;
+ if (haystack == NULL || haystack[0] == 0)
return FALSE;
- }
- completion->priv->providers = g_list_delete_link (completion->priv->providers, item);
+ for (; *casefold_needle; casefold_needle = g_utf8_next_char (casefold_needle))
+ {
+ gunichar ch = g_utf8_get_char (casefold_needle);
+ gunichar chup = g_unichar_toupper (ch);
+ const gchar *tmp;
+ const gchar *downtmp;
+ const gchar *uptmp;
+
+ /*
+ * Note that the following code is not really correct. We want
+ * to be relatively fast here, but we also don't want to convert
+ * strings to casefolded versions for querying on each compare.
+ * So we use the casefold version and compare with upper. This
+ * works relatively well since we are usually dealing with ASCII
+ * for function names and symbols.
+ */
+
+ downtmp = strchr (haystack, ch);
+ uptmp = strchr (haystack, chup);
+
+ if (downtmp && uptmp)
+ tmp = MIN (downtmp, uptmp);
+ else if (downtmp)
+ tmp = downtmp;
+ else if (uptmp)
+ tmp = uptmp;
+ else
+ return FALSE;
+
+ /*
+ * Here we calculate the cost of this character into the score.
+ * If we matched exactly on the next character, the cost is ZERO.
+ * However, if we had to skip some characters, we have a cost
+ * of 2*distance to the character. This is necessary so that
+ * when we add the cost of the remaining haystack, strings which
+ * exhausted @casefold_needle score lower (higher priority) than
+ * strings which had to skip characters but matched the same
+ * number of characters in the string.
+ */
+ real_score += (tmp - haystack) * 2;
- g_object_unref (provider);
+ /* Add extra cost if we matched by using toupper */
+ if ((gunichar)*haystack == chup)
+ real_score += 1;
- if (error != NULL)
- {
- *error = NULL;
+ /*
+ * * Now move past our matching character so we cannot match
+ * * it a second time.
+ * */
+ haystack = tmp + 1;
}
+ if (priority != NULL)
+ *priority = real_score + strlen (haystack);
+
return TRUE;
}
-/**
- * gtk_source_completion_hide:
- * @completion: a #GtkSourceCompletion.
- *
- * Hides the completion if it is active (visible).
- */
-void
-gtk_source_completion_hide (GtkSourceCompletion *completion)
+static void
+add_attributes (PangoAttrList **attrs,
+ guint begin,
+ guint end)
{
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION (completion));
-
- reset_completion (completion);
+ PangoAttribute *attr;
- if (gtk_widget_get_visible (GTK_WIDGET (completion->priv->main_window)))
+ if (*attrs == NULL)
{
- g_signal_emit (completion, signals[HIDE], 0);
+ *attrs = pango_attr_list_new ();
}
-}
-/**
- * gtk_source_completion_get_info_window:
- * @completion: a #GtkSourceCompletion.
- *
- * The info widget is the window where the completion displays optional extra
- * information of the proposal.
- *
- * Returns: (transfer none): The #GtkSourceCompletionInfo window
- * associated with @completion.
- */
-GtkSourceCompletionInfo *
-gtk_source_completion_get_info_window (GtkSourceCompletion *completion)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION (completion), NULL);
+ attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE);
+ attr->start_index = begin;
+ attr->end_index = end;
+ pango_attr_list_insert (*attrs, g_steal_pointer (&attr));
- return completion->priv->info_window;
+ attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
+ attr->start_index = begin;
+ attr->end_index = end;
+ pango_attr_list_insert (*attrs, g_steal_pointer (&attr));
}
/**
- * gtk_source_completion_get_view:
- * @completion: a #GtkSourceCompletion.
- *
- * The #GtkSourceView associated with @completion, or %NULL if the view has been
- * destroyed.
+ * gtk_source_completion_fuzzy_highlight:
+ * @haystack: the string to be highlighted
+ * @casefold_query: the typed-text used to highlight @haystack
*
- * Returns: (nullable) (transfer none): The #GtkSourceView associated with
- * @completion, or %NULL.
- */
-GtkSourceView *
-gtk_source_completion_get_view (GtkSourceCompletion *completion)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION (completion), NULL);
-
- return completion->priv->view;
-}
-
-/**
- * gtk_source_completion_create_context:
- * @completion: a #GtkSourceCompletion.
- * @position: (nullable): a #GtkTextIter, or %NULL.
+ * This will add <b> tags around matched characters in @haystack
+ * based on @casefold_query.
*
- * Create a new #GtkSourceCompletionContext for @completion. The position where
- * the completion occurs can be specified by @position. If @position is %NULL,
- * the current cursor position will be used.
+ * Returns: (transfer full) (nullable): a #PangoAttrList or %NULL
*
- * Returns: (transfer floating): a new #GtkSourceCompletionContext.
- * The reference being returned is a 'floating' reference,
- * so if you invoke gtk_source_completion_start() with this context
- * you don't need to unref it.
+ * Since: 5.0
*/
-GtkSourceCompletionContext *
-gtk_source_completion_create_context (GtkSourceCompletion *completion,
- GtkTextIter *position)
+PangoAttrList *
+gtk_source_completion_fuzzy_highlight (const char *haystack,
+ const char *casefold_query)
{
- GtkTextIter iter;
+ const char *real_haystack = haystack;
+ PangoAttrList *attrs = NULL;
+ gunichar str_ch;
+ gunichar match_ch;
+ gboolean element_open = FALSE;
+ guint begin = 0;
+ guint end = 0;
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION (completion), NULL);
-
- if (completion->priv->view == NULL)
+ if (haystack == NULL || casefold_query == NULL)
{
return NULL;
}
- if (position == NULL)
- {
- get_iter_at_insert (completion, &iter);
- }
- else
+ for (; *haystack; haystack = g_utf8_next_char (haystack))
{
- iter = *position;
- }
-
- return _gtk_source_completion_context_new (completion, &iter);
-}
+ str_ch = g_utf8_get_char (haystack);
+ match_ch = g_utf8_get_char (casefold_query);
-/**
- * gtk_source_completion_block_interactive:
- * @completion: a #GtkSourceCompletion.
- *
- * Block interactive completion. This can be used to disable interactive
- * completion when inserting or deleting text from the buffer associated with
- * the completion. Use gtk_source_completion_unblock_interactive() to enable
- * interactive completion again.
- *
- * This function may be called multiple times. It will continue to block
- * interactive completion until gtk_source_completion_unblock_interactive()
- * has been called the same number of times.
- */
-void
-gtk_source_completion_block_interactive (GtkSourceCompletion *completion)
-{
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION (completion));
+ if ((str_ch == match_ch) || (g_unichar_tolower (str_ch) == g_unichar_tolower (match_ch)))
+ {
+ if (!element_open)
+ {
+ begin = haystack - real_haystack;
+ element_open = TRUE;
+ }
- if (completion->priv->view == NULL)
- {
- return;
+ /* TODO: We could seek to the next char and append in a batch. */
+ casefold_query = g_utf8_next_char (casefold_query);
+ }
+ else
+ {
+ if (element_open)
+ {
+ end = haystack - real_haystack;
+ add_attributes (&attrs, begin, end);
+ element_open = FALSE;
+ }
+ }
}
- if (completion->priv->block_interactive_num == 0)
+ if (element_open)
{
- block_interactive (completion);
+ end = haystack - real_haystack;
+ add_attributes (&attrs, begin, end);
}
- completion->priv->block_interactive_num++;
+ return g_steal_pointer (&attrs);
}
-/**
- * gtk_source_completion_unblock_interactive:
- * @completion: a #GtkSourceCompletion.
- *
- * Unblock interactive completion. This can be used after using
- * gtk_source_completion_block_interactive() to enable interactive completion
- * again.
- */
void
-gtk_source_completion_unblock_interactive (GtkSourceCompletion *completion)
+_gtk_source_completion_css_changed (GtkSourceCompletion *self,
+ GtkCssStyleChange *change)
{
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION (completion));
-
- if (completion->priv->view == NULL)
- {
- return;
- }
-
- if (completion->priv->block_interactive_num == 1)
- {
- g_signal_handlers_unblock_by_func (completion->priv->buffer,
- buffer_insert_text_cb,
- completion);
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION (self));
+ g_return_if_fail (change != NULL);
- g_signal_handlers_unblock_by_func (completion->priv->buffer,
- buffer_delete_range_cb,
- completion);
- }
+ g_clear_pointer (&self->font_desc, pango_font_description_free);
+ self->font_desc = create_font_description (self);
- if (completion->priv->block_interactive_num > 0)
+ if (self->display != NULL)
{
- completion->priv->block_interactive_num--;
+ _gtk_source_completion_list_set_font_desc (self->display, self->font_desc);
}
}
diff --git a/gtksourceview/gtksourcecompletion.h b/gtksourceview/gtksourcecompletion.h
index a5dfd9246dd26869364c11377d1fc38a85d5a6cd..01fcc74251e902cddbcf97c8294a63f858077856 100644
--- a/gtksourceview/gtksourcecompletion.h
+++ b/gtksourceview/gtksourcecompletion.h
@@ -1,9 +1,7 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
- *
+/*
* This file is part of GtkSourceView
*
- * Copyright (C) 2007 - 2009 Jesús Barbero Rodríguez
- * Copyright (C) 2009 - Jesse van den Kieboom
+ * Copyright 2020 Christian Hergert
*
* GtkSourceView is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -17,140 +15,52 @@
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, see .
- */
-
-#ifndef GTK_SOURCE_COMPLETION_H
-#define GTK_SOURCE_COMPLETION_H
-
-#if !defined (GTK_SOURCE_H_INSIDE) && !defined (GTK_SOURCE_COMPILATION)
-#error "Only can be included directly."
-#endif
-
-#include
-#include
-
-G_BEGIN_DECLS
-
-/*
- * Type checking and casting macros
- */
-#define GTK_SOURCE_TYPE_COMPLETION (gtk_source_completion_get_type())
-#define GTK_SOURCE_COMPLETION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_SOURCE_TYPE_COMPLETION, GtkSourceCompletion))
-#define GTK_SOURCE_COMPLETION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_SOURCE_TYPE_COMPLETION, GtkSourceCompletionClass))
-#define GTK_SOURCE_IS_COMPLETION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_SOURCE_TYPE_COMPLETION))
-#define GTK_SOURCE_IS_COMPLETION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_SOURCE_TYPE_COMPLETION))
-#define GTK_SOURCE_COMPLETION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_SOURCE_TYPE_COMPLETION, GtkSourceCompletionClass))
-
-/**
- * GTK_SOURCE_COMPLETION_ERROR:
- *
- * Error domain for the completion. Errors in this domain will be from the
- * #GtkSourceCompletionError enumeration. See #GError for more information on
- * error domains.
- */
-#define GTK_SOURCE_COMPLETION_ERROR (gtk_source_completion_error_quark ())
-
-typedef struct _GtkSourceCompletionPrivate GtkSourceCompletionPrivate;
-typedef struct _GtkSourceCompletionClass GtkSourceCompletionClass;
-
-/**
- * GtkSourceCompletionError:
- * @GTK_SOURCE_COMPLETION_ERROR_ALREADY_BOUND: The #GtkSourceCompletionProvider
- * is already bound to the #GtkSourceCompletion object.
- * @GTK_SOURCE_COMPLETION_ERROR_NOT_BOUND: The #GtkSourceCompletionProvider is
- * not bound to the #GtkSourceCompletion object.
*
- * An error code used with %GTK_SOURCE_COMPLETION_ERROR in a #GError returned
- * from a completion-related function.
+ * SPDX-License-Identifier: LGPL-2.1-or-later
*/
-typedef enum _GtkSourceCompletionError
-{
- GTK_SOURCE_COMPLETION_ERROR_ALREADY_BOUND = 0,
- GTK_SOURCE_COMPLETION_ERROR_NOT_BOUND
-} GtkSourceCompletionError;
-struct _GtkSourceCompletion
-{
- GObject parent_instance;
+#pragma once
- GtkSourceCompletionPrivate *priv;
-};
-
-struct _GtkSourceCompletionClass
-{
- GObjectClass parent_class;
-
- gboolean (* proposal_activated) (GtkSourceCompletion *completion,
- GtkSourceCompletionProvider *provider,
- GtkSourceCompletionProposal *proposal);
- void (* show) (GtkSourceCompletion *completion);
- void (* hide) (GtkSourceCompletion *completion);
- void (* populate_context) (GtkSourceCompletion *completion,
- GtkSourceCompletionContext *context);
-
- /* Actions */
- void (* move_cursor) (GtkSourceCompletion *completion,
- GtkScrollStep step,
- gint num);
- void (* move_page) (GtkSourceCompletion *completion,
- GtkScrollStep step,
- gint num);
- void (* activate_proposal) (GtkSourceCompletion *completion);
-
- gpointer padding[20];
-};
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-GType gtk_source_completion_get_type (void) G_GNUC_CONST;
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-GQuark gtk_source_completion_error_quark (void);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-gboolean gtk_source_completion_add_provider (GtkSourceCompletion *completion,
- GtkSourceCompletionProvider *provider,
- GError **error);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-gboolean gtk_source_completion_remove_provider (GtkSourceCompletion *completion,
- GtkSourceCompletionProvider *provider,
- GError **error);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-GList *gtk_source_completion_get_providers (GtkSourceCompletion *completion);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-gboolean gtk_source_completion_start (GtkSourceCompletion *completion,
- GList *providers,
- GtkSourceCompletionContext *context);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_completion_hide (GtkSourceCompletion *completion);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-GtkSourceCompletionInfo *
- gtk_source_completion_get_info_window (GtkSourceCompletion *completion);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-GtkSourceView *gtk_source_completion_get_view (GtkSourceCompletion *completion);
+#include
-GTK_SOURCE_AVAILABLE_IN_ALL
-GtkSourceCompletionContext *
- gtk_source_completion_create_context (GtkSourceCompletion *completion,
- GtkTextIter *position);
+#include "gtksourcetypes.h"
-GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_completion_block_interactive (GtkSourceCompletion *completion);
+G_BEGIN_DECLS
-GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_completion_unblock_interactive (GtkSourceCompletion *completion);
+#define GTK_SOURCE_TYPE_COMPLETION (gtk_source_completion_get_type())
+
+GTK_SOURCE_AVAILABLE_IN_5_0
+G_DECLARE_FINAL_TYPE (GtkSourceCompletion, gtk_source_completion, GTK_SOURCE, COMPLETION, GObject)
+
+GTK_SOURCE_AVAILABLE_IN_5_0
+GtkSourceView *gtk_source_completion_get_view (GtkSourceCompletion *self);
+GTK_SOURCE_AVAILABLE_IN_5_0
+GtkSourceBuffer *gtk_source_completion_get_buffer (GtkSourceCompletion *self);
+GTK_SOURCE_AVAILABLE_IN_5_0
+void gtk_source_completion_show (GtkSourceCompletion *self);
+GTK_SOURCE_AVAILABLE_IN_5_0
+void gtk_source_completion_hide (GtkSourceCompletion *self);
+GTK_SOURCE_AVAILABLE_IN_5_0
+void gtk_source_completion_add_provider (GtkSourceCompletion *self,
+ GtkSourceCompletionProvider *provider);
+GTK_SOURCE_AVAILABLE_IN_5_0
+void gtk_source_completion_remove_provider (GtkSourceCompletion *self,
+ GtkSourceCompletionProvider *provider);
+GTK_SOURCE_AVAILABLE_IN_5_0
+void gtk_source_completion_block_interactive (GtkSourceCompletion *self);
+GTK_SOURCE_AVAILABLE_IN_5_0
+void gtk_source_completion_unblock_interactive (GtkSourceCompletion *self);
+GTK_SOURCE_AVAILABLE_IN_5_0
+guint gtk_source_completion_get_page_size (GtkSourceCompletion *self);
+GTK_SOURCE_AVAILABLE_IN_5_0
+void gtk_source_completion_set_page_size (GtkSourceCompletion *self,
+ guint page_size);
+GTK_SOURCE_AVAILABLE_IN_5_0
+gboolean gtk_source_completion_fuzzy_match (const char *haystack,
+ const char *casefold_needle,
+ guint *priority);
+GTK_SOURCE_AVAILABLE_IN_5_0
+PangoAttrList *gtk_source_completion_fuzzy_highlight (const char *haystack,
+ const char *casefold_query);
-G_GNUC_INTERNAL
-void _gtk_source_completion_add_proposals (GtkSourceCompletion *completion,
- GtkSourceCompletionContext *context,
- GtkSourceCompletionProvider *provider,
- GList *proposals,
- gboolean finished);
G_END_DECLS
-
-#endif /* GTK_SOURCE_COMPLETION_H */
diff --git a/gtksourceview/gtksourcecompletion.ui b/gtksourceview/gtksourcecompletion.ui
deleted file mode 100644
index 497eabd0152c47ff4ba52c2f4d0fa25d2495b4f9..0000000000000000000000000000000000000000
--- a/gtksourceview/gtksourcecompletion.ui
+++ /dev/null
@@ -1,119 +0,0 @@
-
-
-
-
-
-
-
- popup
- combo
- False
- True
- True
- False
- False
- False
- True
-
-
- True
- vertical
-
-
- True
- False
-
-
- True
- False
- False
- False
- False
- True
-
-
-
-
-
-
-
-
-
- True
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- True
- horizontal
-
-
- True
- False
- Show detailed proposal information
- GTK_RELIEF_NONE
- _Details…
- True
-
-
-
-
- True
- end
- True
-
-
- 1
-
-
-
-
- True
- 6
-
-
- 2
-
-
-
-
- 1
-
-
-
-
-
-
diff --git a/gtksourceview/gtksourcecompletioncell-private.h b/gtksourceview/gtksourcecompletioncell-private.h
new file mode 100644
index 0000000000000000000000000000000000000000..ea01f2321ea8f6d8037619b434d553f03a2481e2
--- /dev/null
+++ b/gtksourceview/gtksourcecompletioncell-private.h
@@ -0,0 +1,32 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2020 Christian Hergert
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#pragma once
+
+#include "gtksourcecompletioncell.h"
+
+G_BEGIN_DECLS
+
+void _gtk_source_completion_cell_set_attrs (GtkSourceCompletionCell *self,
+ PangoAttrList *attrs);
+gboolean _gtk_source_completion_cell_is_empty (GtkSourceCompletionCell *self);
+
+G_END_DECLS
diff --git a/gtksourceview/gtksourcecompletioncell.c b/gtksourceview/gtksourcecompletioncell.c
new file mode 100644
index 0000000000000000000000000000000000000000..1db71e82196f35eb832a4987f9dca351523c4301
--- /dev/null
+++ b/gtksourceview/gtksourcecompletioncell.c
@@ -0,0 +1,452 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2020 Christian Hergert
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include "gtksource-enumtypes.h"
+#include "gtksourcecompletioncell-private.h"
+
+struct _GtkSourceCompletionCell
+{
+ GtkWidget widget;
+ GtkSourceCompletionColumn column;
+ GtkWidget *child;
+ PangoAttrList *attrs;
+};
+
+enum {
+ PROP_0,
+ PROP_COLUMN,
+ PROP_MARKUP,
+ PROP_PAINTABLE,
+ PROP_TEXT,
+ PROP_WIDGET,
+ N_PROPS
+};
+
+G_DEFINE_TYPE (GtkSourceCompletionCell, gtk_source_completion_cell, GTK_TYPE_WIDGET)
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+gtk_source_completion_cell_set_column (GtkSourceCompletionCell *self,
+ GtkSourceCompletionColumn column)
+{
+ g_assert (GTK_SOURCE_IS_COMPLETION_CELL (self));
+
+ self->column = column;
+
+ switch (column)
+ {
+ case GTK_SOURCE_COMPLETION_COLUMN_ICON:
+ gtk_widget_add_css_class (GTK_WIDGET (self), "icon");
+ break;
+
+ case GTK_SOURCE_COMPLETION_COLUMN_BEFORE:
+ gtk_widget_add_css_class (GTK_WIDGET (self), "before");
+ break;
+
+ case GTK_SOURCE_COMPLETION_COLUMN_TYPED_TEXT:
+ gtk_widget_add_css_class (GTK_WIDGET (self), "typed-text");
+ break;
+
+ case GTK_SOURCE_COMPLETION_COLUMN_AFTER:
+ gtk_widget_add_css_class (GTK_WIDGET (self), "after");
+ break;
+
+ case GTK_SOURCE_COMPLETION_COLUMN_COMMENT:
+ gtk_widget_add_css_class (GTK_WIDGET (self), "comment");
+ break;
+
+ case GTK_SOURCE_COMPLETION_COLUMN_DETAILS:
+ gtk_widget_add_css_class (GTK_WIDGET (self), "details");
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void
+gtk_source_completion_cell_dispose (GObject *object)
+{
+ GtkSourceCompletionCell *self = (GtkSourceCompletionCell *)object;
+
+ g_clear_pointer (&self->child, gtk_widget_unparent);
+ g_clear_pointer (&self->attrs, pango_attr_list_unref);
+
+ G_OBJECT_CLASS (gtk_source_completion_cell_parent_class)->dispose (object);
+}
+
+static void
+gtk_source_completion_cell_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceCompletionCell *self = GTK_SOURCE_COMPLETION_CELL (object);
+
+ switch (prop_id)
+ {
+ case PROP_COLUMN:
+ g_value_set_enum (value, self->column);
+ break;
+
+ case PROP_TEXT:
+ if (GTK_IS_LABEL (self->child))
+ g_value_set_string (value, gtk_label_get_label (GTK_LABEL (self->child)));
+ break;
+
+ case PROP_MARKUP:
+ if (GTK_IS_LABEL (self->child) &&
+ gtk_label_get_use_markup (GTK_LABEL (self->child)))
+ g_value_set_string (value, gtk_label_get_label (GTK_LABEL (self->child)));
+ break;
+
+ case PROP_PAINTABLE:
+ if (GTK_IS_IMAGE (self->child))
+ g_value_set_object (value, gtk_image_get_paintable (GTK_IMAGE (self->child)));
+ break;
+
+ case PROP_WIDGET:
+ g_value_set_object (value, self->child);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gtk_source_completion_cell_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceCompletionCell *self = GTK_SOURCE_COMPLETION_CELL (object);
+
+ switch (prop_id)
+ {
+ case PROP_COLUMN:
+ gtk_source_completion_cell_set_column (self, g_value_get_enum (value));
+ break;
+
+ case PROP_MARKUP:
+ gtk_source_completion_cell_set_markup (self, g_value_get_string (value));
+ break;
+
+ case PROP_TEXT:
+ gtk_source_completion_cell_set_text (self, g_value_get_string (value));
+ break;
+
+ case PROP_PAINTABLE:
+ gtk_source_completion_cell_set_paintable (self, g_value_get_object (value));
+ break;
+
+ case PROP_WIDGET:
+ gtk_source_completion_cell_set_widget (self, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gtk_source_completion_cell_class_init (GtkSourceCompletionCellClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = gtk_source_completion_cell_dispose;
+ object_class->get_property = gtk_source_completion_cell_get_property;
+ object_class->set_property = gtk_source_completion_cell_set_property;
+
+ properties [PROP_COLUMN] =
+ g_param_spec_enum ("column",
+ "Column",
+ "Column",
+ GTK_SOURCE_TYPE_COMPLETION_COLUMN,
+ GTK_SOURCE_COMPLETION_COLUMN_TYPED_TEXT,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_MARKUP] =
+ g_param_spec_string ("markup",
+ "Markup",
+ "Markup",
+ NULL,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_TEXT] =
+ g_param_spec_string ("text",
+ "Text",
+ "Text",
+ NULL,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_PAINTABLE] =
+ g_param_spec_object ("paintable",
+ "Paintable",
+ "Paintable",
+ GDK_TYPE_PAINTABLE,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_WIDGET] =
+ g_param_spec_object ("widget",
+ "Widget",
+ "Widget",
+ GTK_TYPE_WIDGET,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ gtk_widget_class_set_css_name (widget_class, "cell");
+ gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
+}
+
+static void
+gtk_source_completion_cell_init (GtkSourceCompletionCell *self)
+{
+ gtk_widget_add_css_class (GTK_WIDGET (self), "cell");
+}
+
+void
+gtk_source_completion_cell_set_markup (GtkSourceCompletionCell *self,
+ const char *markup)
+{
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_CELL (self));
+
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_CELL (self));
+
+ if (!GTK_IS_LABEL (self->child))
+ {
+ GtkWidget *child = gtk_label_new (NULL);
+ gtk_source_completion_cell_set_widget (self, child);
+ }
+
+ gtk_label_set_text (GTK_LABEL (self->child), markup);
+ gtk_label_set_use_markup (GTK_LABEL (self->child), TRUE);
+}
+
+void
+gtk_source_completion_cell_set_text (GtkSourceCompletionCell *self,
+ const char *text)
+{
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_CELL (self));
+
+ if (!GTK_IS_LABEL (self->child))
+ {
+ GtkWidget *child = gtk_label_new (NULL);
+ gtk_source_completion_cell_set_widget (self, child);
+ }
+
+ if (gtk_label_get_use_markup (GTK_LABEL (self->child)))
+ {
+ gtk_label_set_use_markup (GTK_LABEL (self->child), FALSE);
+ }
+
+ if (g_strcmp0 (gtk_label_get_label (GTK_LABEL (self->child)), text) != 0)
+ {
+ gtk_label_set_label (GTK_LABEL (self->child), text);
+ }
+}
+
+void
+gtk_source_completion_cell_set_text_with_attributes (GtkSourceCompletionCell *self,
+ const char *text,
+ PangoAttrList *attrs)
+{
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_CELL (self));
+
+ gtk_source_completion_cell_set_text (self, text);
+
+ if (attrs != NULL)
+ {
+ if (self->attrs != NULL)
+ {
+ PangoAttrList *copy = pango_attr_list_copy (self->attrs);
+ pango_attr_list_splice (copy, attrs, 0, 0);
+ gtk_label_set_attributes (GTK_LABEL (self->child), copy);
+ g_clear_pointer (©, pango_attr_list_unref);
+ }
+ else
+ {
+ gtk_label_set_attributes (GTK_LABEL (self->child), attrs);
+ }
+ }
+ else
+ {
+ gtk_label_set_attributes (GTK_LABEL (self->child), self->attrs);
+ }
+}
+
+void
+gtk_source_completion_cell_set_paintable (GtkSourceCompletionCell *self,
+ GdkPaintable *paintable)
+{
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_CELL (self));
+ g_return_if_fail (!paintable || GDK_IS_PAINTABLE (paintable));
+
+ gtk_source_completion_cell_set_widget (self, gtk_image_new_from_paintable (paintable));
+}
+
+/**
+ * gtk_source_completion_cell_get_widget:
+ * @self: a #GtkSourceCompletionCell
+ *
+ * Gets the child #GtkWidget, if any.
+ *
+ * Returns: (transfer none) (nullable): a #GtkWidget or %NULL
+ *
+ * Since: 5.0
+ */
+GtkWidget *
+gtk_source_completion_cell_get_widget (GtkSourceCompletionCell *self)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_CELL (self), NULL);
+
+ return self->child;
+}
+
+void
+gtk_source_completion_cell_set_widget (GtkSourceCompletionCell *self,
+ GtkWidget *widget)
+{
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_CELL (self));
+ g_return_if_fail (!widget || GTK_IS_WIDGET (widget));
+ g_return_if_fail (!widget || gtk_widget_get_parent (widget) == NULL);
+
+ if (widget == self->child)
+ return;
+
+ g_clear_pointer (&self->child, gtk_widget_unparent);
+
+ if (widget != NULL)
+ {
+ self->child = widget;
+ gtk_widget_set_parent (widget, GTK_WIDGET (self));
+
+ if (GTK_IS_LABEL (widget))
+ {
+ gtk_label_set_attributes (GTK_LABEL (widget), self->attrs);
+
+ if (self->column == GTK_SOURCE_COMPLETION_COLUMN_BEFORE)
+ {
+ gtk_label_set_xalign (GTK_LABEL (widget), 1.0);
+ }
+ else if (self->column == GTK_SOURCE_COMPLETION_COLUMN_AFTER ||
+ self->column == GTK_SOURCE_COMPLETION_COLUMN_TYPED_TEXT ||
+ self->column == GTK_SOURCE_COMPLETION_COLUMN_COMMENT ||
+ self->column == GTK_SOURCE_COMPLETION_COLUMN_DETAILS)
+ {
+ gtk_label_set_xalign (GTK_LABEL (widget), 0.0);
+ }
+
+ if (self->column == GTK_SOURCE_COMPLETION_COLUMN_COMMENT)
+ {
+ gtk_label_set_xalign (GTK_LABEL (widget), 0.0);
+ gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END);
+ gtk_label_set_wrap (GTK_LABEL (widget), TRUE);
+ gtk_label_set_max_width_chars (GTK_LABEL (widget), 50);
+ gtk_widget_set_valign (widget, GTK_ALIGN_BASELINE);
+ }
+ }
+ else if (GTK_IS_IMAGE (widget))
+ {
+ if (self->column == GTK_SOURCE_COMPLETION_COLUMN_AFTER)
+ {
+ gtk_widget_set_halign (widget, GTK_ALIGN_END);
+ }
+ }
+ }
+}
+
+GtkSourceCompletionColumn
+gtk_source_completion_cell_get_column (GtkSourceCompletionCell *self)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_CELL (self), 0);
+
+ return self->column;
+}
+
+void
+_gtk_source_completion_cell_set_attrs (GtkSourceCompletionCell *self,
+ PangoAttrList *attrs)
+{
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_CELL (self));
+
+ if (attrs != self->attrs)
+ {
+ g_clear_pointer (&self->attrs, pango_attr_list_unref);
+
+ if (attrs)
+ {
+ self->attrs = pango_attr_list_ref (attrs);
+ }
+
+ if (GTK_IS_LABEL (self->child))
+ {
+ gtk_label_set_attributes (GTK_LABEL (self->child), attrs);
+ }
+ }
+}
+
+void
+gtk_source_completion_cell_set_icon_name (GtkSourceCompletionCell *self,
+ const char *icon_name)
+{
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_CELL (self));
+
+ if (!GTK_IS_IMAGE (self->child))
+ {
+ GtkWidget *image = gtk_image_new ();
+ gtk_source_completion_cell_set_widget (self, image);
+ }
+
+ if (g_strcmp0 (icon_name, gtk_image_get_icon_name (GTK_IMAGE (self->child))) != 0)
+ {
+ gtk_image_set_from_icon_name (GTK_IMAGE (self->child), icon_name);
+ }
+}
+
+void
+gtk_source_completion_cell_set_gicon (GtkSourceCompletionCell *self,
+ GIcon *gicon)
+{
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_CELL (self));
+ g_return_if_fail (!gicon || G_IS_ICON (gicon));
+
+ if (!GTK_IS_IMAGE (self->child))
+ {
+ GtkWidget *image = gtk_image_new ();
+ gtk_source_completion_cell_set_widget (self, image);
+ }
+
+ gtk_image_set_from_gicon (GTK_IMAGE (self->child), gicon);
+}
+
+gboolean
+_gtk_source_completion_cell_is_empty (GtkSourceCompletionCell *self)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_CELL (self), FALSE);
+
+ return self->child == NULL;
+}
diff --git a/gtksourceview/gtksourcecompletioncell.h b/gtksourceview/gtksourcecompletioncell.h
new file mode 100644
index 0000000000000000000000000000000000000000..8c490443b4117f2b0ea07f9c074ac9b4a2fa0500
--- /dev/null
+++ b/gtksourceview/gtksourcecompletioncell.h
@@ -0,0 +1,72 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2020 Christian Hergert
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#pragma once
+
+#include
+
+#include "gtksourcetypes.h"
+
+G_BEGIN_DECLS
+
+#define GTK_SOURCE_TYPE_COMPLETION_CELL (gtk_source_completion_cell_get_type())
+
+typedef enum _GtkSourceCompletionColumn
+{
+ GTK_SOURCE_COMPLETION_COLUMN_ICON = 0,
+ GTK_SOURCE_COMPLETION_COLUMN_BEFORE = 1,
+ GTK_SOURCE_COMPLETION_COLUMN_TYPED_TEXT = 2,
+ GTK_SOURCE_COMPLETION_COLUMN_AFTER = 3,
+ GTK_SOURCE_COMPLETION_COLUMN_COMMENT = 4,
+ GTK_SOURCE_COMPLETION_COLUMN_DETAILS = 5,
+} GtkSourceCompletionColumn;
+
+GTK_SOURCE_AVAILABLE_IN_5_0
+G_DECLARE_FINAL_TYPE (GtkSourceCompletionCell, gtk_source_completion_cell, GTK_SOURCE, COMPLETION_CELL, GtkWidget)
+
+GTK_SOURCE_AVAILABLE_IN_5_0
+GtkSourceCompletionColumn gtk_source_completion_cell_get_column (GtkSourceCompletionCell *self);
+GTK_SOURCE_AVAILABLE_IN_5_0
+GtkWidget *gtk_source_completion_cell_get_widget (GtkSourceCompletionCell *self);
+GTK_SOURCE_AVAILABLE_IN_5_0
+void gtk_source_completion_cell_set_widget (GtkSourceCompletionCell *self,
+ GtkWidget *child);
+GTK_SOURCE_AVAILABLE_IN_5_0
+void gtk_source_completion_cell_set_markup (GtkSourceCompletionCell *self,
+ const char *markup);
+GTK_SOURCE_AVAILABLE_IN_5_0
+void gtk_source_completion_cell_set_icon_name (GtkSourceCompletionCell *self,
+ const char *icon_name);
+GTK_SOURCE_AVAILABLE_IN_5_0
+void gtk_source_completion_cell_set_gicon (GtkSourceCompletionCell *self,
+ GIcon *gicon);
+GTK_SOURCE_AVAILABLE_IN_5_0
+void gtk_source_completion_cell_set_paintable (GtkSourceCompletionCell *self,
+ GdkPaintable *paintable);
+GTK_SOURCE_AVAILABLE_IN_5_0
+void gtk_source_completion_cell_set_text (GtkSourceCompletionCell *self,
+ const char *text);
+GTK_SOURCE_AVAILABLE_IN_5_0
+void gtk_source_completion_cell_set_text_with_attributes (GtkSourceCompletionCell *self,
+ const char *text,
+ PangoAttrList *attrs);
+
+G_END_DECLS
diff --git a/gtksourceview/gtksourcecompletioncontainer.c b/gtksourceview/gtksourcecompletioncontainer.c
deleted file mode 100644
index 0e28adc5c11c9764b07599d8bd5f694dedebd044..0000000000000000000000000000000000000000
--- a/gtksourceview/gtksourcecompletioncontainer.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- */
-/*
- * This file is part of GtkSourceView
- *
- * Copyright (C) 2013, 2014, 2016 - Sébastien Wilmet
- *
- * GtkSourceView is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * GtkSourceView 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, see .
- */
-
-/*
- * Custom sizing of the scrolled window containing the GtkTreeView containing
- * the completion proposals. If the GtkTreeView is small enough, the scrolled
- * window returns the natural size of the GtkTreeView. If it exceeds a certain
- * size, the scrolled window returns a smaller size, with the height at a row
- * boundary of the GtkTreeView.
- *
- * The purpose is to have a compact completion window, with a certain size
- * limit.
- */
-
-#ifdef HAVE_CONFIG_H
-#include
-#endif
-
-#include "gtksourcecompletioncontainer.h"
-
-#define UNREALIZED_WIDTH 350
-#define MAX_HEIGHT 180
-
-G_DEFINE_TYPE (GtkSourceCompletionContainer,
- _gtk_source_completion_container,
- GTK_TYPE_SCROLLED_WINDOW);
-
-static gint
-get_max_width (GtkSourceCompletionContainer *container)
-{
- if (gtk_widget_get_realized (GTK_WIDGET (container)))
- {
- GdkDisplay *display;
- GdkMonitor *monitor;
- GtkWidget *toplevel;
- GdkWindow *window;
- GdkRectangle geom;
- gint max_width;
- gint xorigin;
-
- toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container));
- window = gtk_widget_get_window (toplevel);
- display = gtk_widget_get_display (toplevel);
- monitor = gdk_display_get_monitor_at_window (display, window);
- gdk_monitor_get_geometry (monitor, &geom);
-
- gdk_window_get_origin (window, &xorigin, NULL);
-
- /* Just in case xorigin is not the global coordinate limit the max
- * size to the monitor width.
- */
- max_width = MIN (geom.width + geom.x - xorigin, geom.width);
-
- return MAX (max_width, UNREALIZED_WIDTH);
- }
-
- return UNREALIZED_WIDTH;
-}
-
-static void
-_gtk_source_completion_container_get_preferred_width (GtkWidget *widget,
- gint *min_width,
- gint *nat_width)
-{
- GtkSourceCompletionContainer *container = GTK_SOURCE_COMPLETION_CONTAINER (widget);
- GtkWidget *child;
- GtkRequisition nat_size;
- gint width;
-
- child = gtk_bin_get_child (GTK_BIN (container));
- gtk_widget_get_preferred_size (child, NULL, &nat_size);
-
- width = MIN (nat_size.width, get_max_width (container));
-
- if (GTK_WIDGET_CLASS (_gtk_source_completion_container_parent_class)->get_preferred_width != NULL)
- {
- gint min_width_parent = 0;
-
- GTK_WIDGET_CLASS (_gtk_source_completion_container_parent_class)->get_preferred_width (widget,
- &min_width_parent,
- NULL);
-
- width = MAX (width, min_width_parent);
- }
-
- if (min_width != NULL)
- {
- *min_width = width;
- }
-
- if (nat_width != NULL)
- {
- *nat_width = width;
- }
-
- g_return_if_fail (width >= 0);
-}
-
-static gint
-get_row_height (GtkSourceCompletionContainer *container,
- gint tree_view_height)
-{
- GtkWidget *tree_view;
- GtkTreeModel *model;
- gint nb_rows;
-
- /* For another possible implementation, see gtkentrycompletion.c in the
- * GTK+ source code (the _gtk_entry_completion_resize_popup() function).
- * It uses gtk_tree_view_column_cell_get_size() for retrieving the
- * height, plus gtk_widget_style_get() to retrieve the
- * "vertical-separator" height (note that the vertical separator must
- * probably be counted one less time than the number or rows).
- * But using that technique is buggy, it returns a smaller height (it's
- * maybe a bug in GtkTreeView, or there are other missing parameters).
- *
- * Note that the following implementation doesn't take into account
- * "vertical-separator". If there are some sizing bugs, it's maybe the
- * source of the problem. (note that on my system the separator size was
- * 0).
- */
-
- tree_view = gtk_bin_get_child (GTK_BIN (container));
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
-
- if (model == NULL)
- {
- return 0;
- }
-
- nb_rows = gtk_tree_model_iter_n_children (model, NULL);
-
- if (nb_rows == 0)
- {
- return 0;
- }
-
- return tree_view_height / nb_rows;
-}
-
-/* Return a height at a row boundary of the GtkTreeView. */
-static void
-_gtk_source_completion_container_get_preferred_height (GtkWidget *widget,
- gint *min_height,
- gint *nat_height)
-{
- GtkSourceCompletionContainer *container = GTK_SOURCE_COMPLETION_CONTAINER (widget);
- GtkWidget *child;
- GtkRequisition nat_size;
- gint height;
-
- child = gtk_bin_get_child (GTK_BIN (container));
- gtk_widget_get_preferred_size (child, NULL, &nat_size);
-
- if (nat_size.height <= MAX_HEIGHT)
- {
- height = nat_size.height;
- }
- else
- {
- gint row_height = get_row_height (container, nat_size.height);
- gint n_rows_allowed = row_height != 0 ? MAX_HEIGHT / row_height : 0;
-
- height = n_rows_allowed * row_height;
- }
-
- if (GTK_WIDGET_CLASS (_gtk_source_completion_container_parent_class)->get_preferred_height != NULL)
- {
- gint min_height_parent = 0;
-
- GTK_WIDGET_CLASS (_gtk_source_completion_container_parent_class)->get_preferred_height (widget,
- &min_height_parent,
- NULL);
-
- height = MAX (height, min_height_parent);
- }
-
- if (min_height != NULL)
- {
- *min_height = height;
- }
-
- if (nat_height != NULL)
- {
- *nat_height = height;
- }
-
- g_return_if_fail (height >= 0);
-}
-
-static void
-_gtk_source_completion_container_class_init (GtkSourceCompletionContainerClass *klass)
-{
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-
- widget_class->get_preferred_width = _gtk_source_completion_container_get_preferred_width;
- widget_class->get_preferred_height = _gtk_source_completion_container_get_preferred_height;
-}
-
-static void
-_gtk_source_completion_container_init (GtkSourceCompletionContainer *container)
-{
-}
-
-GtkSourceCompletionContainer *
-_gtk_source_completion_container_new (void)
-{
- return g_object_new (GTK_SOURCE_TYPE_COMPLETION_CONTAINER, NULL);
-}
diff --git a/gtksourceview/gtksourcecompletioncontainer.h b/gtksourceview/gtksourcecompletioncontainer.h
deleted file mode 100644
index 7f262cc1768d137533151ca55590b3f41389b98c..0000000000000000000000000000000000000000
--- a/gtksourceview/gtksourcecompletioncontainer.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
- *
- * This file is part of GtkSourceView
- *
- * Copyright (C) 2013 - Sébastien Wilmet
- *
- * GtkSourceView is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * GtkSourceView 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, see .
- */
-
-#ifndef GTK_SOURCE_COMPLETION_CONTAINER_H
-#define GTK_SOURCE_COMPLETION_CONTAINER_H
-
-#include
-#include "gtksourcetypes-private.h"
-
-G_BEGIN_DECLS
-
-#define GTK_SOURCE_TYPE_COMPLETION_CONTAINER (_gtk_source_completion_container_get_type ())
-#define GTK_SOURCE_COMPLETION_CONTAINER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_SOURCE_TYPE_COMPLETION_CONTAINER, GtkSourceCompletionContainer))
-#define GTK_SOURCE_COMPLETION_CONTAINER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_SOURCE_TYPE_COMPLETION_CONTAINER, GtkSourceCompletionContainerClass)
-#define GTK_SOURCE_IS_COMPLETION_CONTAINER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_SOURCE_TYPE_COMPLETION_CONTAINER))
-#define GTK_SOURCE_IS_COMPLETION_CONTAINER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_SOURCE_TYPE_COMPLETION_CONTAINER))
-#define GTK_SOURCE_COMPLETION_CONTAINER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_SOURCE_TYPE_COMPLETION_CONTAINER, GtkSourceCompletionContainerClass))
-
-typedef struct _GtkSourceCompletionContainerClass GtkSourceCompletionContainerClass;
-
-struct _GtkSourceCompletionContainer
-{
- GtkScrolledWindow parent;
-};
-
-struct _GtkSourceCompletionContainerClass
-{
- GtkScrolledWindowClass parent_class;
-};
-
-G_GNUC_INTERNAL
-GType _gtk_source_completion_container_get_type (void) G_GNUC_CONST;
-
-G_GNUC_INTERNAL
-GtkSourceCompletionContainer *
- _gtk_source_completion_container_new (void);
-
-G_END_DECLS
-
-#endif /* GTK_SOURCE_COMPLETION_CONTAINER_H */
diff --git a/gtksourceview/gtksourcecompletioncontext-private.h b/gtksourceview/gtksourcecompletioncontext-private.h
new file mode 100644
index 0000000000000000000000000000000000000000..c025315c05b08361ad11bf3b7b6fc9cadea44930
--- /dev/null
+++ b/gtksourceview/gtksourcecompletioncontext-private.h
@@ -0,0 +1,56 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2020 Christian Hergert
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#pragma once
+
+#include
+
+#include "gtksourcecompletioncontext.h"
+
+G_BEGIN_DECLS
+
+GtkSourceCompletionContext *_gtk_source_completion_context_new (GtkSourceCompletion *completion);
+gboolean _gtk_source_completion_context_get_item_full (GtkSourceCompletionContext *self,
+ guint position,
+ GtkSourceCompletionProvider **provider,
+ GtkSourceCompletionProposal **proposal);
+void _gtk_source_completion_context_add_provider (GtkSourceCompletionContext *self,
+ GtkSourceCompletionProvider *provider);
+void _gtk_source_completion_context_remove_provider (GtkSourceCompletionContext *self,
+ GtkSourceCompletionProvider *provider);
+gboolean _gtk_source_completion_context_can_refilter (GtkSourceCompletionContext *self,
+ const GtkTextIter *begin,
+ const GtkTextIter *end);
+void _gtk_source_completion_context_refilter (GtkSourceCompletionContext *self);
+gboolean _gtk_source_completion_context_iter_invalidates (GtkSourceCompletionContext *self,
+ const GtkTextIter *iter);
+void _gtk_source_completion_context_complete_async (GtkSourceCompletionContext *self,
+ GtkSourceCompletionActivation activation,
+ const GtkTextIter *begin,
+ const GtkTextIter *end,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean _gtk_source_completion_context_complete_finish (GtkSourceCompletionContext *self,
+ GAsyncResult *result,
+ GError **error);
+
+G_END_DECLS
diff --git a/gtksourceview/gtksourcecompletioncontext.c b/gtksourceview/gtksourcecompletioncontext.c
index 0c31956ebbe9298a0968eab240e351ae6c675e73..9a84d6c9b719b11e6a8353a4edeede89febcf8bd 100644
--- a/gtksourceview/gtksourcecompletioncontext.c
+++ b/gtksourceview/gtksourcecompletioncontext.c
@@ -1,8 +1,7 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- *
- *
+/*
* This file is part of GtkSourceView
*
- * Copyright (C) 2009 - Jesse van den Kieboom
+ * Copyright 2020 Christian Hergert
*
* GtkSourceView is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -16,166 +15,187 @@
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, see .
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
*/
-/**
- * SECTION:completioncontext
- * @title: GtkSourceCompletionContext
- * @short_description: The context of a completion
- *
- * Initially, the completion window is hidden. For a completion to occur, it has
- * to be activated. The different possible activations are listed in
- * #GtkSourceCompletionActivation. When an activation occurs, a
- * #GtkSourceCompletionContext object is created, and the eligible providers are
- * asked to add proposals with gtk_source_completion_context_add_proposals().
- *
- * If no proposals are added, the completion window remains hidden, and the
- * context is destroyed.
- *
- * On the other hand, if proposals are added, the completion window becomes
- * visible, and the user can choose a proposal. If the user is not happy with
- * the shown proposals, he or she can insert or delete characters, to modify the
- * completion context and therefore hoping to see the proposal he or she wants.
- * This means that when an insertion or deletion occurs in the #GtkTextBuffer
- * when the completion window is visible, the eligible providers are again asked
- * to add proposals. The #GtkSourceCompletionContext:activation remains the
- * same in this case.
- *
- * When the completion window is hidden, the interactive completion is triggered
- * only on insertion in the buffer, not on deletion. Once the completion window
- * is visible, then on each insertion or deletion, there is a new population and
- * the providers are asked to add proposals. If there are no more proposals, the
- * completion window disappears. So if you want to keep the completion window
- * visible, but there are no proposals, you can insert a dummy proposal named
- * "No proposals". For example, the user types progressively the name of
- * a function, and some proposals appear. The user types a bad character and
- * there are no proposals anymore. What the user wants is to delete the last
- * character, and see the previous proposals. If the completion window
- * disappears, the previous proposals will not reappear on the character
- * deletion.
- *
- * A #GtkTextIter is associated with the context, this is where the completion
- * takes place. With this #GtkTextIter, you can get the associated
- * #GtkTextBuffer with gtk_text_iter_get_buffer().
- */
-#ifdef HAVE_CONFIG_H
-#include
-#endif
-#include "gtksourcecompletioncontext.h"
-#include "gtksource-enumtypes.h"
-#include "gtksourcecompletionprovider.h"
+#include "config.h"
+
+#include
+
+#include "gtksourcebuffer.h"
#include "gtksourcecompletion.h"
+#include "gtksourcecompletioncontext-private.h"
+#include "gtksourcecompletionproposal.h"
+#include "gtksourcecompletionprovider.h"
-struct _GtkSourceCompletionContextPrivate
+struct _GtkSourceCompletionContext
{
+ GObject parent_instance;
+
GtkSourceCompletion *completion;
- GtkTextMark *mark;
+ GArray *providers;
+
+ GtkTextMark *begin_mark;
+ GtkTextMark *end_mark;
+
GtkSourceCompletionActivation activation;
+
+ guint busy : 1;
+ guint has_populated : 1;
+ guint empty : 1;
};
-enum
+typedef struct
{
- PROP_0,
- PROP_COMPLETION,
- PROP_ITER,
- PROP_ACTIVATION
-};
+ GtkSourceCompletionProvider *provider;
+ GListModel *results;
+ GError *error;
+ gulong items_changed_handler;
+} ProviderInfo;
-enum
+typedef struct
{
- CANCELLED,
- N_SIGNALS
-};
+ guint n_active;
+} CompleteTaskData;
+
+static void list_model_iface_init (GListModelInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GtkSourceCompletionContext, gtk_source_completion_context, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, list_model_iface_init))
-static guint context_signals[N_SIGNALS];
+enum {
+ PROP_0,
+ PROP_BUSY,
+ PROP_COMPLETION,
+ PROP_EMPTY,
+ N_PROPS
+};
-G_DEFINE_TYPE_WITH_PRIVATE (GtkSourceCompletionContext, gtk_source_completion_context, G_TYPE_INITIALLY_UNOWNED)
+static GParamSpec *properties [N_PROPS];
static void
-gtk_source_completion_context_dispose (GObject *object)
+clear_provider_info (gpointer data)
{
- GtkSourceCompletionContext *context = GTK_SOURCE_COMPLETION_CONTEXT (object);
+ ProviderInfo *info = data;
- if (context->priv->mark != NULL)
+ if (info->items_changed_handler != 0)
{
- GtkTextBuffer *buffer = gtk_text_mark_get_buffer (context->priv->mark);
+ g_signal_handler_disconnect (info->results, info->items_changed_handler);
+ info->items_changed_handler = 0;
+ }
- if (buffer != NULL)
- {
- gtk_text_buffer_delete_mark (buffer, context->priv->mark);
- }
+ g_clear_object (&info->provider);
+ g_clear_object (&info->results);
+ g_clear_error (&info->error);
+}
- g_object_unref (context->priv->mark);
- context->priv->mark = NULL;
- }
+static gint
+compare_provider_info (gconstpointer a,
+ gconstpointer b,
+ gpointer user_data)
+{
+ GtkSourceCompletionContext *self = user_data;
+ const ProviderInfo *info_a = a;
+ const ProviderInfo *info_b = b;
+ int priority_a = gtk_source_completion_provider_get_priority (info_a->provider, self);
+ int priority_b = gtk_source_completion_provider_get_priority (info_b->provider, self);
+
+ if (priority_a > priority_b)
+ return -1;
+ else if (priority_a < priority_b)
+ return 1;
+ else
+ return 0;
+}
- g_clear_object (&context->priv->completion);
+static void
+complete_task_data_free (gpointer data)
+{
+ CompleteTaskData *task_data = data;
- G_OBJECT_CLASS (gtk_source_completion_context_parent_class)->dispose (object);
+ g_slice_free (CompleteTaskData, task_data);
}
static void
-set_iter (GtkSourceCompletionContext *context,
- GtkTextIter *iter)
+gtk_source_completion_context_update_empty (GtkSourceCompletionContext *self)
{
- GtkTextBuffer *buffer;
+ gboolean empty = TRUE;
- buffer = gtk_text_iter_get_buffer (iter);
+ g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (self));
- if (context->priv->mark != NULL)
+ for (guint i = 0; i < self->providers->len; i++)
{
- GtkTextBuffer *old_buffer;
+ const ProviderInfo *info = &g_array_index (self->providers, ProviderInfo, i);
- old_buffer = gtk_text_mark_get_buffer (context->priv->mark);
-
- if (old_buffer != buffer)
+ if (info->results != NULL && g_list_model_get_n_items (info->results) > 0)
{
- g_object_unref (context->priv->mark);
- context->priv->mark = NULL;
+ empty = FALSE;
+ break;
}
}
- if (context->priv->mark == NULL)
- {
- context->priv->mark = gtk_text_buffer_create_mark (buffer, NULL, iter, FALSE);
- g_object_ref (context->priv->mark);
- }
- else
+ if (self->empty != empty)
{
- gtk_text_buffer_move_mark (buffer, context->priv->mark, iter);
+ self->empty = empty;
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_EMPTY]);
}
-
- g_object_notify (G_OBJECT (context), "iter");
}
static void
-gtk_source_completion_context_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
+gtk_source_completion_context_mark_failed (GtkSourceCompletionContext *self,
+ GtkSourceCompletionProvider *provider,
+ const GError *error)
{
- GtkSourceCompletionContext *context = GTK_SOURCE_COMPLETION_CONTEXT (object);
+ g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (self));
+ g_assert (GTK_SOURCE_IS_COMPLETION_PROVIDER (provider));
+ g_assert (error != NULL);
- switch (prop_id)
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) ||
+ g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
+ return;
+
+ for (guint i = 0; i < self->providers->len; i++)
{
- case PROP_COMPLETION:
- context->priv->completion = g_value_dup_object (value);
- break;
+ ProviderInfo *info = &g_array_index (self->providers, ProviderInfo, i);
- case PROP_ITER:
- set_iter (context, g_value_get_boxed (value));
- break;
+ if (info->provider == provider)
+ {
+ if (error != info->error)
+ {
+ g_clear_error (&info->error);
+ info->error = g_error_copy (error);
+ }
- case PROP_ACTIVATION:
- context->priv->activation = g_value_get_flags (value);
break;
+ }
+ }
+}
+
+static void
+gtk_source_completion_context_dispose (GObject *object)
+{
+ GtkSourceCompletionContext *self = (GtkSourceCompletionContext *)object;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ g_clear_pointer (&self->providers, g_array_unref);
+ g_clear_object (&self->completion);
+
+ if (self->begin_mark != NULL)
+ {
+ gtk_text_buffer_delete_mark (gtk_text_mark_get_buffer (self->begin_mark), self->begin_mark);
+ g_clear_object (&self->begin_mark);
+ }
+
+ if (self->end_mark != NULL)
+ {
+ gtk_text_buffer_delete_mark (gtk_text_mark_get_buffer (self->end_mark), self->end_mark);
+ g_clear_object (&self->end_mark);
}
+
+ G_OBJECT_CLASS (gtk_source_completion_context_parent_class)->dispose (object);
}
static void
@@ -184,31 +204,43 @@ gtk_source_completion_context_get_property (GObject *object,
GValue *value,
GParamSpec *pspec)
{
- GtkSourceCompletionContext *context = GTK_SOURCE_COMPLETION_CONTEXT (object);
+ GtkSourceCompletionContext *self = GTK_SOURCE_COMPLETION_CONTEXT (object);
switch (prop_id)
{
- case PROP_COMPLETION:
- g_value_set_object (value, context->priv->completion);
- break;
+ case PROP_BUSY:
+ g_value_set_boolean (value, gtk_source_completion_context_get_busy (self));
+ break;
- case PROP_ITER:
- {
- GtkTextIter iter;
+ case PROP_COMPLETION:
+ g_value_set_object (value, gtk_source_completion_context_get_completion (self));
+ break;
- if (gtk_source_completion_context_get_iter (context, &iter))
- {
- g_value_set_boxed (value, &iter);
- }
- }
- break;
+ case PROP_EMPTY:
+ g_value_set_boolean (value, gtk_source_completion_context_get_empty (self));
+ break;
- case PROP_ACTIVATION:
- g_value_set_flags (value, context->priv->activation);
- break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gtk_source_completion_context_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceCompletionContext *self = GTK_SOURCE_COMPLETION_CONTEXT (object);
+
+ switch (prop_id)
+ {
+ case PROP_COMPLETION:
+ self->completion = g_value_dup_object (value);
+ break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
@@ -217,197 +249,790 @@ gtk_source_completion_context_class_init (GtkSourceCompletionContextClass *klass
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
- object_class->set_property = gtk_source_completion_context_set_property;
- object_class->get_property = gtk_source_completion_context_get_property;
object_class->dispose = gtk_source_completion_context_dispose;
+ object_class->get_property = gtk_source_completion_context_get_property;
+ object_class->set_property = gtk_source_completion_context_set_property;
/**
- * GtkSourceCompletionContext::cancelled:
- *
- * Emitted when the current population of proposals has been cancelled.
- * Providers adding proposals asynchronously should connect to this signal
- * to know when to cancel running proposal queries.
- **/
- context_signals[CANCELLED] =
- g_signal_new ("cancelled",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (GtkSourceCompletionContextClass, cancelled),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
- g_signal_set_va_marshaller (context_signals[CANCELLED],
- G_TYPE_FROM_CLASS (klass),
- g_cclosure_marshal_VOID__VOIDv);
+ * GtkSourceCompletionContext:busy:
+ *
+ * The "busy" property is %TRUE while the completion context is
+ * populating completion proposals.
+ *
+ * Since: 5.0
+ */
+ properties [PROP_BUSY] =
+ g_param_spec_boolean ("busy",
+ "Busy",
+ "Is the completion context busy populating",
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
/**
- * GtkSourceCompletionContext:completion:
- *
- * The #GtkSourceCompletion associated with the context.
- **/
- g_object_class_install_property (object_class,
- PROP_COMPLETION,
- g_param_spec_object ("completion",
- "Completion",
- "The completion object to which the context belongs",
- GTK_SOURCE_TYPE_COMPLETION,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS));
+ * GtkSourceCompletionContext:empty:
+ *
+ * The "empty" property is %TRUE when there are no results.
+ *
+ * It will be notified when the first result is added or the last
+ * result is removed.
+ *
+ * Since: 5.0
+ */
+ properties [PROP_EMPTY] =
+ g_param_spec_boolean ("empty",
+ "Empty",
+ "If the context has no results",
+ TRUE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
/**
- * GtkSourceCompletionContext:iter:
- *
- * The #GtkTextIter at which the completion is invoked.
- **/
- g_object_class_install_property (object_class,
- PROP_ITER,
- g_param_spec_boxed ("iter",
- "Iterator",
- "The GtkTextIter at which the completion was invoked",
- GTK_TYPE_TEXT_ITER,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS));
+ * GtkSourceCompletionContext:completion:
+ *
+ * The "completion" is the #GtkSourceCompletion that was used to create the context.
+ *
+ * Since: 5.0
+ */
+ properties [PROP_COMPLETION] =
+ g_param_spec_object ("completion",
+ "Completion",
+ "Completion",
+ GTK_SOURCE_TYPE_COMPLETION,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- /**
- * GtkSourceCompletionContext:activation:
- *
- * The completion activation
- **/
- g_object_class_install_property (object_class,
- PROP_ACTIVATION,
- g_param_spec_flags ("activation",
- "Activation",
- "The type of activation",
- GTK_SOURCE_TYPE_COMPLETION_ACTIVATION,
- GTK_SOURCE_COMPLETION_ACTIVATION_USER_REQUESTED,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT |
- G_PARAM_STATIC_STRINGS));
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+gtk_source_completion_context_init (GtkSourceCompletionContext *self)
+{
+ self->empty = TRUE;
+
+ self->providers = g_array_new (FALSE, FALSE, sizeof (ProviderInfo));
+ g_array_set_clear_func (self->providers, clear_provider_info);
+}
+
+static GType
+gtk_source_completion_context_get_item_type (GListModel *model)
+{
+ return GTK_SOURCE_TYPE_COMPLETION_PROPOSAL;
+}
+
+static guint
+gtk_source_completion_context_get_n_items (GListModel *model)
+{
+ GtkSourceCompletionContext *self = (GtkSourceCompletionContext *)model;
+ guint count = 0;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (self));
+
+ for (guint i = 0; i < self->providers->len; i++)
+ {
+ const ProviderInfo *info = &g_array_index (self->providers, ProviderInfo, i);
+
+ if (info->results != NULL)
+ {
+ count += g_list_model_get_n_items (info->results);
+ }
+ }
+
+ return count;
+}
+
+gboolean
+_gtk_source_completion_context_get_item_full (GtkSourceCompletionContext *self,
+ guint position,
+ GtkSourceCompletionProvider **provider,
+ GtkSourceCompletionProposal **proposal)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (self), FALSE);
+ g_return_val_if_fail (position < G_MAXUINT, FALSE);
+
+ if (provider != NULL)
+ *provider = NULL;
+
+ if (proposal != NULL)
+ *proposal = NULL;
+
+ for (guint i = 0; i < self->providers->len; i++)
+ {
+ const ProviderInfo *info = &g_array_index (self->providers, ProviderInfo, i);
+ guint n_items;
+
+ if (info->results == NULL)
+ continue;
+
+ n_items = g_list_model_get_n_items (info->results);
+
+ if (n_items == 0)
+ continue;
+
+ if (position >= n_items)
+ {
+ position -= n_items;
+ continue;
+ }
+
+ if (provider != NULL)
+ {
+ *provider = g_object_ref (info->provider);
+ }
+
+ if (proposal != NULL)
+ {
+ *proposal = g_list_model_get_item (info->results, position);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gpointer
+gtk_source_completion_context_get_item (GListModel *model,
+ guint position)
+{
+ GtkSourceCompletionContext *self = (GtkSourceCompletionContext *)model;
+ g_autoptr(GtkSourceCompletionProposal) proposal = NULL;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (self));
+
+ if (_gtk_source_completion_context_get_item_full (self, position, NULL, &proposal))
+ {
+ return g_steal_pointer (&proposal);
+ }
+
+ return NULL;
}
static void
-gtk_source_completion_context_init (GtkSourceCompletionContext *context)
+list_model_iface_init (GListModelInterface *iface)
{
- context->priv = gtk_source_completion_context_get_instance_private (context);
+ iface->get_item_type = gtk_source_completion_context_get_item_type;
+ iface->get_item = gtk_source_completion_context_get_item;
+ iface->get_n_items = gtk_source_completion_context_get_n_items;
}
/**
- * gtk_source_completion_context_add_proposals:
- * @context: a #GtkSourceCompletionContext.
- * @provider: a #GtkSourceCompletionProvider.
- * @proposals: (nullable) (element-type GtkSource.CompletionProposal): The list of proposals to add.
- * @finished: Whether the provider is finished adding proposals.
- *
- * Providers can use this function to add proposals to the completion. They
- * can do so asynchronously by means of the @finished argument. Providers must
- * ensure that they always call this function with @finished set to %TRUE
- * once each population (even if no proposals need to be added).
- * Population occurs when the gtk_source_completion_provider_populate()
- * function is called.
- **/
+ * gtk_source_completion_context_get_bounds:
+ * @self: an #GtkSourceCompletionContext
+ * @begin: (out) (optional): a #GtkTextIter
+ * @end: (out) (optional): a #GtkTextIter
+ *
+ * Gets the bounds for the completion, which is the beginning of the
+ * current word (taking break characters into account) to the current
+ * insertion cursor.
+ *
+ * If @begin is non-%NULL, it will be set to the start position of the
+ * current word being completed.
+ *
+ * If @end is non-%NULL, it will be set to the insertion cursor for the
+ * current word being completed.
+ *
+ * Returns: %TRUE if the marks are still valid and @begin or @end was set.
+ *
+ * Since: 5.0
+ */
+gboolean
+gtk_source_completion_context_get_bounds (GtkSourceCompletionContext *self,
+ GtkTextIter *begin,
+ GtkTextIter *end)
+{
+ GtkSourceBuffer *buffer;
+
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (self), FALSE);
+ g_return_val_if_fail (self->completion != NULL, FALSE);
+ g_return_val_if_fail (begin != NULL || end != NULL, FALSE);
+
+ buffer = gtk_source_completion_get_buffer (self->completion);
+
+ g_return_val_if_fail (buffer != NULL, FALSE);
+
+ if (begin != NULL)
+ memset (begin, 0, sizeof *begin);
+
+ if (end != NULL)
+ memset (end, 0, sizeof *end);
+
+ if (self->begin_mark == NULL)
+ {
+ /* Try to give some sort of valid iter */
+ gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (buffer), begin, end);
+ return FALSE;
+ }
+
+ g_assert (GTK_IS_TEXT_MARK (self->begin_mark));
+ g_assert (GTK_IS_TEXT_MARK (self->end_mark));
+ g_assert (GTK_IS_TEXT_BUFFER (buffer));
+
+ if (begin != NULL)
+ {
+ gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (buffer), begin, self->begin_mark);
+ }
+
+ if (end != NULL)
+ {
+ gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (buffer), end, self->end_mark);
+ }
+
+ return TRUE;
+}
+
+/**
+ * gtk_source_completion_context_get_completion:
+ * @self: an #GtkSourceCompletionContext
+ *
+ * Gets the #GtkSourceCompletion that created the context.
+ *
+ * Returns: (transfer none) (nullable): an #GtkSourceCompletion or %NULL
+ *
+ * Since: 5.0
+ */
+GtkSourceCompletion *
+gtk_source_completion_context_get_completion (GtkSourceCompletionContext *self)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (self), NULL);
+
+ return self->completion;
+}
+
+GtkSourceCompletionContext *
+_gtk_source_completion_context_new (GtkSourceCompletion *completion)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION (completion), NULL);
+
+ return g_object_new (GTK_SOURCE_TYPE_COMPLETION_CONTEXT,
+ "completion", completion,
+ NULL);
+}
+
void
-gtk_source_completion_context_add_proposals (GtkSourceCompletionContext *context,
- GtkSourceCompletionProvider *provider,
- GList *proposals,
- gboolean finished)
+_gtk_source_completion_context_add_provider (GtkSourceCompletionContext *self,
+ GtkSourceCompletionProvider *provider)
{
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (context));
+ ProviderInfo info = {0};
+
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (self));
g_return_if_fail (GTK_SOURCE_IS_COMPLETION_PROVIDER (provider));
+ g_return_if_fail (self->has_populated == FALSE);
- _gtk_source_completion_add_proposals (context->priv->completion,
- context,
- provider,
- proposals,
- finished);
+ info.provider = g_object_ref (provider);
+ info.results = NULL;
+
+ g_array_append_val (self->providers, info);
+ g_array_sort_with_data (self->providers, compare_provider_info, self);
+}
+
+void
+_gtk_source_completion_context_remove_provider (GtkSourceCompletionContext *self,
+ GtkSourceCompletionProvider *provider)
+{
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (self));
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_PROVIDER (provider));
+ g_return_if_fail (self->has_populated == FALSE);
+
+ for (guint i = 0; i < self->providers->len; i++)
+ {
+ const ProviderInfo *info = &g_array_index (self->providers, ProviderInfo, i);
+
+ if (info->provider == provider)
+ {
+ g_array_remove_index (self->providers, i);
+ return;
+ }
+ }
+
+ g_warning ("No such provider <%s %p> in context",
+ G_OBJECT_TYPE_NAME (provider), provider);
+}
+
+static void
+gtk_source_completion_context_items_changed_cb (GtkSourceCompletionContext *self,
+ guint position,
+ guint removed,
+ guint added,
+ GListModel *results)
+{
+ guint real_position = 0;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (self));
+ g_assert (G_IS_LIST_MODEL (results));
+
+ if (removed == 0 && added == 0)
+ return;
+
+ for (guint i = 0; i < self->providers->len; i++)
+ {
+ ProviderInfo *info = &g_array_index (self->providers, ProviderInfo, i);
+
+ if (info->results == results)
+ {
+ g_list_model_items_changed (G_LIST_MODEL (self),
+ real_position + position,
+ removed,
+ added);
+ break;
+ }
+
+ if (info->results != NULL)
+ real_position += g_list_model_get_n_items (info->results);
+ }
+
+ gtk_source_completion_context_update_empty (self);
}
/**
- * gtk_source_completion_context_get_iter:
- * @context: a #GtkSourceCompletionContext.
- * @iter: (out): a #GtkTextIter.
+ * gtk_source_completion_context_set_proposals_for_provider:
+ * @self: an #GtkSourceCompletionContext
+ * @provider: an #GtkSourceCompletionProvider
+ * @results: (nullable): a #GListModel or %NULL
*
- * Get the iter at which the completion was invoked. Providers can use this
- * to determine how and if to match proposals.
+ * This function allows providers to update their results for a context
+ * outside of a call to gtk_source_completion_provider_populate_async(). This
+ * can be used to immediately return results for a provider while it does
+ * additional asynchronous work. Doing so will allow the completions to
+ * update while the operation is in progress.
*
- * Returns: %TRUE if @iter is correctly set, %FALSE otherwise.
- **/
-gboolean
-gtk_source_completion_context_get_iter (GtkSourceCompletionContext *context,
- GtkTextIter *iter)
+ * Since: 5.0
+ */
+void
+gtk_source_completion_context_set_proposals_for_provider (GtkSourceCompletionContext *self,
+ GtkSourceCompletionProvider *provider,
+ GListModel *results)
{
- GtkTextBuffer *mark_buffer;
- GtkSourceView *view;
- GtkTextBuffer *completion_buffer;
+ guint position = 0;
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (context), FALSE);
+ g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (self));
+ g_assert (GTK_SOURCE_IS_COMPLETION_PROVIDER (provider));
+ g_assert (!results || G_IS_LIST_MODEL (results));
- if (context->priv->mark == NULL)
+ for (guint i = 0; i < self->providers->len; i++)
{
- /* This should never happen: context should be always be created
- providing a position iter */
- g_warning ("Completion context without mark");
- return FALSE;
+ ProviderInfo *info = &g_array_index (self->providers, ProviderInfo, i);
+
+ if (info->provider == provider)
+ {
+ guint n_removed = 0;
+ guint n_added = 0;
+
+ if (info->results == results)
+ return;
+
+ if (info->results != NULL)
+ n_removed = g_list_model_get_n_items (info->results);
+
+ if (results != NULL)
+ n_added = g_list_model_get_n_items (results);
+
+ if (info->items_changed_handler != 0)
+ {
+ g_signal_handler_disconnect (info->results, info->items_changed_handler);
+ info->items_changed_handler = 0;
+ }
+
+ g_set_object (&info->results, results);
+
+ if (info->results != NULL)
+ info->items_changed_handler =
+ g_signal_connect_object (info->results,
+ "items-changed",
+ G_CALLBACK (gtk_source_completion_context_items_changed_cb),
+ self,
+ G_CONNECT_SWAPPED);
+
+ g_list_model_items_changed (G_LIST_MODEL (self), position, n_removed, n_added);
+
+ break;
+ }
+
+ if (info->results != NULL)
+ position += g_list_model_get_n_items (info->results);
}
- mark_buffer = gtk_text_mark_get_buffer (context->priv->mark);
+ gtk_source_completion_context_update_empty (self);
+}
+
+static void
+gtk_source_completion_context_populate_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GtkSourceCompletionProvider *provider = (GtkSourceCompletionProvider *)object;
+ GtkSourceCompletionContext *self;
+ CompleteTaskData *task_data;
+ g_autoptr(GListModel) results = NULL;
+ g_autoptr(GTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_PROVIDER (provider));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (G_IS_TASK (task));
+
+ self = g_task_get_source_object (task);
+ g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (self));
- if (mark_buffer == NULL)
+ task_data = g_task_get_task_data (task);
+ g_assert (task_data != NULL);
+
+ if (!(results = gtk_source_completion_provider_populate_finish (provider, result, &error)))
+ gtk_source_completion_context_mark_failed (self, provider, error);
+ else
+ gtk_source_completion_context_set_proposals_for_provider (self, provider, results);
+
+ task_data->n_active--;
+
+ gtk_source_completion_context_update_empty (self);
+
+ if (task_data->n_active == 0)
+ g_task_return_boolean (task, TRUE);
+}
+
+static void
+gtk_source_completion_context_notify_complete_cb (GtkSourceCompletionContext *self,
+ GParamSpec *pspec,
+ GTask *task)
+{
+ g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (self));
+ g_assert (G_IS_TASK (task));
+
+ self->busy = FALSE;
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_BUSY]);
+}
+
+/**
+ * _gtk_source_completion_context_complete_async:
+ * @self: a #GtkSourceCompletionContext
+ * @activation: how we are being activated
+ * @iter: a #GtkTextIter
+ * @cancellable: (nullable): a #GCancellable or %NULL
+ * @callback: (nullable): a callback or %NULL
+ * @user_data: closure data for @callback
+ *
+ * Asynchronously requests that the completion context load proposals
+ * from the registered providers.
+ *
+ * Since: 5.0
+ */
+void
+_gtk_source_completion_context_complete_async (GtkSourceCompletionContext *self,
+ GtkSourceCompletionActivation activation,
+ const GtkTextIter *begin,
+ const GtkTextIter *end,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+ CompleteTaskData *task_data;
+ GtkSourceBuffer *buffer;
+ guint n_items;
+
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (self));
+ g_return_if_fail (self->has_populated == FALSE);
+ g_return_if_fail (self->begin_mark == NULL);
+ g_return_if_fail (self->end_mark == NULL);
+ g_return_if_fail (begin != NULL);
+ g_return_if_fail (end != NULL);
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ self->activation = activation;
+ self->has_populated = TRUE;
+ self->busy = TRUE;
+
+ buffer = gtk_source_completion_context_get_buffer (self);
+
+ self->begin_mark = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (buffer), NULL, begin, TRUE);
+ g_object_ref (self->begin_mark);
+
+ self->end_mark = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (buffer), NULL, end, FALSE);
+ g_object_ref (self->end_mark);
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_source_tag (task, _gtk_source_completion_context_complete_async);
+ g_task_set_priority (task, G_PRIORITY_LOW);
+
+ task_data = g_slice_new0 (CompleteTaskData);
+ task_data->n_active = self->providers->len;
+ g_task_set_task_data (task, task_data, complete_task_data_free);
+
+ /* Always notify of busy completion, whether we fail or not */
+ g_signal_connect_object (task,
+ "notify::completed",
+ G_CALLBACK (gtk_source_completion_context_notify_complete_cb),
+ self,
+ G_CONNECT_SWAPPED);
+
+ for (guint i = 0; i < self->providers->len; i++)
{
- return FALSE;
+ const ProviderInfo *info = &g_array_index (self->providers, ProviderInfo, i);
+
+ gtk_source_completion_provider_populate_async (info->provider,
+ self,
+ cancellable,
+ gtk_source_completion_context_populate_cb,
+ g_object_ref (task));
}
- view = gtk_source_completion_get_view (context->priv->completion);
- if (view == NULL)
+ /* Providers may adjust their position based on our new marks */
+ n_items = g_list_model_get_n_items (G_LIST_MODEL (self));
+ g_array_sort_with_data (self->providers, compare_provider_info, self);
+ g_list_model_items_changed (G_LIST_MODEL (self), 0, n_items, n_items);
+
+ if (task_data->n_active == 0)
{
- return FALSE;
+ g_task_return_boolean (task, TRUE);
}
- completion_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_BUSY]);
+}
- if (completion_buffer != mark_buffer)
+/**
+ * _gtk_source_completion_context_complete_finish:
+ * @self: an #GtkSourceCompletionContext
+ * @result: a #GAsyncResult provided to callback
+ * @error: a location for a #GError, or %NULL
+ *
+ * Completes an asynchronous request to populate proposals.
+ *
+ * Returns: %TRUE if successful; otherwise %FALSE and @error is set
+ *
+ * Since: 5.0
+ */
+gboolean
+_gtk_source_completion_context_complete_finish (GtkSourceCompletionContext *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (self), FALSE);
+ g_return_val_if_fail (G_IS_TASK (result), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+/**
+ * gtk_source_completion_context_get_busy:
+ *
+ * Gets the "busy" property. This is set to %TRUE while the completion
+ * context is actively fetching proposals from registered
+ * #GtkSourceCompletionProvider's.
+ *
+ * Returns: %TRUE if the context is busy
+ *
+ * Since: 5.0
+ */
+gboolean
+gtk_source_completion_context_get_busy (GtkSourceCompletionContext *self)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (self), FALSE);
+
+ return self->busy;
+}
+
+/**
+ * gtk_source_completion_context_get_buffer:
+ * @self: an #GtkSourceCompletionContext
+ *
+ * Gets the underlying buffer used by the context.
+ *
+ * This is a convenience function to get the buffer via the #GtkSourceCompletion
+ * property.
+ *
+ * Returns: (transfer none) (nullable): a #GtkTextBuffer or %NULL
+ *
+ * Since: 5.0
+ */
+GtkSourceBuffer *
+gtk_source_completion_context_get_buffer (GtkSourceCompletionContext *self)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (self), NULL);
+
+ if (self->completion != NULL)
+ return gtk_source_completion_get_buffer (self->completion);
+
+ return NULL;
+}
+
+/**
+ * gtk_source_completion_context_get_view:
+ * @self: a #GtkSourceCompletionContext
+ *
+ * Gets the text view for the context.
+ *
+ * Returns: (nullable) (transfer none): a #GtkSourceView or %NULL
+ *
+ * Since: 5.0
+ */
+GtkSourceView *
+gtk_source_completion_context_get_view (GtkSourceCompletionContext *self)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (self), NULL);
+
+ if (self->completion != NULL)
+ return gtk_source_completion_get_view (self->completion);
+
+ return NULL;
+}
+
+void
+_gtk_source_completion_context_refilter (GtkSourceCompletionContext *self)
+{
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (self));
+
+ for (guint i = 0; i < self->providers->len; i++)
{
+ const ProviderInfo *info = &g_array_index (self->providers, ProviderInfo, i);
+
+ if (info->error != NULL)
+ continue;
+
+ if (info->results == NULL)
+ continue;
+
+ gtk_source_completion_provider_refilter (info->provider, self, info->results);
+ }
+}
+
+gboolean
+_gtk_source_completion_context_iter_invalidates (GtkSourceCompletionContext *self,
+ const GtkTextIter *iter)
+{
+ GtkTextIter begin, end;
+ GtkTextBuffer *buffer;
+
+ g_assert (!self || GTK_SOURCE_IS_COMPLETION_CONTEXT (self));
+ g_assert (iter != NULL);
+
+ if (self == NULL)
return FALSE;
+
+ buffer = gtk_text_iter_get_buffer (iter);
+
+ gtk_text_buffer_get_iter_at_mark (buffer, &begin, self->begin_mark);
+ gtk_text_buffer_get_iter_at_mark (buffer, &end, self->end_mark);
+
+ return gtk_text_iter_compare (&begin, iter) <= 0 &&
+ gtk_text_iter_compare (&end, iter) >= 0;
+}
+
+/**
+ * gtk_source_completion_context_get_empty:
+ * @self: a #GtkSourceCompletionContext
+ *
+ * Checks if any proposals have been provided to the context.
+ *
+ * Out of convenience, this function will return %TRUE if @self is %NULL.
+ *
+ * Returns: %TRUE if there are no proposals in the context
+ *
+ * Since: 5.0
+ */
+gboolean
+gtk_source_completion_context_get_empty (GtkSourceCompletionContext *self)
+{
+ g_return_val_if_fail (!self || GTK_SOURCE_IS_COMPLETION_CONTEXT (self), FALSE);
+
+ return self ? self->empty : TRUE;
+}
+
+/**
+ * gtk_source_completion_context_get_word:
+ * @self: a #GtkSourceCompletionContext
+ *
+ * Gets the word that is being completed up to the position of the insert mark.
+ *
+ * Returns: (transfer full): a string containing the current word
+ *
+ * Since: 5.0
+ */
+gchar *
+gtk_source_completion_context_get_word (GtkSourceCompletionContext *self)
+{
+ GtkTextIter begin, end;
+
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (self), NULL);
+
+ gtk_source_completion_context_get_bounds (self, &begin, &end);
+
+ return gtk_text_iter_get_slice (&begin, &end);
+}
+
+gboolean
+_gtk_source_completion_context_can_refilter (GtkSourceCompletionContext *self,
+ const GtkTextIter *begin,
+ const GtkTextIter *end)
+{
+ GtkTextIter old_begin;
+ GtkTextIter old_end;
+
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (self), FALSE);
+ g_return_val_if_fail (begin != NULL, FALSE);
+ g_return_val_if_fail (end != NULL, FALSE);
+
+ gtk_source_completion_context_get_bounds (self, &old_begin, &old_end);
+
+ if (gtk_text_iter_equal (&old_begin, begin))
+ {
+ /*
+ * TODO: We can probably get smarter about this by asking all of
+ * the providers if they can refilter the new word (and only reload
+ * the data for those that cannot.
+ *
+ * Also, we might want to deal with that by copying the context
+ * into a new context and query using that.
+ */
+ if (gtk_text_iter_compare (&old_end, end) <= 0)
+ {
+ GtkTextBuffer *buffer = gtk_text_iter_get_buffer (begin);
+
+ gtk_text_buffer_move_mark (buffer, self->begin_mark, begin);
+ gtk_text_buffer_move_mark (buffer, self->end_mark, end);
+
+ return TRUE;
+ }
}
- gtk_text_buffer_get_iter_at_mark (mark_buffer, iter, context->priv->mark);
- return TRUE;
+ return FALSE;
}
/**
* gtk_source_completion_context_get_activation:
- * @context: a #GtkSourceCompletionContext.
+ * @self: a #GtkSourceCompletionContext
*
- * Get the context activation.
+ * Gets the mode for which the context was activated.
*
- * Returns: The context activation.
+ * Since: 5.0
*/
GtkSourceCompletionActivation
-gtk_source_completion_context_get_activation (GtkSourceCompletionContext *context)
+gtk_source_completion_context_get_activation (GtkSourceCompletionContext *self)
{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (context),
- GTK_SOURCE_COMPLETION_ACTIVATION_NONE);
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (self), 0);
- return context->priv->activation;
+ return self->activation;
}
-void
-_gtk_source_completion_context_cancel (GtkSourceCompletionContext *context)
+/**
+ * gtk_source_completion_context_get_language:
+ * @self: a #GtkSourceCompletionContext
+ *
+ * Gets the language of the underlying buffer, if any.
+ *
+ * Returns: (nullable) (transfer none): a #GtkSourceLanguage or %NULL
+ *
+ * Since: 5.0
+ */
+GtkSourceLanguage *
+gtk_source_completion_context_get_language (GtkSourceCompletionContext *self)
{
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (context));
+ GtkSourceBuffer *buffer;
- g_signal_emit (context, context_signals[CANCELLED], 0);
-}
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (self), NULL);
-GtkSourceCompletionContext *
-_gtk_source_completion_context_new (GtkSourceCompletion *completion,
- GtkTextIter *position)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION (completion), NULL);
- g_return_val_if_fail (position != NULL, NULL);
+ buffer = gtk_source_completion_context_get_buffer (self);
- return g_object_new (GTK_SOURCE_TYPE_COMPLETION_CONTEXT,
- "completion", completion,
- "iter", position,
- NULL);
+ if (buffer != NULL)
+ {
+ return gtk_source_buffer_get_language (buffer);
+ }
+
+ return NULL;
}
diff --git a/gtksourceview/gtksourcecompletioncontext.h b/gtksourceview/gtksourcecompletioncontext.h
index c4d146b7482987a37904b0753f1ec084abcd604b..17025749df1f1a590b3fb63699f3cc4f35a06380 100644
--- a/gtksourceview/gtksourcecompletioncontext.h
+++ b/gtksourceview/gtksourcecompletioncontext.h
@@ -1,8 +1,7 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
- *
+/*
* This file is part of GtkSourceView
*
- * Copyright (C) 2009 - Jesse van den Kieboom
+ * Copyright 2020 Christian Hergert
*
* GtkSourceView is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -16,87 +15,56 @@
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, see .
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
*/
-#ifndef GTK_SOURCE_COMPLETION_CONTEXT_H
-#define GTK_SOURCE_COMPLETION_CONTEXT_H
-
-#if !defined (GTK_SOURCE_H_INSIDE) && !defined (GTK_SOURCE_COMPILATION)
-#error "Only can be included directly."
-#endif
+#pragma once
#include
-#include
-G_BEGIN_DECLS
+#include "gtksourcetypes.h"
-#define GTK_SOURCE_TYPE_COMPLETION_CONTEXT (gtk_source_completion_context_get_type ())
-#define GTK_SOURCE_COMPLETION_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_SOURCE_TYPE_COMPLETION_CONTEXT, GtkSourceCompletionContext))
-#define GTK_SOURCE_COMPLETION_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_SOURCE_TYPE_COMPLETION_CONTEXT, GtkSourceCompletionContextClass))
-#define GTK_SOURCE_IS_COMPLETION_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_SOURCE_TYPE_COMPLETION_CONTEXT))
-#define GTK_SOURCE_IS_COMPLETION_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_SOURCE_TYPE_COMPLETION_CONTEXT))
-#define GTK_SOURCE_COMPLETION_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_SOURCE_TYPE_COMPLETION_CONTEXT, GtkSourceCompletionContextClass))
+G_BEGIN_DECLS
-typedef struct _GtkSourceCompletionContextClass GtkSourceCompletionContextClass;
-typedef struct _GtkSourceCompletionContextPrivate GtkSourceCompletionContextPrivate;
+#define GTK_SOURCE_TYPE_COMPLETION_CONTEXT (gtk_source_completion_context_get_type())
-/**
- * GtkSourceCompletionActivation:
- * @GTK_SOURCE_COMPLETION_ACTIVATION_NONE: None.
- * @GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE: Interactive activation. By
- * default, it occurs on each insertion in the #GtkTextBuffer. This can be
- * blocked temporarily with gtk_source_completion_block_interactive().
- * @GTK_SOURCE_COMPLETION_ACTIVATION_USER_REQUESTED: User requested activation.
- * By default, it occurs when the user presses
- * Controlspace.
- */
typedef enum _GtkSourceCompletionActivation
{
GTK_SOURCE_COMPLETION_ACTIVATION_NONE = 0,
- GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE = 1 << 0,
- GTK_SOURCE_COMPLETION_ACTIVATION_USER_REQUESTED = 1 << 1
+ GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE = 1,
+ GTK_SOURCE_COMPLETION_ACTIVATION_USER_REQUESTED = 2,
} GtkSourceCompletionActivation;
-struct _GtkSourceCompletionContext {
- GInitiallyUnowned parent;
-
- GtkSourceCompletionContextPrivate *priv;
-};
-
-struct _GtkSourceCompletionContextClass {
- GInitiallyUnownedClass parent_class;
-
- void (*cancelled) (GtkSourceCompletionContext *context);
-
- /* Padding for future expansion */
- gpointer padding[10];
-};
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-GType gtk_source_completion_context_get_type (void) G_GNUC_CONST;
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_completion_context_add_proposals (GtkSourceCompletionContext *context,
- GtkSourceCompletionProvider *provider,
- GList *proposals,
- gboolean finished);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-gboolean gtk_source_completion_context_get_iter (GtkSourceCompletionContext *context,
- GtkTextIter *iter);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-GtkSourceCompletionActivation
- gtk_source_completion_context_get_activation (GtkSourceCompletionContext *context);
-
-G_GNUC_INTERNAL
-GtkSourceCompletionContext *
- _gtk_source_completion_context_new (GtkSourceCompletion *completion,
- GtkTextIter *position);
-
-G_GNUC_INTERNAL
-void _gtk_source_completion_context_cancel (GtkSourceCompletionContext *context);
+GTK_SOURCE_AVAILABLE_IN_5_0
+G_DECLARE_FINAL_TYPE (GtkSourceCompletionContext, gtk_source_completion_context, GTK_SOURCE, COMPLETION_CONTEXT, GObject)
+
+GTK_SOURCE_AVAILABLE_IN_5_0
+GtkSourceCompletion *gtk_source_completion_context_get_completion (GtkSourceCompletionContext *self);
+GTK_SOURCE_AVAILABLE_IN_5_0
+GtkSourceCompletionActivation gtk_source_completion_context_get_activation (GtkSourceCompletionContext *self);
+GTK_SOURCE_AVAILABLE_IN_5_0
+gboolean gtk_source_completion_context_get_bounds (GtkSourceCompletionContext *self,
+ GtkTextIter *begin,
+ GtkTextIter *end);
+GTK_SOURCE_AVAILABLE_IN_5_0
+void gtk_source_completion_context_get_start_iter (GtkSourceCompletionContext *self,
+ GtkTextIter *iter);
+GTK_SOURCE_AVAILABLE_IN_5_0
+gboolean gtk_source_completion_context_get_empty (GtkSourceCompletionContext *self);
+GTK_SOURCE_AVAILABLE_IN_5_0
+char *gtk_source_completion_context_get_word (GtkSourceCompletionContext *self);
+GTK_SOURCE_AVAILABLE_IN_5_0
+gboolean gtk_source_completion_context_get_busy (GtkSourceCompletionContext *self);
+GTK_SOURCE_AVAILABLE_IN_5_0
+GtkSourceView *gtk_source_completion_context_get_view (GtkSourceCompletionContext *self);
+GTK_SOURCE_AVAILABLE_IN_5_0
+GtkSourceBuffer *gtk_source_completion_context_get_buffer (GtkSourceCompletionContext *self);
+GTK_SOURCE_AVAILABLE_IN_5_0
+GtkSourceLanguage *gtk_source_completion_context_get_language (GtkSourceCompletionContext *self);
+GTK_SOURCE_AVAILABLE_IN_5_0
+void gtk_source_completion_context_set_proposals_for_provider (GtkSourceCompletionContext *self,
+ GtkSourceCompletionProvider *provider,
+ GListModel *results);
G_END_DECLS
-
-#endif /* GTK_SOURCE_COMPLETION_CONTEXT_H */
diff --git a/gtksourceview/gtksourcecompletioninfo-private.h b/gtksourceview/gtksourcecompletioninfo-private.h
new file mode 100644
index 0000000000000000000000000000000000000000..2f82edbe17e7f6f9cc888137b3e803c8476c8cc7
--- /dev/null
+++ b/gtksourceview/gtksourcecompletioninfo-private.h
@@ -0,0 +1,37 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2020 Christian Hergert
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#pragma once
+
+#include
+
+#include "gtksourcetypes-private.h"
+
+G_BEGIN_DECLS
+
+#define GTK_SOURCE_TYPE_COMPLETION_INFO (_gtk_source_completion_info_get_type())
+
+G_DECLARE_FINAL_TYPE (GtkSourceCompletionInfo, _gtk_source_completion_info, GTK_SOURCE, COMPLETION_INFO, GtkSourceAssistant)
+
+GtkSourceCompletionInfo *_gtk_source_completion_info_new (void);
+GtkSourceCompletionCell *_gtk_source_completion_info_get_cell (GtkSourceCompletionInfo *self);
+
+G_END_DECLS
diff --git a/gtksourceview/gtksourcecompletioninfo.c b/gtksourceview/gtksourcecompletioninfo.c
index 714c132754c675feb6743fa2ed37ba72bf1d08e4..405ac3fa61bd945222bd3efc55f03a815e46be78 100644
--- a/gtksourceview/gtksourcecompletioninfo.c
+++ b/gtksourceview/gtksourcecompletioninfo.c
@@ -1,10 +1,7 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- */
/*
* This file is part of GtkSourceView
*
- * Copyright (C) 2007 -2009 Jesús Barbero Rodríguez
- * Copyright (C) 2009 - Jesse van den Kieboom
- * Copyright (C) 2012 - Sébastien Wilmet
+ * Copyright 2020 Christian Hergert
*
* GtkSourceView is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -18,448 +15,74 @@
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, see .
- */
-
-/**
- * SECTION:completioninfo
- * @title: GtkSourceCompletionInfo
- * @short_description: Calltips object
- *
- * This object can be used to show a calltip or help for the
- * current completion proposal.
- *
- * The info window has always the same size as the natural size of its child
- * widget, added with gtk_container_add(). If you want a fixed size instead, a
- * possibility is to use a scrolled window, as the following example
- * demonstrates.
*
- *
- * Fixed size with a scrolled window.
- *
- * GtkSourceCompletionInfo *info;
- * GtkWidget *your_widget;
- * GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);
- *
- * gtk_widget_set_size_request (scrolled_window, 300, 200);
- * gtk_container_add (GTK_CONTAINER (scrolled_window), your_widget);
- * gtk_container_add (GTK_CONTAINER (info), scrolled_window);
- *
- *
- *
- * If the calltip is displayed on top of a certain widget, say a #GtkTextView,
- * you should attach the calltip window to the #GtkTextView with
- * gtk_window_set_attached_to(). By doing this, the calltip will be hidden when
- * the #GtkWidget::focus-out-event signal is emitted by the #GtkTextView. You
- * may also be interested by the #GtkTextBuffer:cursor-position property (when
- * its value is modified). If you use the #GtkSourceCompletionInfo through the
- * #GtkSourceCompletion machinery, you don't need to worry about this.
+ * SPDX-License-Identifier: LGPL-2.1-or-later
*/
-#ifdef HAVE_CONFIG_H
-#include
-#endif
+#include "config.h"
-#include "gtksourcecompletioninfo.h"
-#include
+#include "gtksourceassistant-private.h"
+#include "gtksourcecompletioncell-private.h"
+#include "gtksourcecompletioninfo-private.h"
-struct _GtkSourceCompletionInfoPrivate
+struct _GtkSourceCompletionInfo
{
- guint idle_resize;
-
- GtkWidget *attached_to;
- gulong focus_out_event_handler;
-
- gint xoffset;
-
- guint transient_set : 1;
+ GtkSourceAssistant parent_instance;
+ GtkSourceCompletionCell *cell;
};
-G_DEFINE_TYPE_WITH_PRIVATE (GtkSourceCompletionInfo, gtk_source_completion_info, GTK_TYPE_WINDOW);
-
-/* Resize the window */
-
-static gboolean
-idle_resize (GtkSourceCompletionInfo *info)
-{
- GtkWidget *child = gtk_bin_get_child (GTK_BIN (info));
- GtkRequisition nat_size;
- guint border_width;
- gint window_width;
- gint window_height;
- gint cur_window_width;
- gint cur_window_height;
-
- info->priv->idle_resize = 0;
-
- if (child == NULL)
- {
- return G_SOURCE_REMOVE;
- }
-
- gtk_widget_get_preferred_size (child, NULL, &nat_size);
-
- border_width = gtk_container_get_border_width (GTK_CONTAINER (info));
-
- window_width = nat_size.width + 2 * border_width;
- window_height = nat_size.height + 2 * border_width;
-
- gtk_window_get_size (GTK_WINDOW (info), &cur_window_width, &cur_window_height);
-
- /* Avoid an infinite loop */
- if (cur_window_width != window_width || cur_window_height != window_height)
- {
- gtk_window_resize (GTK_WINDOW (info),
- MAX (1, window_width),
- MAX (1, window_height));
- }
-
- return G_SOURCE_REMOVE;
-}
-
-static void
-queue_resize (GtkSourceCompletionInfo *info)
-{
- if (info->priv->idle_resize == 0)
- {
- info->priv->idle_resize = g_idle_add ((GSourceFunc)idle_resize, info);
- }
-}
-
-static void
-gtk_source_completion_info_check_resize (GtkContainer *container)
-{
- GtkSourceCompletionInfo *info = GTK_SOURCE_COMPLETION_INFO (container);
- queue_resize (info);
-
- GTK_CONTAINER_CLASS (gtk_source_completion_info_parent_class)->check_resize (container);
-}
-
-/* Geometry management */
-
-static GtkSizeRequestMode
-gtk_source_completion_info_get_request_mode (GtkWidget *widget)
-{
- return GTK_SIZE_REQUEST_CONSTANT_SIZE;
-}
-
-static void
-gtk_source_completion_info_get_preferred_width (GtkWidget *widget,
- gint *min_width,
- gint *nat_width)
-{
- GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget));
- gint width = 0;
-
- if (child != NULL)
- {
- GtkRequisition nat_size;
- gtk_widget_get_preferred_size (child, NULL, &nat_size);
- width = nat_size.width;
- }
-
- if (min_width != NULL)
- {
- *min_width = width;
- }
-
- if (nat_width != NULL)
- {
- *nat_width = width;
- }
-}
-
-static void
-gtk_source_completion_info_get_preferred_height (GtkWidget *widget,
- gint *min_height,
- gint *nat_height)
-{
- GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget));
- gint height = 0;
-
- if (child != NULL)
- {
- GtkRequisition nat_size;
- gtk_widget_get_preferred_size (child, NULL, &nat_size);
- height = nat_size.height;
- }
-
- if (min_height != NULL)
- {
- *min_height = height;
- }
-
- if (nat_height != NULL)
- {
- *nat_height = height;
- }
-}
-
-/* Init, dispose, finalize, ... */
-
-static gboolean
-focus_out_event_cb (GtkSourceCompletionInfo *info)
-{
- gtk_widget_hide (GTK_WIDGET (info));
- return FALSE;
-}
-
-static void
-set_attached_to (GtkSourceCompletionInfo *info,
- GtkWidget *attached_to)
-{
- if (info->priv->attached_to != NULL)
- {
- g_object_remove_weak_pointer (G_OBJECT (info->priv->attached_to),
- (gpointer *) &info->priv->attached_to);
-
- if (info->priv->focus_out_event_handler != 0)
- {
- g_signal_handler_disconnect (info->priv->attached_to,
- info->priv->focus_out_event_handler);
-
- info->priv->focus_out_event_handler = 0;
- }
- }
-
- info->priv->attached_to = attached_to;
-
- if (attached_to == NULL)
- {
- return;
- }
-
- g_object_add_weak_pointer (G_OBJECT (attached_to),
- (gpointer *) &info->priv->attached_to);
-
- info->priv->focus_out_event_handler =
- g_signal_connect_swapped (attached_to,
- "focus-out-event",
- G_CALLBACK (focus_out_event_cb),
- info);
-
- info->priv->transient_set = FALSE;
-}
-
-static void
-update_attached_to (GtkSourceCompletionInfo *info)
-{
- set_attached_to (info, gtk_window_get_attached_to (GTK_WINDOW (info)));
-}
-
-static void
-gtk_source_completion_info_init (GtkSourceCompletionInfo *info)
-{
- info->priv = gtk_source_completion_info_get_instance_private (info);
-
- g_signal_connect (info,
- "notify::attached-to",
- G_CALLBACK (update_attached_to),
- NULL);
-
- update_attached_to (info);
-
- /* Tooltip style */
- gtk_window_set_title (GTK_WINDOW (info), _("Completion Info"));
- gtk_widget_set_name (GTK_WIDGET (info), "gtk-tooltip");
-
- gtk_window_set_type_hint (GTK_WINDOW (info),
- GDK_WINDOW_TYPE_HINT_COMBO);
-
- gtk_container_set_border_width (GTK_CONTAINER (info), 1);
-}
+G_DEFINE_TYPE (GtkSourceCompletionInfo, _gtk_source_completion_info, GTK_SOURCE_TYPE_ASSISTANT)
static void
-gtk_source_completion_info_dispose (GObject *object)
+_gtk_source_completion_info_get_offset (GtkSourceAssistant *assistant,
+ int *x_offset,
+ int *y_offset)
{
- GtkSourceCompletionInfo *info = GTK_SOURCE_COMPLETION_INFO (object);
+ GtkStyleContext *style_context;
+ GtkBorder margin;
- if (info->priv->idle_resize != 0)
- {
- g_source_remove (info->priv->idle_resize);
- info->priv->idle_resize = 0;
- }
+ g_assert (GTK_SOURCE_IS_COMPLETION_INFO (assistant));
- set_attached_to (info, NULL);
+ style_context = gtk_widget_get_style_context (GTK_WIDGET (assistant));
+ gtk_style_context_get_margin (style_context, &margin);
- G_OBJECT_CLASS (gtk_source_completion_info_parent_class)->dispose (object);
+ *x_offset = -margin.left + 1;
+ *y_offset = -margin.top;
}
static void
-gtk_source_completion_info_show (GtkWidget *widget)
+_gtk_source_completion_info_class_init (GtkSourceCompletionInfoClass *klass)
{
- GtkSourceCompletionInfo *info = GTK_SOURCE_COMPLETION_INFO (widget);
-
- if (info->priv->attached_to != NULL && !info->priv->transient_set)
- {
- GtkWidget *toplevel;
-
- toplevel = gtk_widget_get_toplevel (GTK_WIDGET (info->priv->attached_to));
- if (gtk_widget_is_toplevel (toplevel))
- {
- gtk_window_set_transient_for (GTK_WINDOW (info),
- GTK_WINDOW (toplevel));
- info->priv->transient_set = TRUE;
- }
- }
+ GtkSourceAssistantClass *assistant_class = GTK_SOURCE_ASSISTANT_CLASS (klass);
- GTK_WIDGET_CLASS (gtk_source_completion_info_parent_class)->show (widget);
-}
-
-static gboolean
-gtk_source_completion_info_draw (GtkWidget *widget,
- cairo_t *cr)
-{
- GTK_WIDGET_CLASS (gtk_source_completion_info_parent_class)->draw (widget, cr);
-
- gtk_render_frame (gtk_widget_get_style_context (widget),
- cr,
- 0, 0,
- gtk_widget_get_allocated_width (widget),
- gtk_widget_get_allocated_height (widget));
-
- return FALSE;
+ assistant_class->get_offset = _gtk_source_completion_info_get_offset;
}
static void
-gtk_source_completion_info_class_init (GtkSourceCompletionInfoClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
- GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
-
- object_class->dispose = gtk_source_completion_info_dispose;
-
- widget_class->show = gtk_source_completion_info_show;
- widget_class->draw = gtk_source_completion_info_draw;
- widget_class->get_request_mode = gtk_source_completion_info_get_request_mode;
- widget_class->get_preferred_width = gtk_source_completion_info_get_preferred_width;
- widget_class->get_preferred_height = gtk_source_completion_info_get_preferred_height;
-
- container_class->check_resize = gtk_source_completion_info_check_resize;
-}
-
-void
-_gtk_source_completion_info_set_xoffset (GtkSourceCompletionInfo *window,
- gint xoffset)
+_gtk_source_completion_info_init (GtkSourceCompletionInfo *self)
{
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION_INFO (window));
+ gtk_widget_add_css_class (GTK_WIDGET (self), "completion-info");
+ gtk_popover_set_position (GTK_POPOVER (self), GTK_POS_RIGHT);
+ gtk_popover_set_autohide (GTK_POPOVER (self), FALSE);
- window->priv->xoffset = xoffset;
+ self->cell = g_object_new (GTK_SOURCE_TYPE_COMPLETION_CELL,
+ "column", GTK_SOURCE_COMPLETION_COLUMN_DETAILS,
+ "halign", GTK_ALIGN_START,
+ "valign", GTK_ALIGN_START,
+ NULL);
+ _gtk_source_assistant_set_child (GTK_SOURCE_ASSISTANT (self), GTK_WIDGET (self->cell));
}
-/* Move to iter */
-
-static void
-get_iter_pos (GtkTextView *text_view,
- GtkTextIter *iter,
- gint *x,
- gint *y,
- gint *height)
-{
- GdkRectangle location;
-
- gtk_text_view_get_iter_location (text_view, iter, &location);
-
- gtk_text_view_buffer_to_window_coords (text_view,
- GTK_TEXT_WINDOW_WIDGET,
- location.x,
- location.y,
- x,
- y);
-
- *height = location.height;
-}
-
-static void
-move_to_iter (GtkSourceCompletionInfo *window,
- GtkTextView *view,
- GtkTextIter *iter)
-{
- GdkRectangle position;
- GdkWindow *gdk_window;
- gint x, y;
- gint line_height;
-
- gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
-
- if (gdk_window == NULL)
- {
- return;
- }
-
- get_iter_pos (view, iter, &x, &y, &line_height);
-
- gtk_widget_translate_coordinates (GTK_WIDGET (view),
- gtk_widget_get_toplevel (GTK_WIDGET (view)),
- x, y, &x, &y);
-
- position.x = x;
- position.y = y;
- position.height = line_height;
- position.width = 0;
-
- gdk_window_move_to_rect (gdk_window,
- &position,
- GDK_GRAVITY_SOUTH_WEST,
- GDK_GRAVITY_NORTH_WEST,
- GDK_ANCHOR_SLIDE | GDK_ANCHOR_FLIP_Y | GDK_ANCHOR_RESIZE,
- window->priv->xoffset, 0);
-}
-
-static void
-move_to_cursor (GtkSourceCompletionInfo *window,
- GtkTextView *view)
-{
- GtkTextBuffer *buffer;
- GtkTextIter insert;
-
- buffer = gtk_text_view_get_buffer (view);
- gtk_text_buffer_get_iter_at_mark (buffer, &insert, gtk_text_buffer_get_insert (buffer));
-
- move_to_iter (window, view, &insert);
-}
-
-/* Public functions */
-
-/**
- * gtk_source_completion_info_new:
- *
- * Returns: a new GtkSourceCompletionInfo.
- */
GtkSourceCompletionInfo *
-gtk_source_completion_info_new (void)
+_gtk_source_completion_info_new (void)
{
- return g_object_new (GTK_SOURCE_TYPE_COMPLETION_INFO,
- "type", GTK_WINDOW_POPUP,
- "border-width", 3,
- NULL);
+ return g_object_new (GTK_SOURCE_TYPE_COMPLETION_INFO, NULL);
}
-/**
- * gtk_source_completion_info_move_to_iter:
- * @info: a #GtkSourceCompletionInfo.
- * @view: a #GtkTextView on which the info window should be positioned.
- * @iter: (nullable): a #GtkTextIter.
- *
- * Moves the #GtkSourceCompletionInfo to @iter. If @iter is %NULL @info is
- * moved to the cursor position. Moving will respect the #GdkGravity setting
- * of the info window and will ensure the line at @iter is not occluded by
- * the window.
- */
-void
-gtk_source_completion_info_move_to_iter (GtkSourceCompletionInfo *info,
- GtkTextView *view,
- GtkTextIter *iter)
+GtkSourceCompletionCell *
+_gtk_source_completion_info_get_cell (GtkSourceCompletionInfo *self)
{
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION_INFO (info));
- g_return_if_fail (GTK_IS_TEXT_VIEW (view));
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_INFO (self), NULL);
- if (iter == NULL)
- {
- move_to_cursor (info, view);
- }
- else
- {
- move_to_iter (info, view, iter);
- }
+ return self->cell;
}
diff --git a/gtksourceview/gtksourcecompletioninfo.h b/gtksourceview/gtksourcecompletioninfo.h
deleted file mode 100644
index bbd2759f4583b1b0c608b37e5965732a262b8ce9..0000000000000000000000000000000000000000
--- a/gtksourceview/gtksourcecompletioninfo.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
- *
- * This file is part of GtkSourceView
- *
- * Copyright (C) 2007 - 2009 Jesús Barbero Rodríguez
- * Copyright (C) 2009 - Jesse van den Kieboom
- *
- * GtkSourceView is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * GtkSourceView 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, see .
- */
-
-#ifndef GTK_SOURCE_COMPLETION_INFO_H
-#define GTK_SOURCE_COMPLETION_INFO_H
-
-#if !defined (GTK_SOURCE_H_INSIDE) && !defined (GTK_SOURCE_COMPILATION)
-#error "Only can be included directly."
-#endif
-
-#include
-#include
-
-G_BEGIN_DECLS
-
-#define GTK_SOURCE_TYPE_COMPLETION_INFO (gtk_source_completion_info_get_type ())
-#define GTK_SOURCE_COMPLETION_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_SOURCE_TYPE_COMPLETION_INFO, GtkSourceCompletionInfo))
-#define GTK_SOURCE_COMPLETION_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_SOURCE_TYPE_COMPLETION_INFO, GtkSourceCompletionInfoClass)
-#define GTK_SOURCE_IS_COMPLETION_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_SOURCE_TYPE_COMPLETION_INFO))
-#define GTK_SOURCE_IS_COMPLETION_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_SOURCE_TYPE_COMPLETION_INFO))
-#define GTK_SOURCE_COMPLETION_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_SOURCE_TYPE_COMPLETION_INFO, GtkSourceCompletionInfoClass))
-
-typedef struct _GtkSourceCompletionInfoPrivate GtkSourceCompletionInfoPrivate;
-
-struct _GtkSourceCompletionInfo
-{
- GtkWindow parent;
-
- GtkSourceCompletionInfoPrivate *priv;
-};
-
-typedef struct _GtkSourceCompletionInfoClass GtkSourceCompletionInfoClass;
-
-struct _GtkSourceCompletionInfoClass
-{
- GtkWindowClass parent_class;
-
- gpointer padding[10];
-};
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-GType gtk_source_completion_info_get_type (void) G_GNUC_CONST;
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-GtkSourceCompletionInfo *
- gtk_source_completion_info_new (void);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_completion_info_move_to_iter (GtkSourceCompletionInfo *info,
- GtkTextView *view,
- GtkTextIter *iter);
-
-G_GNUC_INTERNAL
-void _gtk_source_completion_info_set_xoffset (GtkSourceCompletionInfo *info,
- gint xoffset);
-
-G_END_DECLS
-
-#endif /* GTK_SOURCE_COMPLETION_INFO_H */
diff --git a/gtksourceview/gtksourcecompletionitem.c b/gtksourceview/gtksourcecompletionitem.c
deleted file mode 100644
index 049ff4e3183ab3da950301a464c1bd1e177a8dcb..0000000000000000000000000000000000000000
--- a/gtksourceview/gtksourcecompletionitem.c
+++ /dev/null
@@ -1,544 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
- *
- * This file is part of GtkSourceView
- *
- * Copyright (C) 2009 - Jesse van den Kieboom
- * Copyright (C) 2016 - Sébastien Wilmet
- *
- * GtkSourceView is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * GtkSourceView 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, see .
- */
-
-/**
- * SECTION:completionitem
- * @title: GtkSourceCompletionItem
- * @short_description: Simple implementation of GtkSourceCompletionProposal
- *
- * The #GtkSourceCompletionItem class is a simple implementation of the
- * #GtkSourceCompletionProposal interface.
- */
-
-#ifdef HAVE_CONFIG_H
-#include
-#endif
-
-#include "gtksourcecompletionitem.h"
-#include "gtksourcecompletionproposal.h"
-
-struct _GtkSourceCompletionItemPrivate
-{
- gchar *label;
- gchar *markup;
- gchar *text;
- GdkPixbuf *icon;
- gchar *icon_name;
- GIcon *gicon;
- gchar *info;
-};
-
-enum
-{
- PROP_0,
- PROP_LABEL,
- PROP_MARKUP,
- PROP_TEXT,
- PROP_ICON,
- PROP_ICON_NAME,
- PROP_GICON,
- PROP_INFO
-};
-
-static void gtk_source_completion_proposal_iface_init (gpointer g_iface, gpointer iface_data);
-
-G_DEFINE_TYPE_WITH_CODE (GtkSourceCompletionItem,
- gtk_source_completion_item,
- G_TYPE_OBJECT,
- G_ADD_PRIVATE (GtkSourceCompletionItem)
- G_IMPLEMENT_INTERFACE (GTK_SOURCE_TYPE_COMPLETION_PROPOSAL,
- gtk_source_completion_proposal_iface_init))
-
-static gchar *
-gtk_source_completion_proposal_get_label_impl (GtkSourceCompletionProposal *proposal)
-{
- return g_strdup (GTK_SOURCE_COMPLETION_ITEM (proposal)->priv->label);
-}
-
-static gchar *
-gtk_source_completion_proposal_get_markup_impl (GtkSourceCompletionProposal *proposal)
-{
- return g_strdup (GTK_SOURCE_COMPLETION_ITEM (proposal)->priv->markup);
-}
-
-static gchar *
-gtk_source_completion_proposal_get_text_impl (GtkSourceCompletionProposal *proposal)
-{
- return g_strdup (GTK_SOURCE_COMPLETION_ITEM (proposal)->priv->text);
-}
-
-static GdkPixbuf *
-gtk_source_completion_proposal_get_icon_impl (GtkSourceCompletionProposal *proposal)
-{
- return GTK_SOURCE_COMPLETION_ITEM (proposal)->priv->icon;
-}
-
-static const gchar *
-gtk_source_completion_proposal_get_icon_name_impl (GtkSourceCompletionProposal *proposal)
-{
- return GTK_SOURCE_COMPLETION_ITEM (proposal)->priv->icon_name;
-}
-
-static GIcon *
-gtk_source_completion_proposal_get_gicon_impl (GtkSourceCompletionProposal *proposal)
-{
- return GTK_SOURCE_COMPLETION_ITEM (proposal)->priv->gicon;
-}
-
-static gchar *
-gtk_source_completion_proposal_get_info_impl (GtkSourceCompletionProposal *proposal)
-{
- return g_strdup (GTK_SOURCE_COMPLETION_ITEM (proposal)->priv->info);
-}
-
-static void
-gtk_source_completion_proposal_iface_init (gpointer g_iface,
- gpointer iface_data)
-{
- GtkSourceCompletionProposalIface *iface = g_iface;
-
- /* Interface data getter implementations */
- iface->get_label = gtk_source_completion_proposal_get_label_impl;
- iface->get_markup = gtk_source_completion_proposal_get_markup_impl;
- iface->get_text = gtk_source_completion_proposal_get_text_impl;
- iface->get_icon = gtk_source_completion_proposal_get_icon_impl;
- iface->get_icon_name = gtk_source_completion_proposal_get_icon_name_impl;
- iface->get_gicon = gtk_source_completion_proposal_get_gicon_impl;
- iface->get_info = gtk_source_completion_proposal_get_info_impl;
-}
-
-static void
-gtk_source_completion_item_dispose (GObject *object)
-{
- GtkSourceCompletionItem *item = GTK_SOURCE_COMPLETION_ITEM (object);
-
- g_clear_object (&item->priv->icon);
- g_clear_object (&item->priv->gicon);
-
- G_OBJECT_CLASS (gtk_source_completion_item_parent_class)->dispose (object);
-}
-
-static void
-gtk_source_completion_item_finalize (GObject *object)
-{
- GtkSourceCompletionItem *item = GTK_SOURCE_COMPLETION_ITEM (object);
-
- g_free (item->priv->label);
- g_free (item->priv->markup);
- g_free (item->priv->text);
- g_free (item->priv->icon_name);
- g_free (item->priv->info);
-
- G_OBJECT_CLASS (gtk_source_completion_item_parent_class)->finalize (object);
-}
-
-static void
-gtk_source_completion_item_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkSourceCompletionItem *item;
-
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION_ITEM (object));
-
- item = GTK_SOURCE_COMPLETION_ITEM (object);
-
- switch (prop_id)
- {
- case PROP_LABEL:
- g_value_set_string (value, item->priv->label);
- break;
-
- case PROP_MARKUP:
- g_value_set_string (value, item->priv->markup);
- break;
-
- case PROP_TEXT:
- g_value_set_string (value, item->priv->text);
- break;
-
- case PROP_ICON:
- g_value_set_object (value, item->priv->icon);
- break;
-
- case PROP_ICON_NAME:
- g_value_set_string (value, item->priv->icon_name);
- break;
-
- case PROP_GICON:
- g_value_set_object (value, item->priv->gicon);
- break;
-
- case PROP_INFO:
- g_value_set_string (value, item->priv->info);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-emit_changed (GtkSourceCompletionItem *item)
-{
- gtk_source_completion_proposal_changed (GTK_SOURCE_COMPLETION_PROPOSAL (item));
-}
-
-static void
-gtk_source_completion_item_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkSourceCompletionItem *item;
-
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION_ITEM (object));
-
- item = GTK_SOURCE_COMPLETION_ITEM (object);
-
- switch (prop_id)
- {
- case PROP_LABEL:
- gtk_source_completion_item_set_label (item, g_value_get_string (value));
- break;
-
- case PROP_MARKUP:
- gtk_source_completion_item_set_markup (item, g_value_get_string (value));
- break;
-
- case PROP_TEXT:
- gtk_source_completion_item_set_text (item, g_value_get_string (value));
- break;
-
- case PROP_ICON:
- gtk_source_completion_item_set_icon (item, g_value_get_object (value));
- break;
-
- case PROP_ICON_NAME:
- gtk_source_completion_item_set_icon_name (item, g_value_get_string (value));
- break;
-
- case PROP_GICON:
- gtk_source_completion_item_set_gicon (item, g_value_get_object (value));
- break;
-
- case PROP_INFO:
- gtk_source_completion_item_set_info (item, g_value_get_string (value));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_source_completion_item_class_init (GtkSourceCompletionItemClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->dispose = gtk_source_completion_item_dispose;
- object_class->finalize = gtk_source_completion_item_finalize;
- object_class->get_property = gtk_source_completion_item_get_property;
- object_class->set_property = gtk_source_completion_item_set_property;
-
- /**
- * GtkSourceCompletionItem:label:
- *
- * Label to be shown for this proposal.
- */
- g_object_class_install_property (object_class,
- PROP_LABEL,
- g_param_spec_string ("label",
- "Label",
- "",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS));
-
- /**
- * GtkSourceCompletionItem:markup:
- *
- * Label with markup to be shown for this proposal.
- */
- g_object_class_install_property (object_class,
- PROP_MARKUP,
- g_param_spec_string ("markup",
- "Markup",
- "",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS));
-
- /**
- * GtkSourceCompletionItem:text:
- *
- * Proposal text.
- */
- g_object_class_install_property (object_class,
- PROP_TEXT,
- g_param_spec_string ("text",
- "Text",
- "",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS));
-
- /**
- * GtkSourceCompletionItem:icon:
- *
- * The #GdkPixbuf for the icon to be shown for this proposal.
- */
- g_object_class_install_property (object_class,
- PROP_ICON,
- g_param_spec_object ("icon",
- "Icon",
- "",
- GDK_TYPE_PIXBUF,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS));
-
- /**
- * GtkSourceCompletionItem:icon-name:
- *
- * The icon name for the icon to be shown for this proposal.
- *
- * Since: 3.18
- */
- g_object_class_install_property (object_class,
- PROP_ICON_NAME,
- g_param_spec_string ("icon-name",
- "Icon Name",
- "",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS));
-
- /**
- * GtkSourceCompletionItem:gicon:
- *
- * The #GIcon for the icon to be shown for this proposal.
- *
- * Since: 3.18
- */
- g_object_class_install_property (object_class,
- PROP_GICON,
- g_param_spec_object ("gicon",
- "GIcon",
- "",
- G_TYPE_ICON,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS));
-
- /**
- * GtkSourceCompletionItem:info:
- *
- * Optional extra information to be shown for this proposal.
- */
- g_object_class_install_property (object_class,
- PROP_INFO,
- g_param_spec_string ("info",
- "Info",
- "",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS));
-}
-
-static void
-gtk_source_completion_item_init (GtkSourceCompletionItem *item)
-{
- item->priv = gtk_source_completion_item_get_instance_private (item);
-}
-
-/**
- * gtk_source_completion_item_new:
- *
- * Creates a new #GtkSourceCompletionItem. The desired properties need to be set
- * afterwards.
- *
- * Returns: (transfer full): a new #GtkSourceCompletionItem.
- * Since: 4.0
- */
-GtkSourceCompletionItem *
-gtk_source_completion_item_new (void)
-{
- return g_object_new (GTK_SOURCE_TYPE_COMPLETION_ITEM, NULL);
-}
-
-/**
- * gtk_source_completion_item_set_label:
- * @item: a #GtkSourceCompletionItem.
- * @label: (nullable): the label, or %NULL.
- *
- * Since: 3.24
- */
-void
-gtk_source_completion_item_set_label (GtkSourceCompletionItem *item,
- const gchar *label)
-{
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION_ITEM (item));
-
- if (g_strcmp0 (item->priv->label, label) != 0)
- {
- g_free (item->priv->label);
- item->priv->label = g_strdup (label);
-
- emit_changed (item);
- g_object_notify (G_OBJECT (item), "label");
- }
-}
-
-/**
- * gtk_source_completion_item_set_markup:
- * @item: a #GtkSourceCompletionItem.
- * @markup: (nullable): the markup, or %NULL.
- *
- * Since: 3.24
- */
-void
-gtk_source_completion_item_set_markup (GtkSourceCompletionItem *item,
- const gchar *markup)
-{
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION_ITEM (item));
-
- if (g_strcmp0 (item->priv->markup, markup) != 0)
- {
- g_free (item->priv->markup);
- item->priv->markup = g_strdup (markup);
-
- emit_changed (item);
- g_object_notify (G_OBJECT (item), "markup");
- }
-}
-
-/**
- * gtk_source_completion_item_set_text:
- * @item: a #GtkSourceCompletionItem.
- * @text: (nullable): the text, or %NULL.
- *
- * Since: 3.24
- */
-void
-gtk_source_completion_item_set_text (GtkSourceCompletionItem *item,
- const gchar *text)
-{
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION_ITEM (item));
-
- if (g_strcmp0 (item->priv->text, text) != 0)
- {
- g_free (item->priv->text);
- item->priv->text = g_strdup (text);
-
- emit_changed (item);
- g_object_notify (G_OBJECT (item), "text");
- }
-}
-
-/**
- * gtk_source_completion_item_set_icon:
- * @item: a #GtkSourceCompletionItem.
- * @icon: (nullable): the #GdkPixbuf, or %NULL.
- *
- * Since: 3.24
- */
-void
-gtk_source_completion_item_set_icon (GtkSourceCompletionItem *item,
- GdkPixbuf *icon)
-{
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION_ITEM (item));
- g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
-
- if (g_set_object (&item->priv->icon, icon))
- {
- emit_changed (item);
- g_object_notify (G_OBJECT (item), "icon");
- }
-}
-
-/**
- * gtk_source_completion_item_set_icon_name:
- * @item: a #GtkSourceCompletionItem.
- * @icon_name: (nullable): the icon name, or %NULL.
- *
- * Since: 3.24
- */
-void
-gtk_source_completion_item_set_icon_name (GtkSourceCompletionItem *item,
- const gchar *icon_name)
-{
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION_ITEM (item));
-
- if (g_strcmp0 (item->priv->icon_name, icon_name) != 0)
- {
- g_free (item->priv->icon_name);
- item->priv->icon_name = g_strdup (icon_name);
-
- emit_changed (item);
- g_object_notify (G_OBJECT (item), "icon-name");
- }
-}
-
-/**
- * gtk_source_completion_item_set_gicon:
- * @item: a #GtkSourceCompletionItem.
- * @gicon: (nullable): the #GIcon, or %NULL.
- *
- * Since: 3.24
- */
-void
-gtk_source_completion_item_set_gicon (GtkSourceCompletionItem *item,
- GIcon *gicon)
-{
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION_ITEM (item));
- g_return_if_fail (gicon == NULL || G_IS_ICON (gicon));
-
- if (g_set_object (&item->priv->gicon, gicon))
- {
- emit_changed (item);
- g_object_notify (G_OBJECT (item), "gicon");
- }
-}
-
-/**
- * gtk_source_completion_item_set_info:
- * @item: a #GtkSourceCompletionItem.
- * @info: (nullable): the info, or %NULL.
- *
- * Since: 3.24
- */
-void
-gtk_source_completion_item_set_info (GtkSourceCompletionItem *item,
- const gchar *info)
-{
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION_ITEM (item));
-
- if (g_strcmp0 (item->priv->info, info) != 0)
- {
- g_free (item->priv->info);
- item->priv->info = g_strdup (info);
-
- emit_changed (item);
- g_object_notify (G_OBJECT (item), "info");
- }
-}
diff --git a/gtksourceview/gtksourcecompletionitem.h b/gtksourceview/gtksourcecompletionitem.h
deleted file mode 100644
index 0f9e5b9cb030f81e2cb4d055978f1359e8f19539..0000000000000000000000000000000000000000
--- a/gtksourceview/gtksourcecompletionitem.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
- *
- * This file is part of GtkSourceView
- *
- * Copyright (C) 2009 - Jesse van den Kieboom
- * Copyright (C) 2016 - Sébastien Wilmet
- *
- * GtkSourceView is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * GtkSourceView 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, see .
- */
-
-#ifndef GTK_SOURCE_COMPLETION_ITEM_H
-#define GTK_SOURCE_COMPLETION_ITEM_H
-
-#if !defined (GTK_SOURCE_H_INSIDE) && !defined (GTK_SOURCE_COMPILATION)
-#error "Only can be included directly."
-#endif
-
-#include
-#include
-
-G_BEGIN_DECLS
-
-#define GTK_SOURCE_TYPE_COMPLETION_ITEM (gtk_source_completion_item_get_type ())
-#define GTK_SOURCE_COMPLETION_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_SOURCE_TYPE_COMPLETION_ITEM, GtkSourceCompletionItem))
-#define GTK_SOURCE_COMPLETION_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_SOURCE_TYPE_COMPLETION_ITEM, GtkSourceCompletionItemClass))
-#define GTK_SOURCE_IS_COMPLETION_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_SOURCE_TYPE_COMPLETION_ITEM))
-#define GTK_SOURCE_IS_COMPLETION_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_SOURCE_TYPE_COMPLETION_ITEM))
-#define GTK_SOURCE_COMPLETION_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_SOURCE_TYPE_COMPLETION_ITEM, GtkSourceCompletionItemClass))
-
-typedef struct _GtkSourceCompletionItemClass GtkSourceCompletionItemClass;
-typedef struct _GtkSourceCompletionItemPrivate GtkSourceCompletionItemPrivate;
-
-struct _GtkSourceCompletionItem {
- GObject parent;
-
- GtkSourceCompletionItemPrivate *priv;
-};
-
-struct _GtkSourceCompletionItemClass {
- GObjectClass parent_class;
-
- gpointer padding[10];
-};
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-GType gtk_source_completion_item_get_type (void) G_GNUC_CONST;
-
-GTK_SOURCE_AVAILABLE_IN_4_0
-GtkSourceCompletionItem *gtk_source_completion_item_new (void);
-
-GTK_SOURCE_AVAILABLE_IN_3_24
-void gtk_source_completion_item_set_label (GtkSourceCompletionItem *item,
- const gchar *label);
-
-GTK_SOURCE_AVAILABLE_IN_3_24
-void gtk_source_completion_item_set_markup (GtkSourceCompletionItem *item,
- const gchar *markup);
-
-GTK_SOURCE_AVAILABLE_IN_3_24
-void gtk_source_completion_item_set_text (GtkSourceCompletionItem *item,
- const gchar *text);
-
-GTK_SOURCE_AVAILABLE_IN_3_24
-void gtk_source_completion_item_set_icon (GtkSourceCompletionItem *item,
- GdkPixbuf *icon);
-
-GTK_SOURCE_AVAILABLE_IN_3_24
-void gtk_source_completion_item_set_icon_name (GtkSourceCompletionItem *item,
- const gchar *icon_name);
-
-GTK_SOURCE_AVAILABLE_IN_3_24
-void gtk_source_completion_item_set_gicon (GtkSourceCompletionItem *item,
- GIcon *gicon);
-
-GTK_SOURCE_AVAILABLE_IN_3_24
-void gtk_source_completion_item_set_info (GtkSourceCompletionItem *item,
- const gchar *info);
-
-G_END_DECLS
-
-#endif /* GTK_SOURCE_COMPLETION_ITEM_H */
diff --git a/gtksourceview/gtksourcecompletionlist-private.h b/gtksourceview/gtksourcecompletionlist-private.h
new file mode 100644
index 0000000000000000000000000000000000000000..10a03458ff39cbc9b65d5a7a1f522dca48ce90b0
--- /dev/null
+++ b/gtksourceview/gtksourcecompletionlist-private.h
@@ -0,0 +1,52 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2020 Christian Hergert
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#pragma once
+
+#include
+
+#include "gtksourceassistant-private.h"
+
+G_BEGIN_DECLS
+
+#define GTK_SOURCE_TYPE_COMPLETION_LIST (_gtk_source_completion_list_get_type())
+
+G_DECLARE_FINAL_TYPE (GtkSourceCompletionList, _gtk_source_completion_list, GTK_SOURCE, COMPLETION_LIST, GtkSourceAssistant)
+
+GtkSourceCompletionList *_gtk_source_completion_list_new (void);
+void _gtk_source_completion_list_reposition (GtkSourceCompletionList *self);
+GtkSourceCompletionContext *_gtk_source_completion_list_get_context (GtkSourceCompletionList *self);
+void _gtk_source_completion_list_set_context (GtkSourceCompletionList *self,
+ GtkSourceCompletionContext *context);
+gboolean _gtk_source_completion_list_get_show_details (GtkSourceCompletionList *self);
+void _gtk_source_completion_list_set_show_details (GtkSourceCompletionList *self,
+ gboolean show_details);
+guint _gtk_source_completion_list_get_n_rows (GtkSourceCompletionList *self);
+void _gtk_source_completion_list_set_n_rows (GtkSourceCompletionList *self,
+ guint n_rows);
+void _gtk_source_completion_list_set_font_desc (GtkSourceCompletionList *self,
+ const PangoFontDescription *font_desc);
+void _gtk_source_completion_list_set_show_icons (GtkSourceCompletionList *self,
+ gboolean show_icons);
+void _gtk_source_completion_list_set_remember_info_visibility (GtkSourceCompletionList *self,
+ gboolean remember_info_visibility);
+
+G_END_DECLS
diff --git a/gtksourceview/gtksourcecompletionlist.c b/gtksourceview/gtksourcecompletionlist.c
new file mode 100644
index 0000000000000000000000000000000000000000..0696276823a3126d4f08210e6c977aa02a915456
--- /dev/null
+++ b/gtksourceview/gtksourcecompletionlist.c
@@ -0,0 +1,570 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2020 Christian Hergert
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include
+
+#include "gtksourcecompletioncell-private.h"
+#include "gtksourcecompletioncontext-private.h"
+#include "gtksourcecompletionlist-private.h"
+#include "gtksourcecompletionlistbox-private.h"
+#include "gtksourcecompletionlistboxrow-private.h"
+#include "gtksourcecompletioninfo-private.h"
+#include "gtksourcecompletionprovider.h"
+#include "gtksourceutils-private.h"
+#include "gtksourceview.h"
+
+struct _GtkSourceCompletionList
+{
+ GtkSourceAssistant parent_instance;
+
+ GtkSourceCompletionContext *context;
+ GtkSourceCompletionInfo *info;
+
+ /* Template Widgets */
+ GtkSourceCompletionListBox *listbox;
+ GtkScrolledWindow *scroller;
+ GtkToggleButton *show_details;
+ GtkBox *details;
+ GtkSourceCompletionCell *comments;
+ GtkLabel *alternate_label;
+
+ guint remember_info_visibility : 1;
+};
+
+enum {
+ PROP_0,
+ PROP_CONTEXT,
+ PROP_SHOW_DETAILS,
+ N_PROPS
+};
+
+G_DEFINE_TYPE (GtkSourceCompletionList, _gtk_source_completion_list, GTK_SOURCE_TYPE_ASSISTANT)
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+_gtk_source_completion_list_hide (GtkWidget *widget)
+{
+ GtkSourceCompletionList *self = (GtkSourceCompletionList *)widget;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST (self));
+
+ GTK_WIDGET_CLASS (_gtk_source_completion_list_parent_class)->hide (widget);
+
+ if (!self->remember_info_visibility)
+ {
+ _gtk_source_completion_list_set_show_details (self, FALSE);
+ }
+}
+
+static void
+_gtk_source_completion_list_show (GtkWidget *widget)
+{
+ GtkSourceCompletionList *self = (GtkSourceCompletionList *)widget;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST (self));
+
+ GTK_WIDGET_CLASS (_gtk_source_completion_list_parent_class)->show (widget);
+
+ if (_gtk_source_completion_list_get_show_details (self))
+ {
+ gtk_widget_show (GTK_WIDGET (self->info));
+ }
+}
+
+static void
+_gtk_source_completion_list_show_details_notify_active_cb (GtkSourceCompletionList *self,
+ GParamSpec *pspec,
+ GtkToggleButton *toggle)
+{
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST (self));
+ g_assert (pspec != NULL);
+ g_assert (GTK_IS_TOGGLE_BUTTON (toggle));
+
+ if (gtk_widget_get_visible (GTK_WIDGET (self)) &&
+ _gtk_source_completion_list_get_show_details (self))
+ {
+ gtk_widget_show (GTK_WIDGET (self->info));
+ }
+ else
+ {
+ gtk_widget_hide (GTK_WIDGET (self->info));
+ }
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SHOW_DETAILS]);
+}
+
+static void
+_gtk_source_completion_list_update_comment (GtkSourceCompletionList *self)
+{
+ GtkSourceCompletionCell *info = NULL;
+ GtkSourceCompletionProposal *proposal = NULL;
+ GtkSourceCompletionProvider *provider = NULL;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST (self));
+
+ if (self->info != NULL)
+ {
+ info = _gtk_source_completion_info_get_cell (self->info);
+ }
+
+ if (_gtk_source_completion_list_box_get_selected (self->listbox, &provider, &proposal))
+ {
+ gtk_source_completion_provider_display (provider, self->context, proposal, self->comments);
+
+ if (info != NULL)
+ {
+ gtk_source_completion_provider_display (provider, self->context, proposal, info);
+ }
+ }
+ else
+ {
+ gtk_source_completion_cell_set_widget (self->comments, NULL);
+
+ if (info != NULL)
+ {
+ gtk_source_completion_cell_set_widget (info, NULL);
+ }
+ }
+
+ if (_gtk_source_completion_cell_is_empty (self->comments) &&
+ (info == NULL || _gtk_source_completion_cell_is_empty (info)))
+ {
+ gtk_widget_hide (GTK_WIDGET (self->details));
+ }
+ else
+ {
+ gtk_widget_show (GTK_WIDGET (self->details));
+ }
+
+ if (info != NULL)
+ {
+ if (_gtk_source_completion_cell_is_empty (info))
+ {
+ gtk_widget_hide (GTK_WIDGET (self->info));
+ }
+ else if (_gtk_source_completion_list_get_show_details (self))
+ {
+ if (gtk_widget_get_visible (GTK_WIDGET (self)))
+ {
+ gtk_widget_show (GTK_WIDGET (self->info));
+ }
+ }
+ }
+
+ g_clear_object (&proposal);
+ g_clear_object (&provider);
+}
+
+static void
+_gtk_source_completion_list_notify_alternates_cb (GtkSourceCompletionList *self,
+ GParamSpec *pspec,
+ GtkSourceCompletionListBox *listbox)
+{
+ int n_alternates;
+ int alternate;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST (self));
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST_BOX (listbox));
+
+ n_alternates = _gtk_source_completion_list_box_get_n_alternates (listbox);
+ alternate = _gtk_source_completion_list_box_get_alternate (listbox);
+
+ if (n_alternates == 0)
+ {
+ gtk_label_set_label (self->alternate_label, NULL);
+ }
+ else
+ {
+ char *str;
+
+ n_alternates++;
+ alternate = _gtk_source_completion_list_box_get_alternate (self->listbox);
+
+ if (alternate == -1)
+ {
+ str = g_strdup_printf (_("%d of %u"), 1, n_alternates);
+ }
+ else
+ {
+ str = g_strdup_printf (_("%d of %u"), alternate + 1, n_alternates);
+ }
+
+ gtk_label_set_label (self->alternate_label, str);
+
+ g_free (str);
+ }
+}
+
+static void
+_gtk_source_completion_list_reposition_cb (GtkSourceCompletionList *self)
+{
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST (self));
+
+ _gtk_source_assistant_reposition (GTK_SOURCE_ASSISTANT (self));
+}
+
+static void
+_gtk_source_completion_list_notify_proposal_cb (GtkSourceCompletionList *self,
+ GParamSpec *pspec,
+ GtkSourceCompletionListBox *listbox)
+{
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST (self));
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST_BOX (listbox));
+
+ _gtk_source_completion_list_update_comment (self);
+ _gtk_source_completion_list_notify_alternates_cb (self, NULL, listbox);
+}
+
+static void
+_gtk_source_completion_list_get_offset (GtkSourceAssistant *assistant,
+ int *x_offset,
+ int *y_offset)
+{
+ GtkSourceCompletionList *self = (GtkSourceCompletionList *)assistant;
+ GtkSourceCompletionListBoxRow *row;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST (self));
+ g_assert (x_offset != NULL);
+ g_assert (y_offset != NULL);
+
+ GTK_SOURCE_ASSISTANT_CLASS (_gtk_source_completion_list_parent_class)->get_offset (assistant, x_offset, y_offset);
+
+ if ((row = _gtk_source_completion_list_box_get_first (self->listbox)))
+ {
+ *x_offset = _gtk_source_completion_list_box_row_get_x_offset (row, GTK_WIDGET (self));
+ }
+}
+
+static gboolean
+key_press_propagate_cb (GtkSourceCompletionList *self,
+ guint keyval,
+ guint keycode,
+ GdkModifierType modifiers,
+ GtkEventControllerKey *key)
+{
+ GtkWidget *parent;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST (self));
+ g_assert (GTK_IS_EVENT_CONTROLLER_KEY (key));
+
+ if (gtk_event_controller_key_forward (key, GTK_WIDGET (self->listbox)))
+ {
+ return TRUE;
+ }
+
+ parent = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_SOURCE_TYPE_VIEW);
+
+ if (GTK_SOURCE_IS_VIEW (parent))
+ {
+ return gtk_event_controller_key_forward (key, parent);
+ }
+
+ return GDK_EVENT_PROPAGATE;
+}
+
+static gboolean
+key_release_propagate_cb (GtkSourceCompletionList *self,
+ guint keyval,
+ guint keycode,
+ GdkModifierType modifiers,
+ GtkEventControllerKey *key)
+{
+ GtkWidget *parent;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST (self));
+ g_assert (GTK_IS_EVENT_CONTROLLER_KEY (key));
+
+ if (gtk_event_controller_key_forward (key, GTK_WIDGET (self->listbox)))
+ {
+ return TRUE;
+ }
+
+ parent = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_SOURCE_TYPE_VIEW);
+
+ if (GTK_SOURCE_IS_VIEW (parent))
+ {
+ return gtk_event_controller_key_forward (key, parent);
+ }
+
+ return GDK_EVENT_PROPAGATE;
+}
+
+static void
+_gtk_source_completion_list_get_target_location (GtkSourceAssistant *assistant,
+ GdkRectangle *rect)
+{
+ g_assert (GTK_SOURCE_IS_ASSISTANT (assistant));
+ g_assert (rect != NULL);
+
+ GTK_SOURCE_ASSISTANT_CLASS (_gtk_source_completion_list_parent_class)->get_target_location (assistant, rect);
+
+ /* We want to align to the beginning of the character, so set the width
+ * to 0 to ensure things align correctly.
+ */
+ rect->width = 0;
+}
+
+static GtkSizeRequestMode
+_gtk_source_completion_list_get_request_mode (GtkWidget *widget)
+{
+ return GTK_SIZE_REQUEST_CONSTANT_SIZE;
+}
+
+static void
+_gtk_source_completion_list_dispose (GObject *object)
+{
+ GtkSourceCompletionList *self = (GtkSourceCompletionList *)object;
+
+ g_clear_object (&self->context);
+
+ G_OBJECT_CLASS (_gtk_source_completion_list_parent_class)->dispose (object);
+}
+
+static void
+_gtk_source_completion_list_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceCompletionList *self = GTK_SOURCE_COMPLETION_LIST (object);
+
+ switch (prop_id)
+ {
+ case PROP_CONTEXT:
+ g_value_set_object (value, self->context);
+ break;
+
+ case PROP_SHOW_DETAILS:
+ g_value_set_boolean (value, _gtk_source_completion_list_get_show_details (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+_gtk_source_completion_list_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceCompletionList *self = GTK_SOURCE_COMPLETION_LIST (object);
+
+ switch (prop_id)
+ {
+ case PROP_CONTEXT:
+ _gtk_source_completion_list_set_context (self, g_value_get_object (value));
+ break;
+
+ case PROP_SHOW_DETAILS:
+ _gtk_source_completion_list_set_show_details (self, g_value_get_boolean (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+_gtk_source_completion_list_class_init (GtkSourceCompletionListClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GtkSourceAssistantClass *assistant_class = GTK_SOURCE_ASSISTANT_CLASS (klass);
+
+ object_class->dispose = _gtk_source_completion_list_dispose;
+ object_class->get_property = _gtk_source_completion_list_get_property;
+ object_class->set_property = _gtk_source_completion_list_set_property;
+
+ widget_class->get_request_mode = _gtk_source_completion_list_get_request_mode;
+ widget_class->show = _gtk_source_completion_list_show;
+ widget_class->hide = _gtk_source_completion_list_hide;
+
+ assistant_class->get_offset = _gtk_source_completion_list_get_offset;
+ assistant_class->get_target_location = _gtk_source_completion_list_get_target_location;
+
+ properties [PROP_CONTEXT] =
+ g_param_spec_object ("context",
+ "Context",
+ "The context containing results",
+ GTK_SOURCE_TYPE_COMPLETION_CONTEXT,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_SHOW_DETAILS] =
+ g_param_spec_boolean ("show-details",
+ "Show Details",
+ "Show the details assistant",
+ FALSE,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/gtksourceview/ui/gtksourcecompletionlist.ui");
+ gtk_widget_class_bind_template_child (widget_class, GtkSourceCompletionList, alternate_label);
+ gtk_widget_class_bind_template_child (widget_class, GtkSourceCompletionList, comments);
+ gtk_widget_class_bind_template_child (widget_class, GtkSourceCompletionList, details);
+ gtk_widget_class_bind_template_child (widget_class, GtkSourceCompletionList, listbox);
+ gtk_widget_class_bind_template_child (widget_class, GtkSourceCompletionList, scroller);
+ gtk_widget_class_bind_template_child (widget_class, GtkSourceCompletionList, show_details);
+ gtk_widget_class_bind_template_callback (widget_class, _gtk_source_completion_list_notify_proposal_cb);
+ gtk_widget_class_bind_template_callback (widget_class, _gtk_source_completion_list_reposition_cb);
+
+ g_type_ensure (GTK_SOURCE_TYPE_COMPLETION_LIST_BOX);
+}
+
+static void
+_gtk_source_completion_list_init (GtkSourceCompletionList *self)
+{
+ GtkEventController *key;
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+ gtk_widget_add_css_class (GTK_WIDGET (self), "completion");
+ gtk_popover_set_position (GTK_POPOVER (self), GTK_POS_BOTTOM);
+
+ key = gtk_event_controller_key_new ();
+ gtk_event_controller_set_propagation_phase (key, GTK_PHASE_BUBBLE);
+ g_signal_connect_object (key,
+ "key-pressed",
+ G_CALLBACK (key_press_propagate_cb),
+ self,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (key,
+ "key-released",
+ G_CALLBACK (key_release_propagate_cb),
+ self,
+ G_CONNECT_SWAPPED);
+ gtk_widget_add_controller (GTK_WIDGET (self), g_steal_pointer (&key));
+
+ self->info = GTK_SOURCE_COMPLETION_INFO (_gtk_source_completion_info_new ());
+ _gtk_source_assistant_attach (GTK_SOURCE_ASSISTANT (self->info),
+ GTK_SOURCE_ASSISTANT (self));
+
+ g_signal_connect_object (self->show_details,
+ "notify::active",
+ G_CALLBACK (_gtk_source_completion_list_show_details_notify_active_cb),
+ self,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->listbox,
+ "notify::alternate",
+ G_CALLBACK (_gtk_source_completion_list_notify_alternates_cb),
+ self,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->listbox,
+ "notify::n-alternates",
+ G_CALLBACK (_gtk_source_completion_list_notify_alternates_cb),
+ self,
+ G_CONNECT_SWAPPED);
+}
+
+GtkSourceCompletionList *
+_gtk_source_completion_list_new (void)
+{
+ return g_object_new (GTK_SOURCE_TYPE_COMPLETION_LIST, NULL);
+}
+
+GtkSourceCompletionContext *
+_gtk_source_completion_list_get_context (GtkSourceCompletionList *self)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_LIST (self), NULL);
+
+ return self->context;
+}
+
+void
+_gtk_source_completion_list_set_context (GtkSourceCompletionList *self,
+ GtkSourceCompletionContext *context)
+{
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_LIST (self));
+ g_return_if_fail (!context || GTK_SOURCE_IS_COMPLETION_CONTEXT (context));
+
+ if (g_set_object (&self->context, context))
+ {
+ _gtk_source_completion_list_box_set_context (self->listbox, context);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_CONTEXT]);
+ }
+}
+
+gboolean
+_gtk_source_completion_list_get_show_details (GtkSourceCompletionList *self)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_LIST (self), FALSE);
+
+ return gtk_toggle_button_get_active (self->show_details);
+}
+
+void
+_gtk_source_completion_list_set_show_details (GtkSourceCompletionList *self,
+ gboolean show_details)
+{
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_LIST (self));
+
+ gtk_toggle_button_set_active (self->show_details, show_details);
+}
+
+guint
+_gtk_source_completion_list_get_n_rows (GtkSourceCompletionList *self)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_LIST (self), 0);
+
+ return _gtk_source_completion_list_box_get_n_rows (self->listbox);
+}
+
+void
+_gtk_source_completion_list_set_n_rows (GtkSourceCompletionList *self,
+ guint n_rows)
+{
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_LIST (self));
+
+ _gtk_source_completion_list_box_set_n_rows (self->listbox, n_rows);
+}
+
+void
+_gtk_source_completion_list_set_font_desc (GtkSourceCompletionList *self,
+ const PangoFontDescription *font_desc)
+{
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_LIST (self));
+
+ _gtk_source_completion_list_box_set_font_desc (self->listbox, font_desc);
+}
+
+void
+_gtk_source_completion_list_set_show_icons (GtkSourceCompletionList *self,
+ gboolean show_icons)
+{
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_LIST (self));
+
+ _gtk_source_completion_list_box_set_show_icons (self->listbox, show_icons);
+}
+
+void
+_gtk_source_completion_list_set_remember_info_visibility (GtkSourceCompletionList *self,
+ gboolean remember_info_visibility)
+{
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_LIST (self));
+
+ self->remember_info_visibility = !!remember_info_visibility;
+}
diff --git a/gtksourceview/gtksourcecompletionlist.ui b/gtksourceview/gtksourcecompletionlist.ui
new file mode 100644
index 0000000000000000000000000000000000000000..6209a694bc3b56a75890e511cafccc2e449b0c05
--- /dev/null
+++ b/gtksourceview/gtksourcecompletionlist.ui
@@ -0,0 +1,75 @@
+
+
+
+ false
+
+
+ vertical
+ false
+
+
+ never
+ automatic
+ true
+ true
+ 1
+
+
+ false
+
+
+
+
+
+
+
+
+ false
+ fill
+ true
+ horizontal
+ 12
+ start
+ false
+
+
+
+
+
+
+ horizontal
+ top
+ baseline
+
+
+ 6
+ 6
+ baseline
+
+
+
+
+ false
+ _Details
+ true
+ end
+ start
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gtksourceview/gtksourcecompletionlistbox-private.h b/gtksourceview/gtksourcecompletionlistbox-private.h
new file mode 100644
index 0000000000000000000000000000000000000000..5f4537053644970fa685c2d3ba3c03d160651669
--- /dev/null
+++ b/gtksourceview/gtksourcecompletionlistbox-private.h
@@ -0,0 +1,58 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2020 Christian Hergert
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#pragma once
+
+#include
+
+#include "gtksourcetypes-private.h"
+
+G_BEGIN_DECLS
+
+#define GTK_SOURCE_TYPE_COMPLETION_LIST_BOX (gtk_source_completion_list_box_get_type())
+
+G_DECLARE_FINAL_TYPE (GtkSourceCompletionListBox, gtk_source_completion_list_box, GTK_SOURCE, COMPLETION_LIST_BOX, GtkWidget)
+
+GtkWidget *_gtk_source_completion_list_box_new (void);
+GtkSourceCompletionContext *_gtk_source_completion_list_box_get_context (GtkSourceCompletionListBox *self);
+void _gtk_source_completion_list_box_set_context (GtkSourceCompletionListBox *self,
+ GtkSourceCompletionContext *context);
+guint _gtk_source_completion_list_box_get_n_rows (GtkSourceCompletionListBox *self);
+void _gtk_source_completion_list_box_set_n_rows (GtkSourceCompletionListBox *self,
+ guint n_rows);
+GtkSourceCompletionProposal *_gtk_source_completion_list_box_get_proposal (GtkSourceCompletionListBox *self);
+gboolean _gtk_source_completion_list_box_get_selected (GtkSourceCompletionListBox *self,
+ GtkSourceCompletionProvider **provider,
+ GtkSourceCompletionProposal **proposal);
+void _gtk_source_completion_list_box_move_cursor (GtkSourceCompletionListBox *self,
+ GtkMovementStep step,
+ gint direction);
+void _gtk_source_completion_list_box_set_font_desc (GtkSourceCompletionListBox *self,
+ const PangoFontDescription *font_desc);
+GtkSourceCompletionListBoxRow *_gtk_source_completion_list_box_get_first (GtkSourceCompletionListBox *self);
+gboolean _gtk_source_completion_list_box_key_activates (GtkSourceCompletionListBox *self,
+ const GdkKeyEvent *key);
+int _gtk_source_completion_list_box_get_alternate (GtkSourceCompletionListBox *self);
+guint _gtk_source_completion_list_box_get_n_alternates (GtkSourceCompletionListBox *self);
+void _gtk_source_completion_list_box_set_show_icons (GtkSourceCompletionListBox *self,
+ gboolean show_icons);
+
+G_END_DECLS
diff --git a/gtksourceview/gtksourcecompletionlistbox.c b/gtksourceview/gtksourcecompletionlistbox.c
new file mode 100644
index 0000000000000000000000000000000000000000..f831ed45d9c98afe161b081629a0cf6d47af30ea
--- /dev/null
+++ b/gtksourceview/gtksourcecompletionlistbox.c
@@ -0,0 +1,1273 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2020 Christian Hergert
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include "gtksourcecompletion-private.h"
+#include "gtksourcecompletioncontext-private.h"
+#include "gtksourcecompletionlistbox-private.h"
+#include "gtksourcecompletionlistboxrow-private.h"
+#include "gtksourcecompletionproposal.h"
+#include "gtksourcecompletionprovider.h"
+
+struct _GtkSourceCompletionListBox
+{
+ GtkWidget parent_instance;
+
+ /* The box containing the rows. */
+ GtkBox *box;
+
+ /* Font styling for rows */
+ PangoAttrList *font_attrs;
+
+ /* The completion context that is being displayed. */
+ GtkSourceCompletionContext *context;
+
+ /* The handler for GtkSourceCompletionContext::items-chaged which should
+ * be disconnected when no longer needed.
+ */
+ gulong items_changed_handler;
+
+ /* The number of rows we expect to have visible to the user. */
+ guint n_rows;
+
+ /* The currently selected index within the result set. Signed to
+ * ensure our math in various places allows going negative to catch
+ * lower edge.
+ */
+ int selected;
+
+ /* The alternate proposal for the current selection. This references
+ * something from GtkSourceCompletionProvider.list_alternates().
+ */
+ GPtrArray *alternates;
+ int alternate;
+
+ /* This is set whenever we make a change that requires updating the
+ * row content. We delay the update until the next frame callback so
+ * that we only update once right before we draw the frame. This helps
+ * reduce duplicate work when reacting to ::items-changed in the model.
+ */
+ guint queued_update;
+
+ /* These size groups are used to keep each portion of the proposal row
+ * aligned with each other. Since we only have a fixed number of visible
+ * rows, the overhead here is negligible by introducing the size cycle.
+ */
+ GtkSizeGroup *before_size_group;
+ GtkSizeGroup *typed_text_size_group;
+ GtkSizeGroup *after_size_group;
+
+ /* The adjustments for scrolling the GtkScrollable. */
+ GtkAdjustment *hadjustment;
+ GtkAdjustment *vadjustment;
+
+ /* Gesture to handle button press/touch events. */
+ GtkGesture *click_gesture;
+
+ /* If icons are visible */
+ guint show_icons : 1;
+};
+
+typedef struct
+{
+ GtkSourceCompletionListBox *self;
+ GtkSourceCompletionContext *context;
+ guint n_items;
+ guint position;
+ int selected;
+} UpdateState;
+
+enum {
+ PROP_0,
+ PROP_ALTERNATE,
+ PROP_CONTEXT,
+ PROP_PROPOSAL,
+ PROP_N_ROWS,
+ PROP_HADJUSTMENT,
+ PROP_HSCROLL_POLICY,
+ PROP_N_ALTERNATES,
+ PROP_VADJUSTMENT,
+ PROP_VSCROLL_POLICY,
+ N_PROPS
+};
+
+enum {
+ REPOSITION,
+ N_SIGNALS
+};
+
+static void gtk_source_completion_list_box_queue_update (GtkSourceCompletionListBox *self);
+static gboolean gtk_source_completion_list_box_update_cb (GtkWidget *widget,
+ GdkFrameClock *frame_clock,
+ gpointer user_data);
+static void gtk_source_completion_list_box_do_update (GtkSourceCompletionListBox *self,
+ gboolean update_selection);
+
+G_DEFINE_TYPE_WITH_CODE (GtkSourceCompletionListBox, gtk_source_completion_list_box, GTK_TYPE_WIDGET,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, NULL))
+
+static GParamSpec *properties [N_PROPS];
+static guint signals [N_SIGNALS];
+
+static void
+gtk_source_completion_list_box_set_selected (GtkSourceCompletionListBox *self,
+ int selected)
+{
+ GtkSourceCompletionProposal *proposal = NULL;
+ GtkSourceCompletionProvider *provider = NULL;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self));
+
+ if (selected == -1 && self->context != NULL)
+ {
+ GtkSourceCompletion *completion;
+ gboolean select_on_show;
+
+ completion = gtk_source_completion_context_get_completion (self->context);
+ select_on_show = _gtk_source_completion_get_select_on_show (completion);
+
+ if (select_on_show)
+ {
+ selected = 0;
+ }
+ }
+
+ self->selected = selected;
+ self->alternate = -1;
+ g_clear_pointer (&self->alternates, g_ptr_array_unref);
+
+ if (_gtk_source_completion_list_box_get_selected (self, &provider, &proposal))
+ {
+ self->alternates = gtk_source_completion_provider_list_alternates (provider, self->context, proposal);
+
+ if (self->alternates != NULL)
+ {
+ g_ptr_array_set_free_func (self->alternates, g_object_unref);
+ }
+ }
+
+ gtk_source_completion_list_box_queue_update (self);
+
+ g_clear_object (&proposal);
+ g_clear_object (&provider);
+}
+
+static gboolean
+move_next_alternate (GtkWidget *widget,
+ GVariant *param,
+ gpointer user_data)
+{
+ GtkSourceCompletionListBox *self = (GtkSourceCompletionListBox *)widget;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self));
+
+ if (self->alternates == NULL || self->alternates->len == 0)
+ {
+ return FALSE;
+ }
+
+ if ((guint)(self->alternate + 1) < self->alternates->len)
+ {
+ self->alternate++;
+ }
+ else
+ {
+ self->alternate = -1;
+ }
+
+ gtk_source_completion_list_box_do_update (self, FALSE);
+
+ return TRUE;
+}
+
+static void
+move_next_alternate_action (GtkWidget *widget,
+ const char *action_name,
+ GVariant *param)
+{
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST_BOX (widget));
+
+ move_next_alternate (widget, param, NULL);
+}
+
+static gboolean
+move_previous_alternate (GtkWidget *widget,
+ GVariant *param,
+ gpointer user_data)
+{
+ GtkSourceCompletionListBox *self = (GtkSourceCompletionListBox *)widget;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self));
+
+ if (self->alternates == NULL || self->alternates->len == 0)
+ {
+ return FALSE;
+ }
+
+ if (self->alternate < 0)
+ {
+ self->alternate = self->alternates->len - 1;
+ }
+ else
+ {
+ self->alternate--;
+ }
+
+ gtk_source_completion_list_box_do_update (self, FALSE);
+
+ return TRUE;
+}
+
+static void
+move_previous_alternate_action (GtkWidget *widget,
+ const char *action_name,
+ GVariant *param)
+{
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST_BOX (widget));
+
+ move_previous_alternate (widget, param, NULL);
+}
+
+static guint
+gtk_source_completion_list_box_get_offset (GtkSourceCompletionListBox *self)
+{
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self));
+
+ return gtk_adjustment_get_value (self->vadjustment);
+}
+
+static void
+gtk_source_completion_list_box_set_offset (GtkSourceCompletionListBox *self,
+ guint offset)
+{
+ double value = offset;
+ double page_size;
+ double upper;
+ double lower;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self));
+
+ lower = gtk_adjustment_get_lower (self->vadjustment);
+ upper = gtk_adjustment_get_upper (self->vadjustment);
+ page_size = gtk_adjustment_get_page_size (self->vadjustment);
+
+ if (value > (upper - page_size))
+ {
+ value = upper - page_size;
+ }
+
+ if (value < lower)
+ {
+ value = lower;
+ }
+
+ gtk_adjustment_set_value (self->vadjustment, value);
+}
+
+static void
+gtk_source_completion_list_box_value_changed (GtkSourceCompletionListBox *self,
+ GtkAdjustment *vadj)
+{
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self));
+ g_assert (GTK_IS_ADJUSTMENT (vadj));
+
+ gtk_source_completion_list_box_queue_update (self);
+}
+
+static void
+gtk_source_completion_list_box_set_hadjustment (GtkSourceCompletionListBox *self,
+ GtkAdjustment *hadjustment)
+{
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self));
+ g_assert (!hadjustment || GTK_IS_ADJUSTMENT (hadjustment));
+
+ if (g_set_object (&self->hadjustment, hadjustment))
+ {
+ gtk_source_completion_list_box_queue_update (self);
+ }
+}
+
+static void
+gtk_source_completion_list_box_set_vadjustment (GtkSourceCompletionListBox *self,
+ GtkAdjustment *vadjustment)
+{
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self));
+ g_assert (!vadjustment || GTK_IS_ADJUSTMENT (vadjustment));
+
+ if (self->vadjustment == vadjustment)
+ return;
+
+ if (self->vadjustment)
+ {
+ g_signal_handlers_disconnect_by_func (self->vadjustment,
+ G_CALLBACK (gtk_source_completion_list_box_value_changed),
+ self);
+ g_clear_object (&self->vadjustment);
+ }
+
+ if (vadjustment)
+ {
+ self->vadjustment = g_object_ref (vadjustment);
+
+ gtk_adjustment_set_lower (self->vadjustment, 0);
+ gtk_adjustment_set_upper (self->vadjustment, 0);
+ gtk_adjustment_set_value (self->vadjustment, 0);
+ gtk_adjustment_set_step_increment (self->vadjustment, 1);
+ gtk_adjustment_set_page_size (self->vadjustment, self->n_rows);
+ gtk_adjustment_set_page_increment (self->vadjustment, self->n_rows);
+
+ g_signal_connect_object (self->vadjustment,
+ "value-changed",
+ G_CALLBACK (gtk_source_completion_list_box_value_changed),
+ self,
+ G_CONNECT_SWAPPED);
+ }
+
+ gtk_source_completion_list_box_queue_update (self);
+}
+
+static guint
+get_row_at_y (GtkSourceCompletionListBox *self,
+ double y)
+{
+ GtkAllocation alloc;
+ guint offset;
+ guint n_items;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self));
+ g_assert (G_IS_LIST_MODEL (self->context));
+
+ gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
+
+ offset = gtk_source_completion_list_box_get_offset (self);
+
+ n_items = g_list_model_get_n_items (G_LIST_MODEL (self->context));
+ n_items = MAX (1, MIN (self->n_rows, n_items));
+
+ return offset + (y / (alloc.height / n_items));
+}
+
+static void
+click_gesture_pressed (GtkGestureClick *gesture,
+ guint n_press,
+ double x,
+ double y,
+ GtkSourceCompletionListBox *self)
+{
+ int selected;
+
+ g_assert (GTK_IS_GESTURE_CLICK (gesture));
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self));
+
+ if (self->context == NULL)
+ {
+ return;
+ }
+
+ selected = get_row_at_y (self, y);
+
+ if (selected != self->selected)
+ {
+ gtk_source_completion_list_box_set_selected (self, selected);
+ }
+ else
+ {
+ GtkSourceCompletionProvider *provider = NULL;
+ GtkSourceCompletionProposal *proposal = NULL;
+
+ if (self->selected >= 0 &&
+ self->selected < (int)g_list_model_get_n_items (G_LIST_MODEL (self->context)) &&
+ _gtk_source_completion_context_get_item_full (self->context, self->selected, &provider, &proposal))
+ {
+ _gtk_source_completion_activate (gtk_source_completion_context_get_completion (self->context),
+ self->context, provider, proposal);
+ g_clear_object (&provider);
+ g_clear_object (&proposal);
+ }
+ }
+}
+
+static gboolean
+move_binding_cb (GtkWidget *widget,
+ GVariant *param,
+ gpointer user_data)
+{
+ GtkSourceCompletionListBox *self = (GtkSourceCompletionListBox *)widget;
+ int direction = 0;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self));
+
+ g_variant_get (param, "(i)", &direction);
+
+ if (ABS (direction) == 1)
+ {
+ _gtk_source_completion_list_box_move_cursor (self, GTK_MOVEMENT_DISPLAY_LINES, direction);
+ }
+ else
+ {
+ _gtk_source_completion_list_box_move_cursor (self, GTK_MOVEMENT_PAGES, direction > 0 ? 1 : -1);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+activate_nth_cb (GtkWidget *widget,
+ GVariant *param,
+ gpointer user_data)
+{
+ GtkSourceCompletionListBox *self = (GtkSourceCompletionListBox *)widget;
+ GtkSourceCompletionProvider *provider = NULL;
+ GtkSourceCompletionProposal *proposal = NULL;
+ int nth = 0;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self));
+
+ if (self->context == NULL)
+ {
+ return FALSE;
+ }
+
+ g_variant_get (param, "(i)", &nth);
+
+ if (nth == 0 && self->selected >= 0)
+ {
+ nth = self->selected;
+ }
+ else
+ {
+ nth--;
+ }
+
+ if (nth < 0 || (guint)nth >= g_list_model_get_n_items (G_LIST_MODEL (self->context)))
+ {
+ return FALSE;
+ }
+
+ if (!_gtk_source_completion_context_get_item_full (self->context, nth, &provider, &proposal))
+ {
+ return FALSE;
+ }
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_PROVIDER (provider));
+ g_assert (GTK_SOURCE_IS_COMPLETION_PROPOSAL (proposal));
+
+ _gtk_source_completion_activate (gtk_source_completion_context_get_completion (self->context),
+ self->context,
+ provider,
+ proposal);
+
+ g_clear_object (&proposal);
+ g_clear_object (&provider);
+
+ return TRUE;
+}
+
+static gboolean
+_gtk_source_completion_list_box_key_pressed_cb (GtkSourceCompletionListBox *self,
+ guint keyval,
+ guint keycode,
+ GdkModifierType state,
+ GtkEventControllerKey *key)
+{
+ GtkSourceCompletionProvider *provider = NULL;
+ GtkSourceCompletionProposal *proposal = NULL;
+ gboolean ret = FALSE;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self));
+ g_assert (GTK_IS_EVENT_CONTROLLER_KEY (key));
+
+ if (self->context == NULL)
+ {
+ return FALSE;
+ }
+
+ if (_gtk_source_completion_list_box_get_selected (self, &provider, &proposal))
+ {
+ if (gtk_source_completion_provider_key_activates (provider, self->context, proposal, keyval, state))
+ {
+ _gtk_source_completion_activate (gtk_source_completion_context_get_completion (self->context),
+ self->context,
+ provider,
+ proposal);
+ ret = TRUE;
+ }
+ }
+
+ g_clear_object (&proposal);
+ g_clear_object (&provider);
+
+ return ret;
+}
+
+static void
+gtk_source_completion_list_box_constructed (GObject *object)
+{
+ GtkSourceCompletionListBox *self = (GtkSourceCompletionListBox *)object;
+
+ G_OBJECT_CLASS (gtk_source_completion_list_box_parent_class)->constructed (object);
+
+ if (self->hadjustment == NULL)
+ {
+ self->hadjustment = gtk_adjustment_new (0, 0, 0, 0, 0, 0);
+ }
+
+ if (self->vadjustment == NULL)
+ {
+ self->vadjustment = gtk_adjustment_new (0, 0, 0, 0, 0, 0);
+ }
+
+ gtk_adjustment_set_lower (self->hadjustment, 0);
+ gtk_adjustment_set_upper (self->hadjustment, 0);
+ gtk_adjustment_set_value (self->hadjustment, 0);
+
+ gtk_source_completion_list_box_queue_update (self);
+}
+
+static void
+gtk_source_completion_list_box_dispose (GObject *object)
+{
+ GtkSourceCompletionListBox *self = (GtkSourceCompletionListBox *)object;
+
+ if (self->box != NULL)
+ {
+ gtk_widget_unparent (GTK_WIDGET (self->box));
+ self->box = NULL;
+ }
+
+ g_clear_object (&self->before_size_group);
+ g_clear_object (&self->typed_text_size_group);
+ g_clear_object (&self->after_size_group);
+ g_clear_object (&self->hadjustment);
+ g_clear_object (&self->vadjustment);
+ g_clear_pointer (&self->font_attrs, pango_attr_list_unref);
+
+ G_OBJECT_CLASS (gtk_source_completion_list_box_parent_class)->dispose (object);
+}
+
+static void
+gtk_source_completion_list_box_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceCompletionListBox *self = GTK_SOURCE_COMPLETION_LIST_BOX (object);
+
+ switch (prop_id)
+ {
+ case PROP_N_ALTERNATES:
+ g_value_set_int (value, self->alternates ? self->alternates->len : 0);
+ break;
+
+ case PROP_ALTERNATE:
+ g_value_set_int (value, self->alternate);
+ break;
+
+ case PROP_CONTEXT:
+ g_value_set_object (value, _gtk_source_completion_list_box_get_context (self));
+ break;
+
+ case PROP_PROPOSAL:
+ g_value_take_object (value, _gtk_source_completion_list_box_get_proposal (self));
+ break;
+
+ case PROP_N_ROWS:
+ g_value_set_uint (value, _gtk_source_completion_list_box_get_n_rows (self));
+ break;
+
+ case PROP_HADJUSTMENT:
+ g_value_set_object (value, self->hadjustment);
+ break;
+
+ case PROP_VADJUSTMENT:
+ g_value_set_object (value, self->vadjustment);
+ break;
+
+ case PROP_HSCROLL_POLICY:
+ g_value_set_enum (value, GTK_SCROLL_NATURAL);
+ break;
+
+ case PROP_VSCROLL_POLICY:
+ g_value_set_enum (value, GTK_SCROLL_NATURAL);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gtk_source_completion_list_box_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceCompletionListBox *self = GTK_SOURCE_COMPLETION_LIST_BOX (object);
+
+ switch (prop_id)
+ {
+ case PROP_CONTEXT:
+ _gtk_source_completion_list_box_set_context (self, g_value_get_object (value));
+ break;
+
+ case PROP_N_ROWS:
+ _gtk_source_completion_list_box_set_n_rows (self, g_value_get_uint (value));
+ break;
+
+ case PROP_HADJUSTMENT:
+ gtk_source_completion_list_box_set_hadjustment (self, g_value_get_object (value));
+ break;
+
+ case PROP_VADJUSTMENT:
+ gtk_source_completion_list_box_set_vadjustment (self, g_value_get_object (value));
+ break;
+
+ case PROP_HSCROLL_POLICY:
+ /* Do nothing */
+ break;
+
+ case PROP_VSCROLL_POLICY:
+ /* Do nothing */
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gtk_source_completion_list_box_class_init (GtkSourceCompletionListBoxClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->constructed = gtk_source_completion_list_box_constructed;
+ object_class->dispose = gtk_source_completion_list_box_dispose;
+ object_class->get_property = gtk_source_completion_list_box_get_property;
+ object_class->set_property = gtk_source_completion_list_box_set_property;
+
+ properties [PROP_ALTERNATE] =
+ g_param_spec_int ("alternate",
+ "Alternate",
+ "The alternate to choose",
+ -1, G_MAXINT, -1,
+ (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_N_ALTERNATES] =
+ g_param_spec_int ("n-alternates",
+ "N Alternates",
+ "The number of alternates",
+ 0, G_MAXINT, 0,
+ (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_CONTEXT] =
+ g_param_spec_object ("context",
+ "Context",
+ "The context being displayed",
+ GTK_SOURCE_TYPE_COMPLETION_CONTEXT,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_HADJUSTMENT] =
+ g_param_spec_object ("hadjustment", NULL, NULL,
+ GTK_TYPE_ADJUSTMENT,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_HSCROLL_POLICY] =
+ g_param_spec_enum ("hscroll-policy", NULL, NULL,
+ GTK_TYPE_SCROLLABLE_POLICY,
+ GTK_SCROLL_NATURAL,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_VADJUSTMENT] =
+ g_param_spec_object ("vadjustment", NULL, NULL,
+ GTK_TYPE_ADJUSTMENT,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_VSCROLL_POLICY] =
+ g_param_spec_enum ("vscroll-policy", NULL, NULL,
+ GTK_TYPE_SCROLLABLE_POLICY,
+ GTK_SCROLL_NATURAL,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_PROPOSAL] =
+ g_param_spec_object ("proposal",
+ "Proposal",
+ "The proposal that is currently selected",
+ GTK_SOURCE_TYPE_COMPLETION_PROPOSAL,
+ (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_N_ROWS] =
+ g_param_spec_uint ("n-rows",
+ "N Rows",
+ "The number of visible rows",
+ 1, 32, 5,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ signals [REPOSITION] =
+ g_signal_new_class_handler ("reposition",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ NULL, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ g_signal_set_va_marshaller (signals [REPOSITION],
+ G_TYPE_FROM_CLASS (klass),
+ g_cclosure_marshal_VOID__VOIDv);
+
+ gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
+ gtk_widget_class_set_css_name (widget_class, "list");
+
+ gtk_widget_class_install_action (widget_class, "proposal.move-next-alternate", NULL, move_next_alternate_action);
+ gtk_widget_class_install_action (widget_class, "proposal.move-previous-alternate", NULL, move_previous_alternate_action);
+
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_Down, 0, move_binding_cb, "(i)", 1);
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_Up, 0, move_binding_cb, "(i)", -1);
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_Page_Up, 0, move_binding_cb, "(i)", -2);
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_Page_Down, 0, move_binding_cb, "(i)", 2);
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_1, GDK_ALT_MASK, activate_nth_cb, "(i)", 1);
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_2, GDK_ALT_MASK, activate_nth_cb, "(i)", 2);
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_3, GDK_ALT_MASK, activate_nth_cb, "(i)", 3);
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_4, GDK_ALT_MASK, activate_nth_cb, "(i)", 4);
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_5, GDK_ALT_MASK, activate_nth_cb, "(i)", 5);
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_6, GDK_ALT_MASK, activate_nth_cb, "(i)", 6);
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_7, GDK_ALT_MASK, activate_nth_cb, "(i)", 7);
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_8, GDK_ALT_MASK, activate_nth_cb, "(i)", 8);
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_9, GDK_ALT_MASK, activate_nth_cb, "(i)", 9);
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_Return, 0, activate_nth_cb, "(i)", 0);
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_KP_Enter, 0, activate_nth_cb, "(i)", 0);
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_Tab, 0, activate_nth_cb, "(i)", 0);
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_Right, 0, move_next_alternate, NULL);
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_Left, 0, move_previous_alternate, NULL);
+ gtk_widget_class_add_binding_action (widget_class, GDK_KEY_Escape, 0, "assistant.hide", NULL);
+
+ g_type_ensure (GTK_SOURCE_TYPE_COMPLETION_LIST_BOX_ROW);
+}
+
+static void
+gtk_source_completion_list_box_init (GtkSourceCompletionListBox *self)
+{
+ GtkEventController *key;
+
+ key = gtk_event_controller_key_new ();
+ g_signal_connect_swapped (key,
+ "key-pressed",
+ G_CALLBACK (_gtk_source_completion_list_box_key_pressed_cb),
+ self);
+ gtk_widget_add_controller (GTK_WIDGET (self), key);
+
+ self->box = g_object_new (GTK_TYPE_BOX,
+ "orientation", GTK_ORIENTATION_VERTICAL,
+ "visible", TRUE,
+ NULL);
+ gtk_widget_set_parent (GTK_WIDGET (self->box), GTK_WIDGET (self));
+
+ self->selected = -1;
+ self->alternate = -1;
+ self->before_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+ self->typed_text_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+ self->after_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+ self->click_gesture = gtk_gesture_click_new ();
+ gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (self->click_gesture), GTK_PHASE_BUBBLE);
+ gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (self->click_gesture), FALSE);
+ gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (self->click_gesture), GDK_BUTTON_PRIMARY);
+ g_signal_connect_object (self->click_gesture, "pressed",
+ G_CALLBACK (click_gesture_pressed), self, 0);
+ gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (self->click_gesture));
+}
+
+static void
+gtk_source_completion_list_box_do_update (GtkSourceCompletionListBox *self,
+ gboolean update_selection)
+{
+ UpdateState state = {0};
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self));
+
+ state.self = self;
+ state.context = self->context;
+ state.position = gtk_source_completion_list_box_get_offset (self);
+ state.selected = self->selected;
+
+ if (self->context != NULL)
+ {
+ state.n_items = g_list_model_get_n_items (G_LIST_MODEL (self->context));
+ }
+
+ state.position = MIN (state.position, MAX (state.n_items, self->n_rows) - self->n_rows);
+ state.selected = MIN (self->selected, state.n_items ? (int)state.n_items - 1 : 0);
+
+ if (gtk_adjustment_get_upper (self->vadjustment) != state.n_items)
+ {
+ gtk_adjustment_set_upper (self->vadjustment, state.n_items);
+ }
+
+ for (GtkWidget *iter = gtk_widget_get_first_child (GTK_WIDGET (self->box));
+ iter != NULL;
+ iter = gtk_widget_get_next_sibling (iter))
+ {
+ GtkSourceCompletionProposal *proposal = NULL;
+ GtkSourceCompletionProvider *provider = NULL;
+ gboolean has_alternates = FALSE;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST_BOX_ROW (iter));
+
+ if (state.selected >= 0 && state.position == (guint)state.selected)
+ {
+ gtk_widget_set_state_flags (iter, GTK_STATE_FLAG_SELECTED, FALSE);
+ }
+ else
+ {
+ gtk_widget_unset_state_flags (iter, GTK_STATE_FLAG_SELECTED);
+ }
+
+ if (state.context != NULL && state.position < state.n_items)
+ {
+ _gtk_source_completion_context_get_item_full (state.context,
+ state.position,
+ &provider,
+ &proposal);
+
+ if (state.selected == (int)state.position)
+ {
+ if (self->alternate >= 0 && self->alternate < (int)self->alternates->len)
+ {
+ g_clear_object (&proposal);
+ proposal = g_object_ref (g_ptr_array_index (self->alternates, self->alternate));
+ }
+
+ has_alternates = self->alternates != NULL && self->alternates->len > 0;
+ }
+
+ _gtk_source_completion_list_box_row_display (GTK_SOURCE_COMPLETION_LIST_BOX_ROW (iter),
+ state.context,
+ provider,
+ proposal,
+ self->show_icons,
+ has_alternates);
+
+ gtk_widget_show (iter);
+ }
+ else
+ {
+ _gtk_source_completion_list_box_row_display (GTK_SOURCE_COMPLETION_LIST_BOX_ROW (iter),
+ NULL, NULL, NULL, self->show_icons, FALSE);
+ gtk_widget_hide (GTK_WIDGET (iter));
+ }
+
+ state.position++;
+
+ g_clear_object (&proposal);
+ g_clear_object (&provider);
+ }
+
+ if (update_selection)
+ {
+ gtk_source_completion_list_box_set_selected (self, state.selected);
+ }
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_PROPOSAL]);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_N_ALTERNATES]);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ALTERNATE]);
+
+ g_signal_emit (self, signals [REPOSITION], 0);
+}
+
+static gboolean
+gtk_source_completion_list_box_update_cb (GtkWidget *widget,
+ GdkFrameClock *frame_clock,
+ gpointer user_data)
+{
+ GtkSourceCompletionListBox *self = (GtkSourceCompletionListBox *)widget;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self));
+
+ gtk_source_completion_list_box_do_update (self, TRUE);
+ self->queued_update = 0;
+ return G_SOURCE_REMOVE;
+}
+
+static void
+gtk_source_completion_list_box_queue_update (GtkSourceCompletionListBox *self)
+{
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self));
+
+ /* See gtk_source_completion_list_box_set_selected() for while this needs
+ * to be set here to avoid re-entrancy.
+ */
+ if (self->queued_update == 0)
+ {
+ self->queued_update = gtk_widget_add_tick_callback (GTK_WIDGET (self),
+ gtk_source_completion_list_box_update_cb,
+ NULL, NULL);
+ }
+}
+
+GtkWidget *
+_gtk_source_completion_list_box_new (void)
+{
+ return g_object_new (GTK_SOURCE_TYPE_COMPLETION_LIST_BOX, NULL);
+}
+
+guint
+_gtk_source_completion_list_box_get_n_rows (GtkSourceCompletionListBox *self)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self), 0);
+
+ return self->n_rows;
+}
+
+void
+_gtk_source_completion_list_box_set_n_rows (GtkSourceCompletionListBox *self,
+ guint n_rows)
+{
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self));
+ g_return_if_fail (n_rows > 0);
+ g_return_if_fail (n_rows <= 32);
+
+ if (n_rows != self->n_rows)
+ {
+ GtkWidget *tmp;
+
+ while ((tmp = gtk_widget_get_first_child (GTK_WIDGET (self->box))))
+ {
+ gtk_box_remove (self->box, tmp);
+ }
+
+ self->n_rows = n_rows;
+
+ if (self->vadjustment != NULL)
+ {
+ gtk_adjustment_set_page_size (self->vadjustment, n_rows);
+ }
+
+ for (guint i = 0; i < n_rows; i++)
+ {
+ GtkWidget *row;
+
+ row = _gtk_source_completion_list_box_row_new ();
+ gtk_widget_set_can_focus (GTK_WIDGET (row), FALSE);
+ _gtk_source_completion_list_box_row_attach (GTK_SOURCE_COMPLETION_LIST_BOX_ROW (row),
+ self->before_size_group,
+ self->typed_text_size_group,
+ self->after_size_group);
+ _gtk_source_completion_list_box_row_set_attrs (GTK_SOURCE_COMPLETION_LIST_BOX_ROW (row),
+ self->font_attrs);
+ gtk_box_append (self->box, row);
+ }
+
+ gtk_source_completion_list_box_queue_update (self);
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_N_ROWS]);
+ }
+}
+
+/**
+ * gtk_source_completion_list_box_get_proposal:
+ * @self: a #GtkSourceCompletionListBox
+ *
+ * Gets the currently selected proposal, or %NULL if no proposal is selected
+ *
+ * Returns: (nullable) (transfer full): a #GtkSourceCompletionProposal or %NULL
+ *
+ * Since: 5.0
+ */
+GtkSourceCompletionProposal *
+_gtk_source_completion_list_box_get_proposal (GtkSourceCompletionListBox *self)
+{
+ GtkSourceCompletionProposal *ret = NULL;
+
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self), NULL);
+
+ if (self->context != NULL &&
+ self->selected < (int)g_list_model_get_n_items (G_LIST_MODEL (self->context)))
+ ret = g_list_model_get_item (G_LIST_MODEL (self->context), self->selected);
+
+ g_return_val_if_fail (!ret || GTK_SOURCE_IS_COMPLETION_PROPOSAL (ret), NULL);
+
+ return ret;
+}
+
+/**
+ * _gtk_source_completion_list_box_get_selected:
+ * @self: an #GtkSourceCompletionListBox
+ * @provider: (out) (transfer full) (optional): a location for the provider
+ * @proposal: (out) (transfer full) (optional): a location for the proposal
+ *
+ * Gets the selected item if there is any.
+ *
+ * If there is a selection, %TRUE is returned and @provider and @proposal
+ * are set to the selected provider/proposal.
+ *
+ * Returns: %TRUE if there is a selection
+ *
+ * Since: 5.0
+ */
+gboolean
+_gtk_source_completion_list_box_get_selected (GtkSourceCompletionListBox *self,
+ GtkSourceCompletionProvider **provider,
+ GtkSourceCompletionProposal **proposal)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self), FALSE);
+
+ if (self->context != NULL)
+ {
+ guint n_items = g_list_model_get_n_items (G_LIST_MODEL (self->context));
+
+ if (n_items > 0)
+ {
+ if (self->selected >= 0)
+ {
+ gint selected = MIN (self->selected, (int)n_items - 1);
+ _gtk_source_completion_context_get_item_full (self->context, selected, provider, proposal);
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ * gtk_source_completion_list_box_get_context:
+ * @self: a #GtkSourceCompletionListBox
+ *
+ * Gets the context that is being displayed in the list box.
+ *
+ * Returns: (transfer none) (nullable): an #GtkSourceCompletionContext or %NULL
+ *
+ * Since: 5.0
+ */
+GtkSourceCompletionContext *
+_gtk_source_completion_list_box_get_context (GtkSourceCompletionListBox *self)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self), NULL);
+
+ return self->context;
+}
+
+static void
+gtk_source_completion_list_box_items_changed_cb (GtkSourceCompletionListBox *self,
+ guint position,
+ guint removed,
+ guint added,
+ GListModel *model)
+{
+ guint offset;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self));
+ g_assert (G_IS_LIST_MODEL (model));
+
+ offset = gtk_source_completion_list_box_get_offset (self);
+
+ /* Skip widget resize if results are after visible area */
+ if (position >= offset + self->n_rows)
+ return;
+
+ gtk_source_completion_list_box_queue_update (self);
+}
+
+/**
+ * gtk_source_completion_list_box_set_context:
+ * @self: a #GtkSourceCompletionListBox
+ * @context: the #GtkSourceCompletionContext
+ *
+ * Sets the context to be displayed.
+ *
+ * Since: 5.0
+ */
+void
+_gtk_source_completion_list_box_set_context (GtkSourceCompletionListBox *self,
+ GtkSourceCompletionContext *context)
+{
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self));
+ g_return_if_fail (!context || GTK_SOURCE_IS_COMPLETION_CONTEXT (context));
+
+ if (self->context == context)
+ return;
+
+ if (self->context != NULL && self->items_changed_handler != 0)
+ {
+ g_signal_handler_disconnect (self->context, self->items_changed_handler);
+ self->items_changed_handler = 0;
+ }
+
+ g_set_object (&self->context, context);
+
+ if (self->context != NULL)
+ {
+ self->items_changed_handler =
+ g_signal_connect_object (self->context,
+ "items-changed",
+ G_CALLBACK (gtk_source_completion_list_box_items_changed_cb),
+ self,
+ G_CONNECT_SWAPPED);
+ }
+
+ gtk_source_completion_list_box_set_selected (self, -1);
+ gtk_adjustment_set_value (self->vadjustment, 0);
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_CONTEXT]);
+}
+
+GtkSourceCompletionListBoxRow *
+_gtk_source_completion_list_box_get_first (GtkSourceCompletionListBox *self)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self), NULL);
+
+ return GTK_SOURCE_COMPLETION_LIST_BOX_ROW (gtk_widget_get_first_child (GTK_WIDGET (self->box)));
+}
+
+void
+_gtk_source_completion_list_box_move_cursor (GtkSourceCompletionListBox *self,
+ GtkMovementStep step,
+ int direction)
+{
+ int n_items;
+ int offset;
+
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self));
+
+ if (self->context == NULL || direction == 0)
+ return;
+
+ if (!(n_items = g_list_model_get_n_items (G_LIST_MODEL (self->context))))
+ return;
+
+ /* n_items is signed so that we can do negative comparison */
+ if (n_items < 0)
+ return;
+
+ if (step == GTK_MOVEMENT_BUFFER_ENDS)
+ {
+ if (direction > 0)
+ {
+ gtk_source_completion_list_box_set_offset (self, n_items);
+ gtk_source_completion_list_box_set_selected (self, n_items - 1);
+ }
+ else
+ {
+ gtk_source_completion_list_box_set_offset (self, 0);
+ gtk_source_completion_list_box_set_selected (self, -1);
+ }
+
+ gtk_source_completion_list_box_queue_update (self);
+
+ return;
+ }
+
+ if ((direction < 0 && self->selected == 0) ||
+ (direction > 0 && self->selected == n_items - 1))
+ {
+ return;
+ }
+
+ if (step == GTK_MOVEMENT_PAGES)
+ {
+ direction *= self->n_rows;
+ }
+
+ if ((self->selected + direction) > n_items)
+ {
+ gtk_source_completion_list_box_set_selected (self, n_items - 1);
+ }
+ else if ((self->selected + direction) < 0)
+ {
+ gtk_source_completion_list_box_set_selected (self, 0);
+ }
+ else
+ {
+ gtk_source_completion_list_box_set_selected (self, self->selected + direction);
+ }
+
+ offset = gtk_source_completion_list_box_get_offset (self);
+
+ if (self->selected < offset)
+ {
+ gtk_source_completion_list_box_set_offset (self, self->selected);
+ }
+ else if (self->selected >= (int)(offset + self->n_rows))
+ {
+ gtk_source_completion_list_box_set_offset (self, self->selected - self->n_rows + 1);
+ }
+
+ gtk_source_completion_list_box_queue_update (self);
+}
+
+void
+_gtk_source_completion_list_box_set_font_desc (GtkSourceCompletionListBox *self,
+ const PangoFontDescription *font_desc)
+{
+ GtkWidget *iter;
+
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self));
+
+ g_clear_pointer (&self->font_attrs, pango_attr_list_unref);
+
+ if (font_desc)
+ {
+ self->font_attrs = pango_attr_list_new ();
+
+ if (font_desc != NULL)
+ {
+ pango_attr_list_insert (self->font_attrs, pango_attr_font_desc_new (font_desc));
+ pango_attr_list_insert (self->font_attrs, pango_attr_font_features_new ("tnum"));
+ }
+ }
+
+ for ((iter = gtk_widget_get_first_child (GTK_WIDGET (self->box)));
+ iter != NULL;
+ iter = gtk_widget_get_next_sibling (iter))
+ {
+ _gtk_source_completion_list_box_row_set_attrs (GTK_SOURCE_COMPLETION_LIST_BOX_ROW (iter),
+ self->font_attrs);
+ }
+}
+
+int
+_gtk_source_completion_list_box_get_alternate (GtkSourceCompletionListBox *self)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self), 0);
+
+ return self->alternate + 1;
+}
+
+guint
+_gtk_source_completion_list_box_get_n_alternates (GtkSourceCompletionListBox *self)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self), 0);
+
+ return self->alternates ? self->alternates->len : 0;
+}
+
+void
+_gtk_source_completion_list_box_set_show_icons (GtkSourceCompletionListBox *self,
+ gboolean show_icons)
+{
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_LIST_BOX (self));
+
+ self->show_icons = !!show_icons;
+
+ gtk_source_completion_list_box_queue_update (self);
+}
diff --git a/gtksourceview/gtksourcecompletionlistboxrow-private.h b/gtksourceview/gtksourcecompletionlistboxrow-private.h
new file mode 100644
index 0000000000000000000000000000000000000000..ab3fa8c059302f71c7e8c477ba703c1cbdbe7eb3
--- /dev/null
+++ b/gtksourceview/gtksourcecompletionlistboxrow-private.h
@@ -0,0 +1,50 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2020 Christian Hergert
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#pragma once
+
+#include
+
+#include "gtksourcetypes.h"
+
+G_BEGIN_DECLS
+
+#define GTK_SOURCE_TYPE_COMPLETION_LIST_BOX_ROW (gtk_source_completion_list_box_row_get_type())
+
+G_DECLARE_FINAL_TYPE (GtkSourceCompletionListBoxRow, gtk_source_completion_list_box_row, GTK_SOURCE, COMPLETION_LIST_BOX_ROW, GtkListBoxRow)
+
+GtkWidget *_gtk_source_completion_list_box_row_new (void);
+void _gtk_source_completion_list_box_row_display (GtkSourceCompletionListBoxRow *self,
+ GtkSourceCompletionContext *context,
+ GtkSourceCompletionProvider *provider,
+ GtkSourceCompletionProposal *proposal,
+ gboolean show_icons,
+ gboolean has_alternates);
+gint _gtk_source_completion_list_box_row_get_x_offset (GtkSourceCompletionListBoxRow *self,
+ GtkWidget *toplevel);
+void _gtk_source_completion_list_box_row_set_attrs (GtkSourceCompletionListBoxRow *self,
+ PangoAttrList *attrs);
+void _gtk_source_completion_list_box_row_attach (GtkSourceCompletionListBoxRow *self,
+ GtkSizeGroup *before,
+ GtkSizeGroup *typed_text,
+ GtkSizeGroup *after);
+
+G_END_DECLS
diff --git a/gtksourceview/gtksourcecompletionlistboxrow.c b/gtksourceview/gtksourcecompletionlistboxrow.c
new file mode 100644
index 0000000000000000000000000000000000000000..c64e358b5ce7d28a75599376171ca26b16536ea4
--- /dev/null
+++ b/gtksourceview/gtksourcecompletionlistboxrow.c
@@ -0,0 +1,197 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2020 Christian Hergert
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see .
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include "gtksourcecompletioncell-private.h"
+#include "gtksourcecompletioncontext-private.h"
+#include "gtksourcecompletionlistboxrow-private.h"
+#include "gtksourcecompletionproposal.h"
+#include "gtksourcecompletionprovider.h"
+
+struct _GtkSourceCompletionListBoxRow
+{
+ GtkListBoxRow parent_instance;
+
+ GtkSourceCompletionProposal *proposal;
+ PangoAttrList *attrs;
+
+ GtkBox *box;
+ GtkBox *more;
+ GtkSourceCompletionCell *icon;
+ GtkSourceCompletionCell *before;
+ GtkSourceCompletionCell *typed_text;
+ GtkSourceCompletionCell *after;
+};
+
+G_DEFINE_TYPE (GtkSourceCompletionListBoxRow, gtk_source_completion_list_box_row, GTK_TYPE_LIST_BOX_ROW)
+
+static void
+gtk_source_completion_list_box_row_finalize (GObject *object)
+{
+ GtkSourceCompletionListBoxRow *self = (GtkSourceCompletionListBoxRow *)object;
+
+ g_clear_pointer (&self->attrs, pango_attr_list_unref);
+
+ G_OBJECT_CLASS (gtk_source_completion_list_box_row_parent_class)->finalize (object);
+}
+
+static void
+gtk_source_completion_list_box_row_class_init (GtkSourceCompletionListBoxRowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = gtk_source_completion_list_box_row_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/gtksourceview/ui/gtksourcecompletionlistboxrow.ui");
+ gtk_widget_class_bind_template_child (widget_class, GtkSourceCompletionListBoxRow, box);
+ gtk_widget_class_bind_template_child (widget_class, GtkSourceCompletionListBoxRow, icon);
+ gtk_widget_class_bind_template_child (widget_class, GtkSourceCompletionListBoxRow, before);
+ gtk_widget_class_bind_template_child (widget_class, GtkSourceCompletionListBoxRow, typed_text);
+ gtk_widget_class_bind_template_child (widget_class, GtkSourceCompletionListBoxRow, after);
+ gtk_widget_class_bind_template_child (widget_class, GtkSourceCompletionListBoxRow, more);
+
+ g_type_ensure (GTK_SOURCE_TYPE_COMPLETION_CELL);
+}
+
+static void
+gtk_source_completion_list_box_row_init (GtkSourceCompletionListBoxRow *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+GtkWidget *
+_gtk_source_completion_list_box_row_new (void)
+{
+ return g_object_new (GTK_SOURCE_TYPE_COMPLETION_LIST_BOX_ROW, NULL);
+}
+
+void
+_gtk_source_completion_list_box_row_display (GtkSourceCompletionListBoxRow *self,
+ GtkSourceCompletionContext *context,
+ GtkSourceCompletionProvider *provider,
+ GtkSourceCompletionProposal *proposal,
+ gboolean show_icons,
+ gboolean has_alternates)
+{
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_LIST_BOX_ROW (self));
+ g_return_if_fail (!context || GTK_SOURCE_IS_COMPLETION_CONTEXT (context));
+ g_return_if_fail (!provider || GTK_SOURCE_IS_COMPLETION_PROVIDER (provider));
+ g_return_if_fail (!proposal || GTK_SOURCE_IS_COMPLETION_PROPOSAL (proposal));
+
+ if (proposal == NULL)
+ {
+ gtk_source_completion_cell_set_widget (self->icon, NULL);
+ gtk_source_completion_cell_set_widget (self->before, NULL);
+ gtk_source_completion_cell_set_widget (self->typed_text, NULL);
+ gtk_source_completion_cell_set_widget (self->after, NULL);
+ }
+ else
+ {
+ gtk_source_completion_provider_display (provider, context, proposal, self->icon);
+ gtk_source_completion_provider_display (provider, context, proposal, self->before);
+ gtk_source_completion_provider_display (provider, context, proposal, self->typed_text);
+ gtk_source_completion_provider_display (provider, context, proposal, self->after);
+ }
+
+ gtk_widget_set_visible (GTK_WIDGET (self->icon), show_icons);
+ gtk_widget_set_visible (GTK_WIDGET (self->more), has_alternates);
+}
+
+void
+_gtk_source_completion_list_box_row_attach (GtkSourceCompletionListBoxRow *self,
+ GtkSizeGroup *before,
+ GtkSizeGroup *typed_text,
+ GtkSizeGroup *after)
+{
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_LIST_BOX_ROW (self));
+ g_return_if_fail (GTK_IS_SIZE_GROUP (before));
+ g_return_if_fail (GTK_IS_SIZE_GROUP (typed_text));
+ g_return_if_fail (GTK_IS_SIZE_GROUP (after));
+
+ gtk_size_group_add_widget (before, GTK_WIDGET (self->before));
+ gtk_size_group_add_widget (typed_text, GTK_WIDGET (self->typed_text));
+ gtk_size_group_add_widget (after, GTK_WIDGET (self->after));
+}
+
+static void
+get_margin_and_border (GtkWidget *widget,
+ GtkBorder *margin,
+ GtkBorder *border)
+{
+ GtkStyleContext *style_context = gtk_widget_get_style_context (widget);
+ gtk_style_context_get_margin (style_context, margin);
+ gtk_style_context_get_border (style_context, border);
+}
+
+gint
+_gtk_source_completion_list_box_row_get_x_offset (GtkSourceCompletionListBoxRow *self,
+ GtkWidget *toplevel)
+{
+ GtkRequisition min;
+ GtkRequisition nat;
+ GtkBorder margin;
+ GtkBorder border;
+ double x = 0;
+
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_LIST_BOX_ROW (self), 0);
+ g_return_val_if_fail (GTK_IS_WIDGET (toplevel), 0);
+
+ for (GtkWidget *iter = GTK_WIDGET (self->box);
+ iter != NULL;
+ iter = gtk_widget_get_parent (iter))
+ {
+ get_margin_and_border (iter, &margin, &border);
+ x += margin.left + border.left;
+
+ if (iter == toplevel)
+ {
+ break;
+ }
+ }
+
+ get_margin_and_border (GTK_WIDGET (self->icon), &margin, &border);
+ gtk_widget_get_preferred_size (GTK_WIDGET (self->icon), &min, &nat);
+ x += margin.left + border.left + nat.width + margin.right + border.right;
+
+ get_margin_and_border (GTK_WIDGET (self->before), &margin, &border);
+ gtk_widget_get_preferred_size (GTK_WIDGET (self->before), &min, &nat);
+ x += margin.left + border.left + nat.width + border.right + margin.right;
+
+ get_margin_and_border (GTK_WIDGET (self->typed_text), &margin, &border);
+ gtk_widget_get_preferred_size (GTK_WIDGET (self->typed_text), &min, &nat);
+ x += margin.left + border.left;
+
+ return -x;
+}
+
+void
+_gtk_source_completion_list_box_row_set_attrs (GtkSourceCompletionListBoxRow *self,
+ PangoAttrList *attrs)
+{
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST_BOX_ROW (self));
+
+ _gtk_source_completion_cell_set_attrs (self->icon, attrs);
+ _gtk_source_completion_cell_set_attrs (self->before, attrs);
+ _gtk_source_completion_cell_set_attrs (self->typed_text, attrs);
+ _gtk_source_completion_cell_set_attrs (self->after, attrs);
+}
diff --git a/gtksourceview/gtksourcecompletionlistboxrow.ui b/gtksourceview/gtksourcecompletionlistboxrow.ui
new file mode 100644
index 0000000000000000000000000000000000000000..671fce2fb82ecdf97c6727cc018d162f524694cf
--- /dev/null
+++ b/gtksourceview/gtksourcecompletionlistboxrow.ui
@@ -0,0 +1,65 @@
+
+
+
+ false
+
+
+ false
+ true
+ horizontal
+
+
+ false
+ icon
+
+
+
+
+ false
+ before
+
+
+
+
+ false
+ typed-text
+ true
+
+
+
+
+ false
+ after
+
+
+
+
+
+
+
+ proposal.move-previous-alternate
+ false
+ pan-start-symbolic
+
+
+
+
+
+ proposal.move-next-alternate
+ false
+ pan-end-symbolic
+
+
+
+
+
+
+
+
+
diff --git a/gtksourceview/gtksourcecompletionmodel.c b/gtksourceview/gtksourcecompletionmodel.c
deleted file mode 100644
index 73facc7789dd789f43f7be09c69ad65348270626..0000000000000000000000000000000000000000
--- a/gtksourceview/gtksourcecompletionmodel.c
+++ /dev/null
@@ -1,1243 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- *
- *
- * This file is part of GtkSourceView
- *
- * Copyright (C) 2009 - Jesse van den Kieboom
- * Copyright (C) 2013 - Sébastien Wilmet
- *
- * GtkSourceView is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * GtkSourceView 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, see .
- */
-
-#ifdef HAVE_CONFIG_H
-#include
-#endif
-
-#include "gtksourcecompletionmodel.h"
-#include
-#include "gtksourcecompletionprovider.h"
-#include "gtksourcecompletionproposal.h"
-
-typedef struct
-{
- GtkSourceCompletionModel *model;
- GtkSourceCompletionProvider *completion_provider;
-
- /* List of ProposalInfo. If the header is visible, it is included. */
- GQueue *proposals;
-
- /* By default, all providers are visible. But with Ctrl+{left, right},
- * the user can switch between providers. In this case, only one
- * provider is visible, and the others are hidden. */
- guint visible : 1;
-} ProviderInfo;
-
-typedef struct
-{
- /* Node from model->priv->providers */
- GList *provider_node;
-
- /* For the header, the completion proposal is NULL. */
- GtkSourceCompletionProposal *completion_proposal;
-
- /* For the "changed" signal emitted by the proposal.
- * When the node is freed, the signal is disconnected. */
- gulong changed_id;
-} ProposalInfo;
-
-struct _GtkSourceCompletionModelPrivate
-{
- GType column_types[GTK_SOURCE_COMPLETION_MODEL_N_COLUMNS];
-
- /* List of ProviderInfo sorted by priority in descending order. */
- GList *providers;
-
- /* List of GtkSourceCompletionProvider. If NULL, all providers are
- * visible. */
- GList *visible_providers;
-
- guint show_headers : 1;
-};
-
-static void tree_model_iface_init (gpointer g_iface, gpointer iface_data);
-
-G_DEFINE_TYPE_WITH_CODE (GtkSourceCompletionModel,
- gtk_source_completion_model,
- G_TYPE_OBJECT,
- G_ADD_PRIVATE (GtkSourceCompletionModel)
- G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
- tree_model_iface_init))
-
-/* Utility functions */
-
-static gboolean
-is_header (ProposalInfo *info)
-{
- g_assert (info != NULL);
-
- return info->completion_proposal == NULL;
-}
-
-static gboolean
-is_provider_visible (GtkSourceCompletionModel *model,
- GtkSourceCompletionProvider *provider)
-{
- if (model->priv->visible_providers == NULL)
- {
- return TRUE;
- }
-
- return g_list_find (model->priv->visible_providers, provider) != NULL;
-}
-
-static gboolean
-get_iter_from_index (GtkSourceCompletionModel *model,
- GtkTreeIter *iter,
- gint idx)
-{
- gint provider_index = 0;
- GList *l;
- ProviderInfo *info;
-
- if (idx < 0)
- {
- return FALSE;
- }
-
- /* Find the provider */
- for (l = model->priv->providers; l != NULL; l = l->next)
- {
- gint new_index;
- info = l->data;
-
- if (!info->visible)
- {
- continue;
- }
-
- new_index = provider_index + info->proposals->length;
-
- if (idx < new_index)
- {
- break;
- }
-
- provider_index = new_index;
- }
-
- if (l == NULL)
- {
- return FALSE;
- }
-
- /* Find the node inside the provider */
- iter->user_data = g_queue_peek_nth_link (info->proposals, idx - provider_index);
-
- return iter->user_data != NULL;
-}
-
-static gint
-get_provider_start_index (GtkSourceCompletionModel *model,
- ProviderInfo *info)
-{
- gint start_index = 0;
- GList *l;
-
- g_assert (info != NULL);
-
- for (l = model->priv->providers; l != NULL; l = l->next)
- {
- ProviderInfo *cur_info = l->data;
-
- if (cur_info == info)
- {
- break;
- }
-
- if (cur_info->visible)
- {
- start_index += cur_info->proposals->length;
- }
- }
-
- /* The provider must be in the list. */
- g_assert (l != NULL);
-
- return start_index;
-}
-
-static GtkTreePath *
-get_proposal_path (GtkSourceCompletionModel *model,
- GList *proposal_node)
-{
- ProposalInfo *proposal_info;
- ProviderInfo *provider_info;
- gint idx;
-
- if (proposal_node == NULL)
- {
- return NULL;
- }
-
- proposal_info = proposal_node->data;
- provider_info = proposal_info->provider_node->data;
-
- idx = get_provider_start_index (model, provider_info);
- idx += g_queue_link_index (provider_info->proposals, proposal_node);
-
- return gtk_tree_path_new_from_indices (idx, -1);
-}
-
-/* Returns the first visible provider after @provider. It can be @provider
- * itself. Returns NULL if not found. */
-static GList *
-find_next_visible_provider (GList *provider)
-{
- GList *l;
-
- for (l = provider; l != NULL; l = l->next)
- {
- ProviderInfo *info = l->data;
-
- if (info->visible)
- {
- return l;
- }
- }
-
- return NULL;
-}
-
-/* Returns the first visible provider before @provider. It can be @provider
- * itself. Returns NULL if not found. */
-static GList *
-find_previous_visible_provider (GList *provider)
-{
- GList *l;
-
- for (l = provider; l != NULL; l = l->prev)
- {
- ProviderInfo *info = l->data;
-
- if (info->visible)
- {
- return l;
- }
- }
-
- return NULL;
-}
-
-static GList *
-get_provider_node (GtkSourceCompletionModel *model,
- GtkSourceCompletionProvider *provider)
-{
- GList *l;
-
- for (l = model->priv->providers; l != NULL; l = l->next)
- {
- ProviderInfo *provider_info = l->data;
-
- if (provider_info->completion_provider == provider)
- {
- return l;
- }
- }
-
- return NULL;
-}
-
-static gboolean
-get_last_iter (GtkSourceCompletionModel *model,
- GtkTreeIter *iter)
-{
- GList *last_provider;
- ProviderInfo *provider_info;
-
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (model), FALSE);
- g_return_val_if_fail (iter != NULL, FALSE);
-
- last_provider = g_list_last (model->priv->providers);
-
- if (last_provider == NULL)
- {
- return FALSE;
- }
-
- provider_info = last_provider->data;
-
- iter->user_data = provider_info->proposals->tail;
- g_assert (iter->user_data != NULL);
-
- if (!provider_info->visible)
- {
- return gtk_source_completion_model_iter_previous (model, iter);
- }
-
- return TRUE;
-}
-
-static void
-proposal_info_free (gpointer data)
-{
- ProposalInfo *info = data;
-
- if (data == NULL)
- {
- return;
- }
-
- if (info->completion_proposal != NULL)
- {
- if (info->changed_id != 0)
- {
- g_signal_handler_disconnect (info->completion_proposal,
- info->changed_id);
- }
-
- g_object_unref (info->completion_proposal);
- }
-
- g_slice_free (ProposalInfo, data);
-}
-
-static void
-provider_info_free (gpointer data)
-{
- ProviderInfo *info = data;
-
- if (data == NULL)
- {
- return;
- }
-
- g_object_unref (info->completion_provider);
- g_queue_free_full (info->proposals, (GDestroyNotify)proposal_info_free);
- g_slice_free (ProviderInfo, data);
-}
-
-static void
-add_header (GList *provider_node)
-{
- ProviderInfo *provider_info = provider_node->data;
- ProposalInfo *header = g_slice_new0 (ProposalInfo);
-
- header->provider_node = provider_node;
-
- g_queue_push_head (provider_info->proposals, header);
-}
-
-/* Add the header, and emit the "row-inserted" signal. */
-static void
-show_header (GtkSourceCompletionModel *model,
- GList *provider_node)
-{
- ProviderInfo *provider_info = provider_node->data;
-
- add_header (provider_node);
-
- if (provider_info->visible)
- {
- GtkTreePath *path = get_proposal_path (model, provider_info->proposals->head);
- GtkTreeIter iter;
-
- iter.user_data = provider_info->proposals->head;
- gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, &iter);
-
- gtk_tree_path_free (path);
- }
-}
-
-/* Remove the header, and emit the "row-deleted" signal. */
-static void
-hide_header (GtkSourceCompletionModel *model,
- GList *provider_node)
-{
- ProviderInfo *provider_info = provider_node->data;
- ProposalInfo *proposal_info = g_queue_pop_head (provider_info->proposals);
-
- g_assert (provider_info->proposals->length > 0);
- g_assert (is_header (proposal_info));
-
- proposal_info_free (proposal_info);
-
- if (provider_info->visible)
- {
- GtkTreePath *path = get_proposal_path (model, provider_info->proposals->head);
- gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
- gtk_tree_path_free (path);
- }
-}
-
-/* Interface implementation */
-
-static GtkTreeModelFlags
-tree_model_get_flags (GtkTreeModel *tree_model)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (tree_model), 0);
-
- return GTK_TREE_MODEL_LIST_ONLY | GTK_TREE_MODEL_ITERS_PERSIST;
-}
-
-static gint
-tree_model_get_n_columns (GtkTreeModel *tree_model)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (tree_model), 0);
-
- return GTK_SOURCE_COMPLETION_MODEL_N_COLUMNS;
-}
-
-static GType
-tree_model_get_column_type (GtkTreeModel *tree_model,
- gint idx)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (tree_model), G_TYPE_INVALID);
- g_return_val_if_fail (0 <= idx && idx < GTK_SOURCE_COMPLETION_MODEL_N_COLUMNS, G_TYPE_INVALID);
-
- return GTK_SOURCE_COMPLETION_MODEL (tree_model)->priv->column_types[idx];
-}
-
-static gboolean
-tree_model_get_iter (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreePath *path)
-{
- GtkSourceCompletionModel *model;
- gint *indices;
-
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (tree_model), FALSE);
- g_return_val_if_fail (iter != NULL, FALSE);
- g_return_val_if_fail (path != NULL, FALSE);
-
- model = GTK_SOURCE_COMPLETION_MODEL (tree_model);
- indices = gtk_tree_path_get_indices (path);
-
- return get_iter_from_index (model, iter, indices[0]);
-}
-
-static GtkTreePath *
-tree_model_get_path (GtkTreeModel *tree_model,
- GtkTreeIter *iter)
-{
- GtkSourceCompletionModel *model;
-
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (tree_model), NULL);
- g_return_val_if_fail (iter != NULL, NULL);
- g_return_val_if_fail (iter->user_data != NULL, NULL);
-
- model = GTK_SOURCE_COMPLETION_MODEL (tree_model);
-
- return get_proposal_path (model, iter->user_data);
-}
-
-static void
-tree_model_get_value (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- gint column,
- GValue *value)
-{
- GList *proposal_node;
- ProposalInfo *proposal_info;
- ProviderInfo *provider_info;
- GtkSourceCompletionProposal *completion_proposal;
- GtkSourceCompletionProvider *completion_provider;
-
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (tree_model));
- g_return_if_fail (iter != NULL);
- g_return_if_fail (iter->user_data != NULL);
- g_return_if_fail (0 <= column && column < GTK_SOURCE_COMPLETION_MODEL_N_COLUMNS);
-
- proposal_node = iter->user_data;
- proposal_info = proposal_node->data;
- provider_info = proposal_info->provider_node->data;
- completion_proposal = proposal_info->completion_proposal;
- completion_provider = provider_info->completion_provider;
-
- g_value_init (value, GTK_SOURCE_COMPLETION_MODEL (tree_model)->priv->column_types[column]);
-
- switch (column)
- {
- case GTK_SOURCE_COMPLETION_MODEL_COLUMN_PROVIDER:
- g_value_set_object (value, completion_provider);
- break;
-
- case GTK_SOURCE_COMPLETION_MODEL_COLUMN_PROPOSAL:
- g_value_set_object (value, completion_proposal);
- break;
-
- case GTK_SOURCE_COMPLETION_MODEL_COLUMN_MARKUP:
- if (is_header (proposal_info))
- {
- gchar *name = gtk_source_completion_provider_get_name (completion_provider);
-
- if (name != NULL)
- {
- gchar *escaped = g_markup_escape_text (name, -1);
- gchar *markup = g_strdup_printf ("%s", escaped);
- g_value_take_string (value, markup);
-
- g_free (name);
- g_free (escaped);
- }
- else
- {
- gchar *markup = g_strdup_printf ("%s", _("Provider"));
- g_value_take_string (value, markup);
- }
- }
- else
- {
- gchar *markup = gtk_source_completion_proposal_get_markup (completion_proposal);
-
- if (markup == NULL)
- {
- gchar *label = gtk_source_completion_proposal_get_label (completion_proposal);
- markup = g_markup_escape_text (label != NULL ? label : "", -1);
- g_free (label);
- }
-
- g_value_take_string (value, markup);
- }
- break;
-
- case GTK_SOURCE_COMPLETION_MODEL_COLUMN_ICON:
- if (is_header (proposal_info))
- {
- GdkPixbuf *icon = gtk_source_completion_provider_get_icon (completion_provider);
- g_value_set_object (value, (gpointer)icon);
- }
- else
- {
- GdkPixbuf *icon = gtk_source_completion_proposal_get_icon (completion_proposal);
- g_value_set_object (value, (gpointer)icon);
- }
- break;
-
- case GTK_SOURCE_COMPLETION_MODEL_COLUMN_ICON_NAME:
- if (is_header (proposal_info))
- {
- const gchar *icon_name = gtk_source_completion_provider_get_icon_name (completion_provider);
- g_value_set_string (value, (gpointer)icon_name);
- }
- else
- {
- const gchar *icon_name = gtk_source_completion_proposal_get_icon_name (completion_proposal);
- g_value_set_string (value, (gpointer)icon_name);
- }
- break;
-
- case GTK_SOURCE_COMPLETION_MODEL_COLUMN_GICON:
- if (is_header (proposal_info))
- {
- GIcon *icon = gtk_source_completion_provider_get_gicon (completion_provider);
- g_value_set_object (value, (gpointer)icon);
- }
- else
- {
- GIcon *icon = gtk_source_completion_proposal_get_gicon (completion_proposal);
- g_value_set_object (value, (gpointer)icon);
- }
- break;
-
- case GTK_SOURCE_COMPLETION_MODEL_COLUMN_IS_HEADER:
- g_value_set_boolean (value, is_header (proposal_info));
- break;
-
- default:
- g_assert_not_reached ();
- }
-}
-
-static gboolean
-tree_model_iter_next (GtkTreeModel *tree_model,
- GtkTreeIter *iter)
-{
- ProposalInfo *proposal_info;
- GList *proposal_node;
- GList *cur_provider;
-
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (tree_model), FALSE);
- g_return_val_if_fail (iter != NULL, FALSE);
- g_return_val_if_fail (iter->user_data != NULL, FALSE);
-
- proposal_node = iter->user_data;
- proposal_info = proposal_node->data;
-
- /* Find the right provider, which must be visible */
-
- cur_provider = proposal_info->provider_node;
-
- if (proposal_node->next == NULL)
- {
- cur_provider = g_list_next (cur_provider);
- }
-
- cur_provider = find_next_visible_provider (cur_provider);
-
- if (cur_provider == NULL)
- {
- return FALSE;
- }
-
- /* Find the proposal inside the provider */
-
- if (cur_provider == proposal_info->provider_node)
- {
- iter->user_data = g_list_next (proposal_node);
- }
- else
- {
- ProviderInfo *info = cur_provider->data;
- iter->user_data = info->proposals->head;
- }
-
- g_assert (iter->user_data != NULL);
-
- return TRUE;
-}
-
-static gboolean
-tree_model_iter_children (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreeIter *parent)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (tree_model), FALSE);
- g_return_val_if_fail (iter != NULL, FALSE);
- g_return_val_if_fail (parent == NULL || parent->user_data != NULL, FALSE);
-
- if (parent != NULL)
- {
- return FALSE;
- }
- else
- {
- return get_iter_from_index (GTK_SOURCE_COMPLETION_MODEL (tree_model), iter, 0);
- }
-}
-
-static gboolean
-tree_model_iter_has_child (GtkTreeModel *tree_model,
- GtkTreeIter *iter)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (tree_model), FALSE);
- g_return_val_if_fail (iter != NULL, FALSE);
- g_return_val_if_fail (iter->user_data != NULL, FALSE);
-
- return FALSE;
-}
-
-static gint
-tree_model_iter_n_children (GtkTreeModel *tree_model,
- GtkTreeIter *iter)
-{
- GtkSourceCompletionModel *model;
- GList *l;
- gint num_nodes = 0;
-
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (tree_model), 0);
- g_return_val_if_fail (iter == NULL || iter->user_data != NULL, 0);
-
- if (iter != NULL)
- {
- return 0;
- }
-
- model = GTK_SOURCE_COMPLETION_MODEL (tree_model);
-
- for (l = model->priv->providers; l != NULL; l = l->next)
- {
- ProviderInfo *info = l->data;
-
- if (info->visible)
- {
- num_nodes += info->proposals->length;
- }
- }
-
- return num_nodes;
-}
-
-static gboolean
-tree_model_iter_nth_child (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreeIter *parent,
- gint child_num)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (tree_model), FALSE);
- g_return_val_if_fail (iter != NULL, FALSE);
- g_return_val_if_fail (parent == NULL || parent->user_data != NULL, FALSE);
-
- if (parent != NULL)
- {
- return FALSE;
- }
- else
- {
- return get_iter_from_index (GTK_SOURCE_COMPLETION_MODEL (tree_model),
- iter,
- child_num);
- }
-}
-
-static gboolean
-tree_model_iter_parent (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreeIter *child)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (tree_model), FALSE);
- g_return_val_if_fail (iter != NULL, FALSE);
- g_return_val_if_fail (child != NULL, FALSE);
-
- iter->user_data = NULL;
- return FALSE;
-}
-
-static void
-tree_model_iface_init (gpointer g_iface,
- gpointer iface_data)
-{
- GtkTreeModelIface *iface = g_iface;
-
- iface->get_flags = tree_model_get_flags;
- iface->get_n_columns = tree_model_get_n_columns;
- iface->get_column_type = tree_model_get_column_type;
- iface->get_iter = tree_model_get_iter;
- iface->get_path = tree_model_get_path;
- iface->get_value = tree_model_get_value;
- iface->iter_next = tree_model_iter_next;
- iface->iter_children = tree_model_iter_children;
- iface->iter_has_child = tree_model_iter_has_child;
- iface->iter_n_children = tree_model_iter_n_children;
- iface->iter_nth_child = tree_model_iter_nth_child;
- iface->iter_parent = tree_model_iter_parent;
-}
-
-/* Construction and destruction */
-
-static void
-gtk_source_completion_model_dispose (GObject *object)
-{
- GtkSourceCompletionModel *model = GTK_SOURCE_COMPLETION_MODEL (object);
-
- g_list_free_full (model->priv->providers, (GDestroyNotify)provider_info_free);
- model->priv->providers = NULL;
-
- g_list_free_full (model->priv->visible_providers, g_object_unref);
- model->priv->visible_providers = NULL;
-
- G_OBJECT_CLASS (gtk_source_completion_model_parent_class)->dispose (object);
-}
-
-static void
-gtk_source_completion_model_class_init (GtkSourceCompletionModelClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->dispose = gtk_source_completion_model_dispose;
-}
-
-static void
-gtk_source_completion_model_init (GtkSourceCompletionModel *self)
-{
- self->priv = gtk_source_completion_model_get_instance_private (self);
-
- self->priv->column_types[GTK_SOURCE_COMPLETION_MODEL_COLUMN_MARKUP] = G_TYPE_STRING;
- self->priv->column_types[GTK_SOURCE_COMPLETION_MODEL_COLUMN_ICON] = GDK_TYPE_PIXBUF;
- self->priv->column_types[GTK_SOURCE_COMPLETION_MODEL_COLUMN_ICON_NAME] = G_TYPE_STRING;
- self->priv->column_types[GTK_SOURCE_COMPLETION_MODEL_COLUMN_GICON] = G_TYPE_ICON;
- self->priv->column_types[GTK_SOURCE_COMPLETION_MODEL_COLUMN_PROPOSAL] = G_TYPE_OBJECT;
- self->priv->column_types[GTK_SOURCE_COMPLETION_MODEL_COLUMN_PROVIDER] = G_TYPE_OBJECT;
- self->priv->column_types[GTK_SOURCE_COMPLETION_MODEL_COLUMN_IS_HEADER] = G_TYPE_BOOLEAN;
-
- self->priv->show_headers = 1;
- self->priv->providers = NULL;
- self->priv->visible_providers = NULL;
-}
-
-/* Population: add proposals */
-
-/* Returns the newly-created provider node */
-static GList *
-create_provider_info (GtkSourceCompletionModel *model,
- GtkSourceCompletionProvider *provider)
-{
- ProviderInfo *info;
- gint priority;
- GList *l;
- GList *provider_node;
-
- /* Create the structure */
-
- info = g_slice_new0 (ProviderInfo);
- info->model = model;
- info->completion_provider = g_object_ref (provider);
- info->proposals = g_queue_new ();
- info->visible = is_provider_visible (model, provider);
-
- /* Insert the ProviderInfo in the list */
-
- priority = gtk_source_completion_provider_get_priority (provider);
-
- for (l = model->priv->providers; l != NULL; l = l->next)
- {
- ProviderInfo *cur_info = l->data;
- gint cur_priority = gtk_source_completion_provider_get_priority (cur_info->completion_provider);
-
- if (cur_priority < priority)
- {
- break;
- }
- }
-
- model->priv->providers = g_list_insert_before (model->priv->providers, l, info);
-
- provider_node = g_list_find (model->priv->providers, info);
-
- /* Insert the header if needed */
-
- if (model->priv->show_headers)
- {
- add_header (provider_node);
- }
-
- return provider_node;
-}
-
-static void
-on_proposal_changed (GtkSourceCompletionProposal *proposal,
- GList *proposal_node)
-{
- ProposalInfo *proposal_info = proposal_node->data;
- ProviderInfo *provider_info = proposal_info->provider_node->data;
-
- if (provider_info->visible)
- {
- GtkTreeIter iter;
- GtkTreePath *path;
-
- iter.user_data = proposal_node;
- path = get_proposal_path (provider_info->model, proposal_node);
-
- gtk_tree_model_row_changed (GTK_TREE_MODEL (provider_info->model),
- path,
- &iter);
-
- gtk_tree_path_free (path);
- }
-}
-
-static void
-add_proposal (GtkSourceCompletionProposal *proposal,
- GList *provider_node)
-{
- ProviderInfo *provider_info = provider_node->data;
- ProposalInfo *proposal_info = g_slice_new0 (ProposalInfo);
-
- proposal_info->provider_node = provider_node;
- proposal_info->completion_proposal = g_object_ref (proposal);
-
- g_queue_push_tail (provider_info->proposals, proposal_info);
-
- proposal_info->changed_id = g_signal_connect (proposal,
- "changed",
- G_CALLBACK (on_proposal_changed),
- provider_info->proposals->tail);
-}
-
-void
-gtk_source_completion_model_add_proposals (GtkSourceCompletionModel *model,
- GtkSourceCompletionProvider *provider,
- GList *proposals)
-{
- GList *provider_node = NULL;
-
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (model));
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION_PROVIDER (provider));
-
- if (proposals == NULL)
- {
- return;
- }
-
- provider_node = get_provider_node (model, provider);
-
- if (provider_node == NULL)
- {
- provider_node = create_provider_info (model, provider);
- }
-
- g_list_foreach (proposals, (GFunc)add_proposal, provider_node);
-}
-
-/* Other public functions */
-
-static gpointer
-provider_copy_func (gconstpointer src,
- gpointer data)
-{
- return g_object_ref ((gpointer) src);
-}
-
-void
-gtk_source_completion_model_set_visible_providers (GtkSourceCompletionModel *model,
- GList *providers)
-{
- GList *l;
-
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (model));
-
- for (l = providers; l != NULL; l = l->next)
- {
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION_PROVIDER (l->data));
- }
-
- g_list_free_full (model->priv->visible_providers, g_object_unref);
-
- model->priv->visible_providers = g_list_copy_deep (providers,
- provider_copy_func,
- NULL);
-
- for (l = model->priv->providers; l != NULL; l = l->next)
- {
- ProviderInfo *provider_info = l->data;
- provider_info->visible = is_provider_visible (model, provider_info->completion_provider);
- }
-}
-
-GList *
-gtk_source_completion_model_get_visible_providers (GtkSourceCompletionModel *model)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (model), NULL);
-
- return model->priv->visible_providers;
-}
-
-/* If @only_visible is %TRUE, only the visible providers are taken into account. */
-gboolean
-gtk_source_completion_model_is_empty (GtkSourceCompletionModel *model,
- gboolean only_visible)
-{
- GList *l;
-
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (model), TRUE);
-
- for (l = model->priv->providers; l != NULL; l = l->next)
- {
- ProviderInfo *info = l->data;
-
- if (only_visible && !info->visible)
- {
- continue;
- }
-
- /* A provider can not be empty */
- return FALSE;
- }
-
- return TRUE;
-}
-
-void
-gtk_source_completion_model_set_show_headers (GtkSourceCompletionModel *model,
- gboolean show_headers)
-{
- GList *l;
-
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (model));
-
- if (model->priv->show_headers == show_headers)
- {
- return;
- }
-
- model->priv->show_headers = show_headers;
-
- for (l = model->priv->providers; l != NULL; l = l->next)
- {
- if (show_headers)
- {
- show_header (model, l);
- }
- else
- {
- hide_header (model, l);
- }
- }
-}
-
-gboolean
-gtk_source_completion_model_iter_is_header (GtkSourceCompletionModel *model,
- GtkTreeIter *iter)
-{
- GList *proposal_node;
- ProposalInfo *proposal_info;
-
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (model), FALSE);
- g_return_val_if_fail (iter != NULL, FALSE);
- g_return_val_if_fail (iter->user_data != NULL, FALSE);
-
- proposal_node = iter->user_data;
- proposal_info = proposal_node->data;
-
- return is_header (proposal_info);
-}
-
-gboolean
-gtk_source_completion_model_iter_previous (GtkSourceCompletionModel *model,
- GtkTreeIter *iter)
-{
- /* This function is the symmetry of tree_model_iter_next(). */
-
- ProposalInfo *proposal_info;
- GList *proposal_node;
- GList *cur_provider;
-
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (model), FALSE);
- g_return_val_if_fail (iter != NULL, FALSE);
- g_return_val_if_fail (iter->user_data != NULL, FALSE);
-
- proposal_node = iter->user_data;
- proposal_info = proposal_node->data;
-
- /* Find the right provider, which must be visible */
-
- cur_provider = proposal_info->provider_node;
-
- if (proposal_node->prev == NULL)
- {
- cur_provider = g_list_previous (cur_provider);
- }
-
- cur_provider = find_previous_visible_provider (cur_provider);
-
- if (cur_provider == NULL)
- {
- return FALSE;
- }
-
- /* Find the proposal inside the provider */
-
- if (cur_provider == proposal_info->provider_node)
- {
- iter->user_data = g_list_previous (proposal_node);
- }
- else
- {
- ProviderInfo *info = cur_provider->data;
- iter->user_data = info->proposals->tail;
- }
-
- g_assert (iter->user_data != NULL);
-
- return TRUE;
-}
-
-/* Get all the providers (visible and hidden), sorted by priority in descending
- * order (the highest priority first).
- * Free the return value with g_list_free().
- */
-GList *
-gtk_source_completion_model_get_providers (GtkSourceCompletionModel *model)
-{
- GList *l;
- GList *ret = NULL;
-
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (model), NULL);
-
- for (l = model->priv->providers; l != NULL; l = l->next)
- {
- ProviderInfo *info = l->data;
- ret = g_list_prepend (ret, info->completion_provider);
- }
-
- return g_list_reverse (ret);
-}
-
-/* Get the first proposal. Headers are skipped.
- * Returns TRUE on success.
- */
-gboolean
-gtk_source_completion_model_first_proposal (GtkSourceCompletionModel *model,
- GtkTreeIter *iter)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (model), FALSE);
- g_return_val_if_fail (iter != NULL, FALSE);
-
- if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), iter))
- {
- return FALSE;
- }
-
- while (gtk_source_completion_model_iter_is_header (model, iter))
- {
- if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (model), iter))
- {
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-/* Get the last proposal. Headers are skipped.
- * Returns TRUE on success.
- */
-gboolean
-gtk_source_completion_model_last_proposal (GtkSourceCompletionModel *model,
- GtkTreeIter *iter)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (model), FALSE);
- g_return_val_if_fail (iter != NULL, FALSE);
-
- if (!get_last_iter (model, iter))
- {
- return FALSE;
- }
-
- while (gtk_source_completion_model_iter_is_header (model, iter))
- {
- if (!gtk_source_completion_model_iter_previous (model, iter))
- {
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-/* Get the next proposal. Headers are skipped.
- * Returns TRUE on success.
- */
-gboolean
-gtk_source_completion_model_next_proposal (GtkSourceCompletionModel *model,
- GtkTreeIter *iter)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (model), FALSE);
- g_return_val_if_fail (iter != NULL && iter->user_data != NULL, FALSE);
-
- do
- {
- if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (model), iter))
- {
- return FALSE;
- }
- } while (gtk_source_completion_model_iter_is_header (model, iter));
-
- return TRUE;
-}
-
-/* Get the previous proposal. Headers are skipped.
- * Returns TRUE on success.
- */
-gboolean
-gtk_source_completion_model_previous_proposal (GtkSourceCompletionModel *model,
- GtkTreeIter *iter)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (model), FALSE);
- g_return_val_if_fail (iter != NULL && iter->user_data != NULL, FALSE);
-
- do
- {
- if (!gtk_source_completion_model_iter_previous (model, iter))
- {
- return FALSE;
- }
- } while (gtk_source_completion_model_iter_is_header (model, iter));
-
- return TRUE;
-}
-
-static gboolean
-proposal_has_info (GtkSourceCompletionProvider *provider,
- GtkSourceCompletionProposal *proposal)
-{
- gchar *info;
-
- if (gtk_source_completion_provider_get_info_widget (provider, proposal) != NULL)
- {
- return TRUE;
- }
-
- info = gtk_source_completion_proposal_get_info (proposal);
-
- if (info != NULL)
- {
- g_free (info);
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-provider_has_info (ProviderInfo *provider_info)
-{
- GList *l;
-
- for (l = provider_info->proposals->head; l != NULL; l = l->next)
- {
- ProposalInfo *proposal_info = l->data;
-
- if (proposal_info->completion_proposal == NULL)
- {
- continue;
- }
-
- if (proposal_has_info (provider_info->completion_provider,
- proposal_info->completion_proposal))
- {
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-/* Returns whether the model contains one or more proposal with extra
- * information. If the function returns %FALSE, the "Details" button is useless.
- */
-gboolean
-gtk_source_completion_model_has_info (GtkSourceCompletionModel *model)
-{
- GList *l;
-
- for (l = model->priv->providers; l != NULL; l = l->next)
- {
- ProviderInfo *provider_info = l->data;
-
- if (provider_has_info (provider_info))
- {
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-gboolean
-gtk_source_completion_model_iter_equal (GtkSourceCompletionModel *model,
- GtkTreeIter *iter1,
- GtkTreeIter *iter2)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (model), FALSE);
- g_return_val_if_fail (iter1 != NULL, FALSE);
- g_return_val_if_fail (iter2 != NULL, FALSE);
-
- return iter1->user_data == iter2->user_data;
-}
-
-GtkSourceCompletionModel*
-gtk_source_completion_model_new (void)
-{
- return g_object_new (GTK_SOURCE_TYPE_COMPLETION_MODEL, NULL);
-}
diff --git a/gtksourceview/gtksourcecompletionmodel.h b/gtksourceview/gtksourcecompletionmodel.h
deleted file mode 100644
index 85004f00dba5c7e8eacd446cf6d49f4ccefcc936..0000000000000000000000000000000000000000
--- a/gtksourceview/gtksourcecompletionmodel.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
- *
- * This file is part of GtkSourceView
- *
- * Copyright (C) 2009 - Jesse van den Kieboom
- *
- * GtkSourceView is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * GtkSourceView 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, see .
- */
-
-#ifndef GTK_SOURCE_COMPLETION_MODEL_H
-#define GTK_SOURCE_COMPLETION_MODEL_H
-
-#include
-#include "gtksourcetypes.h"
-#include "gtksourcetypes-private.h"
-
-G_BEGIN_DECLS
-
-#define GTK_SOURCE_TYPE_COMPLETION_MODEL (gtk_source_completion_model_get_type ())
-#define GTK_SOURCE_COMPLETION_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_SOURCE_TYPE_COMPLETION_MODEL, GtkSourceCompletionModel))
-#define GTK_SOURCE_COMPLETION_MODEL_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_SOURCE_TYPE_COMPLETION_MODEL, GtkSourceCompletionModel const))
-#define GTK_SOURCE_COMPLETION_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_SOURCE_TYPE_COMPLETION_MODEL, GtkSourceCompletionModelClass))
-#define GTK_SOURCE_IS_COMPLETION_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_SOURCE_TYPE_COMPLETION_MODEL))
-#define GTK_SOURCE_IS_COMPLETION_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_SOURCE_TYPE_COMPLETION_MODEL))
-#define GTK_SOURCE_COMPLETION_MODEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_SOURCE_TYPE_COMPLETION_MODEL, GtkSourceCompletionModelClass))
-
-typedef struct _GtkSourceCompletionModelClass GtkSourceCompletionModelClass;
-typedef struct _GtkSourceCompletionModelPrivate GtkSourceCompletionModelPrivate;
-
-struct _GtkSourceCompletionModel {
- GObject parent;
-
- GtkSourceCompletionModelPrivate *priv;
-};
-
-struct _GtkSourceCompletionModelClass {
- GObjectClass parent_class;
-
- void (*providers_changed) (GtkSourceCompletionModel *model);
-};
-
-enum
-{
- GTK_SOURCE_COMPLETION_MODEL_COLUMN_MARKUP,
- GTK_SOURCE_COMPLETION_MODEL_COLUMN_ICON,
- GTK_SOURCE_COMPLETION_MODEL_COLUMN_ICON_NAME,
- GTK_SOURCE_COMPLETION_MODEL_COLUMN_GICON,
- GTK_SOURCE_COMPLETION_MODEL_COLUMN_PROPOSAL,
- GTK_SOURCE_COMPLETION_MODEL_COLUMN_PROVIDER,
- GTK_SOURCE_COMPLETION_MODEL_COLUMN_IS_HEADER,
- GTK_SOURCE_COMPLETION_MODEL_N_COLUMNS
-};
-
-GTK_SOURCE_INTERNAL
-GType gtk_source_completion_model_get_type (void) G_GNUC_CONST;
-
-GTK_SOURCE_INTERNAL
-GtkSourceCompletionModel *
- gtk_source_completion_model_new (void);
-
-GTK_SOURCE_INTERNAL
-void gtk_source_completion_model_add_proposals (GtkSourceCompletionModel *model,
- GtkSourceCompletionProvider *provider,
- GList *proposals);
-
-GTK_SOURCE_INTERNAL
-gboolean gtk_source_completion_model_is_empty (GtkSourceCompletionModel *model,
- gboolean only_visible);
-
-GTK_SOURCE_INTERNAL
-void gtk_source_completion_model_set_visible_providers (GtkSourceCompletionModel *model,
- GList *providers);
-
-GTK_SOURCE_INTERNAL
-GList *gtk_source_completion_model_get_visible_providers (GtkSourceCompletionModel *model);
-
-GTK_SOURCE_INTERNAL
-GList *gtk_source_completion_model_get_providers (GtkSourceCompletionModel *model);
-
-GTK_SOURCE_INTERNAL
-void gtk_source_completion_model_set_show_headers (GtkSourceCompletionModel *model,
- gboolean show_headers);
-
-GTK_SOURCE_INTERNAL
-gboolean gtk_source_completion_model_iter_is_header (GtkSourceCompletionModel *model,
- GtkTreeIter *iter);
-
-GTK_SOURCE_INTERNAL
-gboolean gtk_source_completion_model_iter_previous (GtkSourceCompletionModel *model,
- GtkTreeIter *iter);
-
-GTK_SOURCE_INTERNAL
-gboolean gtk_source_completion_model_first_proposal (GtkSourceCompletionModel *model,
- GtkTreeIter *iter);
-
-GTK_SOURCE_INTERNAL
-gboolean gtk_source_completion_model_last_proposal (GtkSourceCompletionModel *model,
- GtkTreeIter *iter);
-
-GTK_SOURCE_INTERNAL
-gboolean gtk_source_completion_model_next_proposal (GtkSourceCompletionModel *model,
- GtkTreeIter *iter);
-
-GTK_SOURCE_INTERNAL
-gboolean gtk_source_completion_model_previous_proposal (GtkSourceCompletionModel *model,
- GtkTreeIter *iter);
-
-GTK_SOURCE_INTERNAL
-gboolean gtk_source_completion_model_has_info (GtkSourceCompletionModel *model);
-
-GTK_SOURCE_INTERNAL
-gboolean gtk_source_completion_model_iter_equal (GtkSourceCompletionModel *model,
- GtkTreeIter *iter1,
- GtkTreeIter *iter2);
-
-G_END_DECLS
-
-#endif /* GTK_SOURCE_COMPLETION_MODEL_H */
diff --git a/gtksourceview/gtksourcecompletionproposal.c b/gtksourceview/gtksourcecompletionproposal.c
index 54417c7b02ce34c7994cefbeb02ebda84a272fa6..b66e2f83d74df763d01c41bcc0b772f78a19a50d 100644
--- a/gtksourceview/gtksourcecompletionproposal.c
+++ b/gtksourceview/gtksourcecompletionproposal.c
@@ -1,9 +1,7 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- */
/*
* This file is part of GtkSourceView
*
- * Copyright (C) 2007 - 2009 Jesús Barbero Rodríguez
- * Copyright (C) 2009 - Jesse van den Kieboom
+ * Copyright 2020 Christian Hergert
*
* GtkSourceView is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -17,323 +15,19 @@
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, see .
- */
-
-#ifdef HAVE_CONFIG_H
-#include
-#endif
-
-#include "gtksourcecompletionproposal.h"
-
-/**
- * SECTION:completionproposal
- * @title: GtkSourceCompletionProposal
- * @short_description: Completion proposal interface
- *
- * The proposal interface represents a completion item in the completion window.
- * It provides information on how to display the completion item and what action
- * should be taken when the completion item is activated.
*
- * The proposal is displayed in the completion window with a label and
- * optionally an icon.
- * The label may be specified using plain text or markup by implementing
- * the corresponding get function. Only one of those get functions
- * should return a value different from %NULL.
- * The icon may be specified as a #GdkPixbuf, as an icon name or as a #GIcon by
- * implementing the corresponding get function. At most one of those get functions
- * should return a value different from %NULL, if they all return %NULL no icon
- * will be used.
+ * SPDX-License-Identifier: LGPL-2.1-or-later
*/
-enum
-{
- CHANGED,
- N_SIGNALS
-};
-
-static guint signals[N_SIGNALS];
-
-typedef GtkSourceCompletionProposalIface GtkSourceCompletionProposalInterface;
-
-G_DEFINE_INTERFACE (GtkSourceCompletionProposal, gtk_source_completion_proposal, G_TYPE_OBJECT)
-
-static gchar *
-gtk_source_completion_proposal_get_label_default (GtkSourceCompletionProposal *proposal)
-{
- return NULL;
-}
-
-static gchar *
-gtk_source_completion_proposal_get_markup_default (GtkSourceCompletionProposal *proposal)
-{
- return NULL;
-}
-
-static gchar *
-gtk_source_completion_proposal_get_text_default (GtkSourceCompletionProposal *proposal)
-{
- return NULL;
-}
-
-static GdkPixbuf *
-gtk_source_completion_proposal_get_icon_default (GtkSourceCompletionProposal *proposal)
-{
- return NULL;
-}
-static const gchar *
-gtk_source_completion_proposal_get_icon_name_default (GtkSourceCompletionProposal *proposal)
-{
- return NULL;
-}
-static GIcon *
-gtk_source_completion_proposal_get_gicon_default (GtkSourceCompletionProposal *proposal)
-{
- return NULL;
-}
+#include "config.h"
-static gchar *
-gtk_source_completion_proposal_get_info_default (GtkSourceCompletionProposal *proposal)
-{
- return NULL;
-}
-
-static guint
-gtk_source_completion_proposal_hash_default (GtkSourceCompletionProposal *proposal)
-{
- return g_direct_hash (proposal);
-}
+#include "gtksourcecompletionproposal.h"
-static gboolean
-gtk_source_completion_proposal_equal_default (GtkSourceCompletionProposal *proposal,
- GtkSourceCompletionProposal *other)
-{
- return g_direct_equal (proposal, other);
-}
+G_DEFINE_INTERFACE (GtkSourceCompletionProposal, gtk_source_completion_proposal, G_TYPE_OBJECT)
static void
-gtk_source_completion_proposal_default_init (GtkSourceCompletionProposalIface *iface)
-{
- static gboolean initialized = FALSE;
-
- iface->get_label = gtk_source_completion_proposal_get_label_default;
- iface->get_markup = gtk_source_completion_proposal_get_markup_default;
- iface->get_text = gtk_source_completion_proposal_get_text_default;
- iface->get_icon = gtk_source_completion_proposal_get_icon_default;
- iface->get_icon_name = gtk_source_completion_proposal_get_icon_name_default;
- iface->get_gicon = gtk_source_completion_proposal_get_gicon_default;
- iface->get_info = gtk_source_completion_proposal_get_info_default;
- iface->hash = gtk_source_completion_proposal_hash_default;
- iface->equal = gtk_source_completion_proposal_equal_default;
-
- if (!initialized)
- {
- /**
- * GtkSourceCompletionProposal::changed:
- * @proposal: The #GtkSourceCompletionProposal
- *
- * Emitted when the proposal has changed. The completion popup
- * will react to this by updating the shown information.
- *
- */
- signals[CHANGED] =
- g_signal_new ("changed",
- G_TYPE_FROM_INTERFACE (iface),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (GtkSourceCompletionProposalIface, changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
- g_signal_set_va_marshaller (signals[CHANGED],
- G_TYPE_FROM_INTERFACE (iface),
- g_cclosure_marshal_VOID__VOIDv);
-
- initialized = TRUE;
- }
-}
-
-/**
- * gtk_source_completion_proposal_get_label:
- * @proposal: a #GtkSourceCompletionProposal.
- *
- * Gets the label of @proposal. The label is shown in the list of proposals as
- * plain text. If you need any markup (such as bold or italic text), you have
- * to implement gtk_source_completion_proposal_get_markup(). The returned string
- * must be freed with g_free().
- *
- * Returns: a new string containing the label of @proposal.
- */
-gchar *
-gtk_source_completion_proposal_get_label (GtkSourceCompletionProposal *proposal)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_PROPOSAL (proposal), NULL);
-
- return GTK_SOURCE_COMPLETION_PROPOSAL_GET_INTERFACE (proposal)->get_label (proposal);
-}
-
-/**
- * gtk_source_completion_proposal_get_markup:
- * @proposal: a #GtkSourceCompletionProposal.
- *
- * Gets the label of @proposal with markup. The label is shown in the list of
- * proposals and may contain markup. This will be used instead of
- * gtk_source_completion_proposal_get_label() if implemented. The returned string
- * must be freed with g_free().
- *
- * Returns: a new string containing the label of @proposal with markup.
- */
-gchar *
-gtk_source_completion_proposal_get_markup (GtkSourceCompletionProposal *proposal)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_PROPOSAL (proposal), NULL);
-
- return GTK_SOURCE_COMPLETION_PROPOSAL_GET_INTERFACE (proposal)->get_markup (proposal);
-}
-
-/**
- * gtk_source_completion_proposal_get_text:
- * @proposal: a #GtkSourceCompletionProposal.
- *
- * Gets the text of @proposal. The text that is inserted into
- * the text buffer when the proposal is activated by the default activation.
- * You are free to implement a custom activation handler in the provider and
- * not implement this function. For more information, see
- * gtk_source_completion_provider_activate_proposal(). The returned string must
- * be freed with g_free().
- *
- * Returns: a new string containing the text of @proposal.
- */
-gchar *
-gtk_source_completion_proposal_get_text (GtkSourceCompletionProposal *proposal)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_PROPOSAL (proposal), NULL);
-
- return GTK_SOURCE_COMPLETION_PROPOSAL_GET_INTERFACE (proposal)->get_text (proposal);
-}
-
-/**
- * gtk_source_completion_proposal_get_icon:
- * @proposal: a #GtkSourceCompletionProposal.
- *
- * Gets the #GdkPixbuf for the icon of @proposal.
- *
- * Returns: (nullable) (transfer none): A #GdkPixbuf with the icon of @proposal.
- */
-GdkPixbuf *
-gtk_source_completion_proposal_get_icon (GtkSourceCompletionProposal *proposal)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_PROPOSAL (proposal), NULL);
-
- return GTK_SOURCE_COMPLETION_PROPOSAL_GET_INTERFACE (proposal)->get_icon (proposal);
-}
-
-/**
- * gtk_source_completion_proposal_get_icon_name:
- * @proposal: a #GtkSourceCompletionProposal.
- *
- * Gets the icon name of @proposal.
- *
- * Returns: (nullable) (transfer none): The icon name of @proposal.
- *
- * Since: 3.18
- */
-const gchar *
-gtk_source_completion_proposal_get_icon_name (GtkSourceCompletionProposal *proposal)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_PROPOSAL (proposal), NULL);
-
- return GTK_SOURCE_COMPLETION_PROPOSAL_GET_INTERFACE (proposal)->get_icon_name (proposal);
-}
-
-/**
- * gtk_source_completion_proposal_get_gicon:
- * @proposal: a #GtkSourceCompletionProposal.
- *
- * Gets the #GIcon for the icon of @proposal.
- *
- * Returns: (nullable) (transfer none): A #GIcon with the icon of @proposal.
- *
- * Since: 3.18
- */
-GIcon *
-gtk_source_completion_proposal_get_gicon (GtkSourceCompletionProposal *proposal)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_PROPOSAL (proposal), NULL);
-
- return GTK_SOURCE_COMPLETION_PROPOSAL_GET_INTERFACE (proposal)->get_gicon (proposal);
-}
-
-/**
- * gtk_source_completion_proposal_get_info:
- * @proposal: a #GtkSourceCompletionProposal.
- *
- * Gets extra information associated to the proposal. This information will be
- * used to present the user with extra, detailed information about the
- * selected proposal. The returned string must be freed with g_free().
- *
- * Returns: (nullable) (transfer full): a newly-allocated string containing
- * extra information of @proposal or %NULL if no extra information is associated
- * to @proposal.
- */
-gchar *
-gtk_source_completion_proposal_get_info (GtkSourceCompletionProposal *proposal)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_PROPOSAL (proposal), NULL);
-
- return GTK_SOURCE_COMPLETION_PROPOSAL_GET_INTERFACE (proposal)->get_info (proposal);
-}
-
-/**
- * gtk_source_completion_proposal_hash:
- * @proposal: a #GtkSourceCompletionProposal.
- *
- * Get the hash value of @proposal. This is used to (together with
- * gtk_source_completion_proposal_equal()) to match proposals in the completion
- * model. By default, it uses a direct hash (g_direct_hash()).
- *
- * Returns: The hash value of @proposal.
- */
-guint
-gtk_source_completion_proposal_hash (GtkSourceCompletionProposal *proposal)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_PROPOSAL (proposal), 0);
-
- return GTK_SOURCE_COMPLETION_PROPOSAL_GET_INTERFACE (proposal)->hash (proposal);
-}
-
-/**
- * gtk_source_completion_proposal_equal:
- * @proposal: a #GtkSourceCompletionProposal.
- * @other: a #GtkSourceCompletionProposal.
- *
- * Get whether two proposal objects are the same. This is used to (together
- * with gtk_source_completion_proposal_hash()) to match proposals in the
- * completion model. By default, it uses direct equality (g_direct_equal()).
- *
- * Returns: %TRUE if @proposal and @object are the same proposal
- */
-gboolean
-gtk_source_completion_proposal_equal (GtkSourceCompletionProposal *proposal,
- GtkSourceCompletionProposal *other)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_PROPOSAL (proposal), FALSE);
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_PROPOSAL (other), FALSE);
-
- return GTK_SOURCE_COMPLETION_PROPOSAL_GET_INTERFACE (proposal)->equal (proposal, other);
-}
-
-/**
- * gtk_source_completion_proposal_changed:
- * @proposal: a #GtkSourceCompletionProposal.
- *
- * Emits the "changed" signal on @proposal. This should be called by
- * implementations whenever the name, icon or info of the proposal has
- * changed.
- */
-void
-gtk_source_completion_proposal_changed (GtkSourceCompletionProposal *proposal)
+gtk_source_completion_proposal_default_init (GtkSourceCompletionProposalInterface *iface)
{
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION_PROPOSAL (proposal));
- g_signal_emit (proposal, signals[CHANGED], 0);
}
diff --git a/gtksourceview/gtksourcecompletionproposal.h b/gtksourceview/gtksourcecompletionproposal.h
index 82858798d9480724f692557459ac0b88fcd7fa34..723f80120eb80cff0858ba9facd5a908051faf98 100644
--- a/gtksourceview/gtksourcecompletionproposal.h
+++ b/gtksourceview/gtksourcecompletionproposal.h
@@ -1,9 +1,7 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
- *
+/*
* This file is part of GtkSourceView
*
- * Copyright (C) 2007 - 2009 Jesús Barbero Rodríguez
- * Copyright (C) 2009 - Jesse van den Kieboom
+ * Copyright 2020 Christian Hergert
*
* GtkSourceView is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -17,110 +15,26 @@
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, see .
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
*/
-#ifndef GTK_SOURCE_COMPLETION_PROPOSAL_H
-#define GTK_SOURCE_COMPLETION_PROPOSAL_H
-
-#if !defined (GTK_SOURCE_H_INSIDE) && !defined (GTK_SOURCE_COMPILATION)
-#error "Only can be included directly."
-#endif
+#pragma once
#include
-#include
-#include
+
+#include "gtksourcetypes.h"
G_BEGIN_DECLS
-#define GTK_SOURCE_TYPE_COMPLETION_PROPOSAL (gtk_source_completion_proposal_get_type ())
-#define GTK_SOURCE_COMPLETION_PROPOSAL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_SOURCE_TYPE_COMPLETION_PROPOSAL, GtkSourceCompletionProposal))
-#define GTK_SOURCE_IS_COMPLETION_PROPOSAL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_SOURCE_TYPE_COMPLETION_PROPOSAL))
-#define GTK_SOURCE_COMPLETION_PROPOSAL_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GTK_SOURCE_TYPE_COMPLETION_PROPOSAL, GtkSourceCompletionProposalIface))
+#define GTK_SOURCE_TYPE_COMPLETION_PROPOSAL (gtk_source_completion_proposal_get_type())
-typedef struct _GtkSourceCompletionProposalIface GtkSourceCompletionProposalIface;
+GTK_SOURCE_AVAILABLE_IN_5_0
+G_DECLARE_INTERFACE (GtkSourceCompletionProposal, gtk_source_completion_proposal, GTK_SOURCE, COMPLETION_PROPOSAL, GObject)
-/**
- * GtkSourceCompletionProposalIface:
- * @parent: The parent interface.
- * @get_label: The virtual function pointer for gtk_source_completion_proposal_get_label().
- * By default, %NULL is returned.
- * @get_markup: The virtual function pointer for gtk_source_completion_proposal_get_markup().
- * By default, %NULL is returned.
- * @get_text: The virtual function pointer for gtk_source_completion_proposal_get_text().
- * By default, %NULL is returned.
- * @get_icon: The virtual function pointer for gtk_source_completion_proposal_get_icon().
- * By default, %NULL is returned.
- * @get_icon_name: The virtual function pointer for gtk_source_completion_proposal_get_icon_name().
- * By default, %NULL is returned.
- * @get_gicon: The virtual function pointer for gtk_source_completion_proposal_get_gicon().
- * By default, %NULL is returned.
- * @get_info: The virtual function pointer for gtk_source_completion_proposal_get_info().
- * By default, %NULL is returned.
- * @hash: The virtual function pointer for gtk_source_completion_proposal_hash().
- * By default, it uses a direct hash (g_direct_hash()).
- * @equal: The virtual function pointer for gtk_source_completion_proposal_equal().
- * By default, it uses direct equality (g_direct_equal()).
- * @changed: The function pointer for the #GtkSourceCompletionProposal::changed signal.
- *
- * The virtual function table for #GtkSourceCompletionProposal.
- */
-struct _GtkSourceCompletionProposalIface
+struct _GtkSourceCompletionProposalInterface
{
- GTypeInterface parent;
-
- /* Interface functions */
- gchar *(*get_label) (GtkSourceCompletionProposal *proposal);
- gchar *(*get_markup) (GtkSourceCompletionProposal *proposal);
- gchar *(*get_text) (GtkSourceCompletionProposal *proposal);
-
- GdkPixbuf *(*get_icon) (GtkSourceCompletionProposal *proposal);
- const gchar *(*get_icon_name) (GtkSourceCompletionProposal *proposal);
- GIcon *(*get_gicon) (GtkSourceCompletionProposal *proposal);
-
- gchar *(*get_info) (GtkSourceCompletionProposal *proposal);
-
- guint (*hash) (GtkSourceCompletionProposal *proposal);
- gboolean (*equal) (GtkSourceCompletionProposal *proposal,
- GtkSourceCompletionProposal *other);
-
- /* Signals */
- void (*changed) (GtkSourceCompletionProposal *proposal);
+ GTypeInterface parent_iface;
};
-GTK_SOURCE_AVAILABLE_IN_ALL
-GType gtk_source_completion_proposal_get_type (void) G_GNUC_CONST;
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-gchar *gtk_source_completion_proposal_get_label (GtkSourceCompletionProposal *proposal);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-gchar *gtk_source_completion_proposal_get_markup (GtkSourceCompletionProposal *proposal);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-gchar *gtk_source_completion_proposal_get_text (GtkSourceCompletionProposal *proposal);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-GdkPixbuf *gtk_source_completion_proposal_get_icon (GtkSourceCompletionProposal *proposal);
-
-GTK_SOURCE_AVAILABLE_IN_3_18
-const gchar *gtk_source_completion_proposal_get_icon_name (GtkSourceCompletionProposal *proposal);
-
-GTK_SOURCE_AVAILABLE_IN_3_18
-GIcon *gtk_source_completion_proposal_get_gicon (GtkSourceCompletionProposal *proposal);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-gchar *gtk_source_completion_proposal_get_info (GtkSourceCompletionProposal *proposal);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_completion_proposal_changed (GtkSourceCompletionProposal *proposal);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-guint gtk_source_completion_proposal_hash (GtkSourceCompletionProposal *proposal);
-
-GTK_SOURCE_AVAILABLE_IN_ALL
-gboolean gtk_source_completion_proposal_equal (GtkSourceCompletionProposal *proposal,
- GtkSourceCompletionProposal *other);
-
G_END_DECLS
-
-#endif /* GTK_SOURCE_COMPLETION_PROPOSAL_H */
diff --git a/gtksourceview/gtksourcecompletionprovider.c b/gtksourceview/gtksourcecompletionprovider.c
index 4dfcdba5f6652ace376d564e551c41926e03141b..35a5cd6e361621b8fb577c0d50fd4c3edafd43ca 100644
--- a/gtksourceview/gtksourcecompletionprovider.c
+++ b/gtksourceview/gtksourcecompletionprovider.c
@@ -1,9 +1,7 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- */
/*
* This file is part of GtkSourceView
*
- * Copyright (C) 2007 - 2009 Jesús Barbero Rodríguez
- * Copyright (C) 2009 - Jesse van den Kieboom
+ * Copyright 2020 Christian Hergert
*
* GtkSourceView is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -17,441 +15,262 @@
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, see .
- */
-
-#ifdef HAVE_CONFIG_H
-#include
-#endif
-
-#include "gtksourcecompletionprovider.h"
-#include "gtksourcecompletionproposal.h"
-#include "gtksourcecompletioninfo.h"
-
-/**
- * SECTION:completionprovider
- * @title: GtkSourceCompletionProvider
- * @short_description: Completion provider interface
- *
- * You must implement this interface to provide proposals to #GtkSourceCompletion
*
- * The provider may be displayed in the completion window as a header row, showing
- * its name and optionally an icon.
- * The icon may be specified as a #GdkPixbuf, as an icon name or as a #GIcon by
- * implementing the corresponding get function. At most one of those get functions
- * should return a value different from %NULL, if they all return %NULL no icon
- * will be used.
+ * SPDX-License-Identifier: LGPL-2.1-or-later
*/
-typedef GtkSourceCompletionProviderIface GtkSourceCompletionProviderInterface;
-G_DEFINE_INTERFACE(GtkSourceCompletionProvider, gtk_source_completion_provider, G_TYPE_OBJECT)
-/* Default implementations */
-static gchar *
-gtk_source_completion_provider_get_name_default (GtkSourceCompletionProvider *provider)
-{
- g_return_val_if_reached (NULL);
-}
-
-static GdkPixbuf *
-gtk_source_completion_provider_get_icon_default (GtkSourceCompletionProvider *provider)
-{
- return NULL;
-}
+#include "config.h"
-static const gchar *
-gtk_source_completion_provider_get_icon_name_default (GtkSourceCompletionProvider *provider)
-{
- return NULL;
-}
+#include "gtksourcecompletioncontext.h"
+#include "gtksourcecompletioncell.h"
+#include "gtksourcecompletionproposal.h"
+#include "gtksourcecompletionprovider.h"
-static GIcon *
-gtk_source_completion_provider_get_gicon_default (GtkSourceCompletionProvider *provider)
-{
- return NULL;
-}
+G_DEFINE_INTERFACE (GtkSourceCompletionProvider, gtk_source_completion_provider, G_TYPE_OBJECT)
static void
-gtk_source_completion_provider_populate_default (GtkSourceCompletionProvider *provider,
- GtkSourceCompletionContext *context)
-{
- gtk_source_completion_context_add_proposals (context, provider, NULL, TRUE);
-}
-
-static GtkSourceCompletionActivation
-gtk_source_completion_provider_get_activation_default (GtkSourceCompletionProvider *provider)
+fallback_populate_async (GtkSourceCompletionProvider *provider,
+ GtkSourceCompletionContext *context,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- return GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE |
- GTK_SOURCE_COMPLETION_ACTIVATION_USER_REQUESTED;
+ GListModel *ret;
+ GError *error = NULL;
+ GTask *task;
+
+ task = g_task_new (provider, cancellable, callback, user_data);
+ g_task_set_source_tag (task, fallback_populate_async);
+
+ ret = GTK_SOURCE_COMPLETION_PROVIDER_GET_IFACE (provider)->populate (provider, context, &error);
+
+ if (ret == NULL)
+ {
+ if (error != NULL)
+ {
+ g_task_return_error (task, g_steal_pointer (&error));
+ }
+ else
+ {
+ g_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ "No results");
+ }
+ }
+ else
+ {
+ g_task_return_pointer (task, g_steal_pointer (&ret), g_object_unref);
+ }
+
+ g_clear_object (&task);
}
-static gboolean
-gtk_source_completion_provider_match_default (GtkSourceCompletionProvider *provider,
- GtkSourceCompletionContext *context)
+static GListModel *
+fallback_populate_finish (GtkSourceCompletionProvider *provider,
+ GAsyncResult *result,
+ GError **error)
{
- return TRUE;
+ return g_task_propagate_pointer (G_TASK (result), error);
}
-static GtkWidget *
-gtk_source_completion_provider_get_info_widget_default (GtkSourceCompletionProvider *provider,
- GtkSourceCompletionProposal *proposal)
+static GListModel *
+fallback_populate (GtkSourceCompletionProvider *provider,
+ GtkSourceCompletionContext *context,
+ GError **error)
{
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ "Not supported");
return NULL;
}
static void
-gtk_source_completion_provider_update_info_default (GtkSourceCompletionProvider *provider,
- GtkSourceCompletionProposal *proposal,
- GtkSourceCompletionInfo *info)
+fallback_refilter (GtkSourceCompletionProvider *provider,
+ GtkSourceCompletionContext *context,
+ GListModel *model)
{
}
-static gboolean
-gtk_source_completion_provider_get_start_iter_default (GtkSourceCompletionProvider *provider,
- GtkSourceCompletionContext *context,
- GtkSourceCompletionProposal *proposal,
- GtkTextIter *iter)
+static void
+fallback_activate (GtkSourceCompletionProvider *provider,
+ GtkSourceCompletionContext *context,
+ GtkSourceCompletionProposal *proposal)
{
- return FALSE;
}
-static gboolean
-gtk_source_completion_provider_activate_proposal_default (GtkSourceCompletionProvider *provider,
- GtkSourceCompletionProposal *proposal,
- GtkTextIter *iter)
+static void
+gtk_source_completion_provider_default_init (GtkSourceCompletionProviderInterface *iface)
{
- return FALSE;
+ iface->populate_async = fallback_populate_async;
+ iface->populate_finish = fallback_populate_finish;
+ iface->populate = fallback_populate;
+ iface->refilter = fallback_refilter;
+ iface->activate = fallback_activate;
}
-static gint
-gtk_source_completion_provider_get_interactive_delay_default (GtkSourceCompletionProvider *provider)
+char *
+gtk_source_completion_provider_get_title (GtkSourceCompletionProvider *self)
{
- /* -1 means the default value in the completion object */
- return -1;
-}
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_PROVIDER (self), NULL);
-static gint
-gtk_source_completion_provider_get_priority_default (GtkSourceCompletionProvider *provider)
-{
- return 0;
+ if (GTK_SOURCE_COMPLETION_PROVIDER_GET_IFACE (self)->get_title)
+ return GTK_SOURCE_COMPLETION_PROVIDER_GET_IFACE (self)->get_title (self);
+
+ return NULL;
}
-static void
-gtk_source_completion_provider_default_init (GtkSourceCompletionProviderIface *iface)
+int
+gtk_source_completion_provider_get_priority (GtkSourceCompletionProvider *self,
+ GtkSourceCompletionContext *context)
{
- iface->get_name = gtk_source_completion_provider_get_name_default;
-
- iface->get_icon = gtk_source_completion_provider_get_icon_default;
- iface->get_icon_name = gtk_source_completion_provider_get_icon_name_default;
- iface->get_gicon = gtk_source_completion_provider_get_gicon_default;
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_PROVIDER (self), 0);
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (context), 0);
- iface->populate = gtk_source_completion_provider_populate_default;
+ if (GTK_SOURCE_COMPLETION_PROVIDER_GET_IFACE (self)->get_priority)
+ return GTK_SOURCE_COMPLETION_PROVIDER_GET_IFACE (self)->get_priority (self, context);
- iface->match = gtk_source_completion_provider_match_default;
- iface->get_activation = gtk_source_completion_provider_get_activation_default;
-
- iface->get_info_widget = gtk_source_completion_provider_get_info_widget_default;
- iface->update_info = gtk_source_completion_provider_update_info_default;
-
- iface->get_start_iter = gtk_source_completion_provider_get_start_iter_default;
- iface->activate_proposal = gtk_source_completion_provider_activate_proposal_default;
-
- iface->get_interactive_delay = gtk_source_completion_provider_get_interactive_delay_default;
- iface->get_priority = gtk_source_completion_provider_get_priority_default;
+ return 0;
}
-/**
- * gtk_source_completion_provider_get_name:
- * @provider: a #GtkSourceCompletionProvider.
- *
- * Get the name of the provider. This should be a translatable name for
- * display to the user. For example: _("Document word completion provider"). The
- * returned string must be freed with g_free().
- *
- * Returns: a new string containing the name of the provider.
- */
-gchar *
-gtk_source_completion_provider_get_name (GtkSourceCompletionProvider *provider)
+gboolean
+gtk_source_completion_provider_is_trigger (GtkSourceCompletionProvider *self,
+ const GtkTextIter *iter,
+ gunichar ch)
{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_PROVIDER (provider), NULL);
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_PROVIDER (self), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
- return GTK_SOURCE_COMPLETION_PROVIDER_GET_INTERFACE (provider)->get_name (provider);
-}
+ if (GTK_SOURCE_COMPLETION_PROVIDER_GET_IFACE (self)->is_trigger)
+ return GTK_SOURCE_COMPLETION_PROVIDER_GET_IFACE (self)->is_trigger (self, iter, ch);
-/**
- * gtk_source_completion_provider_get_icon:
- * @provider: The #GtkSourceCompletionProvider
- *
- * Get the #GdkPixbuf for the icon of the @provider.
- *
- * Returns: (nullable) (transfer none): The icon to be used for the provider,
- * or %NULL if the provider does not have a special icon.
- */
-GdkPixbuf *
-gtk_source_completion_provider_get_icon (GtkSourceCompletionProvider *provider)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_PROVIDER (provider), NULL);
-
- return GTK_SOURCE_COMPLETION_PROVIDER_GET_INTERFACE (provider)->get_icon (provider);
+ return FALSE;
}
-/**
- * gtk_source_completion_provider_get_icon_name:
- * @provider: The #GtkSourceCompletionProvider
- *
- * Gets the icon name of @provider.
- *
- * Returns: (nullable) (transfer none): The icon name to be used for the provider,
- * or %NULL if the provider does not have a special icon.
- *
- * Since: 3.18
- */
-const gchar *
-gtk_source_completion_provider_get_icon_name (GtkSourceCompletionProvider *provider)
+gboolean
+gtk_source_completion_provider_key_activates (GtkSourceCompletionProvider *self,
+ GtkSourceCompletionContext *context,
+ GtkSourceCompletionProposal *proposal,
+ guint keyval,
+ GdkModifierType state)
{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_PROVIDER (provider), NULL);
-
- return GTK_SOURCE_COMPLETION_PROVIDER_GET_INTERFACE (provider)->get_icon_name (provider);
-}
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_PROVIDER (self), FALSE);
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (context), FALSE);
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_PROPOSAL (proposal), FALSE);
-/**
- * gtk_source_completion_provider_get_gicon:
- * @provider: The #GtkSourceCompletionProvider
- *
- * Gets the #GIcon for the icon of @provider.
- *
- * Returns: (nullable) (transfer none): The icon to be used for the provider,
- * or %NULL if the provider does not have a special icon.
- *
- * Since: 3.18
- */
-GIcon *
-gtk_source_completion_provider_get_gicon (GtkSourceCompletionProvider *provider)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_PROVIDER (provider), NULL);
+ if (GTK_SOURCE_COMPLETION_PROVIDER_GET_IFACE (self)->key_activates)
+ return GTK_SOURCE_COMPLETION_PROVIDER_GET_IFACE (self)->key_activates (self, context, proposal, keyval, state);
- return GTK_SOURCE_COMPLETION_PROVIDER_GET_INTERFACE (provider)->get_gicon (provider);
+ return FALSE;
}
-/**
- * gtk_source_completion_provider_populate:
- * @provider: a #GtkSourceCompletionProvider.
- * @context: a #GtkSourceCompletionContext.
- *
- * Populate @context with proposals from @provider added with the
- * gtk_source_completion_context_add_proposals() function.
- */
void
-gtk_source_completion_provider_populate (GtkSourceCompletionProvider *provider,
- GtkSourceCompletionContext *context)
+gtk_source_completion_provider_populate_async (GtkSourceCompletionProvider *self,
+ GtkSourceCompletionContext *context,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- g_return_if_fail (GTK_SOURCE_IS_COMPLETION_PROVIDER (provider));
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_PROVIDER (self));
+ g_return_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (context));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
- GTK_SOURCE_COMPLETION_PROVIDER_GET_INTERFACE (provider)->populate (provider, context);
+ GTK_SOURCE_COMPLETION_PROVIDER_GET_IFACE (self)->populate_async (self, context, cancellable, callback, user_data);
}
/**
- * gtk_source_completion_provider_get_activation:
- * @provider: a #GtkSourceCompletionProvider.
+ * gtk_source_completion_provider_populate_finish:
+ * @self: a #GtkSourceCompletionProvider
+ * @result: a #GAsyncResult provided to callback
+ * @error: a location for a #GError, or %NULL
*
- * Get with what kind of activation the provider should be activated.
- *
- * Returns: a combination of #GtkSourceCompletionActivation.
- **/
-GtkSourceCompletionActivation
-gtk_source_completion_provider_get_activation (GtkSourceCompletionProvider *provider)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_PROVIDER (provider), GTK_SOURCE_COMPLETION_ACTIVATION_NONE);
-
- return GTK_SOURCE_COMPLETION_PROVIDER_GET_INTERFACE (provider)->get_activation (provider);
-}
-
-/**
- * gtk_source_completion_provider_match:
- * @provider: a #GtkSourceCompletionProvider.
- * @context: a #GtkSourceCompletionContext.
+ * Completes an asynchronous operation to populate a completion provider.
*
- * Get whether the provider match the context of completion detailed in
- * @context.
+ * Returns: (transfer full): a #GListModel of #GtkSourceCompletionProposal
*
- * Returns: %TRUE if @provider matches the completion context, %FALSE otherwise.
+ * Since: 5.0
*/
-gboolean
-gtk_source_completion_provider_match (GtkSourceCompletionProvider *provider,
- GtkSourceCompletionContext *context)
+GListModel *
+gtk_source_completion_provider_populate_finish (GtkSourceCompletionProvider *self,
+ GAsyncResult *result,
+ GError **error)
{
- g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_PROVIDER (provider), TRUE);
+ g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_PROVIDER (self), NULL);
- return GTK_SOURCE_COMPLETION_PROVIDER_GET_INTERFACE (provider)->match (provider,
- context);
+ return GTK_SOURCE_COMPLETION_PROVIDER_GET_IFACE (self)->populate_finish (self, result, error);
}
-/**
- * gtk_source_completion_provider_get_info_widget:
- * @provider: a #GtkSourceCompletionProvider.
- * @proposal: a currently selected #GtkSourceCompletionProposal.
- *
- * Get a customized info widget to show extra information of a proposal.
- * This allows for customized widgets on a proposal basis, although in general
- * providers will have the same custom widget for all their proposals and
- * @proposal can be ignored. The implementation of this function is optional.
- *
- * If this function is not implemented, the default widget is a #GtkLabel. The
- * return value of gtk_source_completion_proposal_get_info() is used as the
- * content of the #GtkLabel.
- *
- *
- *