This commit is contained in:
Giuseppe Penone 2016-02-20 21:34:39 +00:00
commit 21dfbd0edf
53 changed files with 4914 additions and 4914 deletions

2
NEWS
View File

@ -1,7 +1,7 @@
Geany 1.27 (unreleased)
Internationalization
* Updated translations: it
* Updated translations: de, it, ja, lt, pt
Geany 1.26 (November 15, 2015)

View File

@ -60,7 +60,7 @@ context_action_cmd=
[indentation]
#width=4
# 0 is spaces, 1 is tabs, 2 is tab & spaces
#type=1
#type=0
[build-menu]
FT_00_LB=Compile

View File

@ -500,7 +500,7 @@
</child>
<child>
<object class="GtkImageMenuItem" id="goto_tag_definition2">
<property name="label" translatable="yes">Go to _Tag Definition</property>
<property name="label" translatable="yes">Go to Symbol Defini_tion</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
@ -7283,7 +7283,7 @@
<object class="GtkMenuItem" id="goto_tag_definition1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Go to _Tag Definition</property>
<property name="label" translatable="yes">Go to Symbol Defini_tion</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_goto_tag_definition1" swapped="no"/>
</object>
@ -7292,7 +7292,7 @@
<object class="GtkMenuItem" id="goto_tag_declaration1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Go to T_ag Declaration</property>
<property name="label" translatable="yes">Go to Symbol Decl_aration</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_goto_tag_declaration1" swapped="no"/>
</object>
@ -8049,7 +8049,7 @@
<object class="GtkMenuItem" id="load_tags1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Load Ta_gs...</property>
<property name="label" translatable="yes">Load Ta_gs File...</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_load_tags1_activate" swapped="no"/>
</object>

View File

@ -342,7 +342,7 @@ Short option Long option Function
-g --generate-tags Generate a global tags file (see
`Generating a global tags file`_).
-P --no-preprocessing Don't preprocess C/C++ files when generating tags.
-P --no-preprocessing Don't preprocess C/C++ files when generating tags file.
-i --new-instance Do not open files in a running instance, force opening
a new instance. Only available if Geany was compiled
@ -894,8 +894,8 @@ To ease navigation in source files and especially between
different files, Geany lets you jump between different navigation
points. Currently, this works for the following:
* `Go to tag declaration`_
* `Go to tag definition`_
* `Go to symbol declaration`_
* `Go to symbol definition`_
* Symbol list items
* Build errors
* Message items
@ -981,7 +981,7 @@ Autocompletion
^^^^^^^^^^^^^^
Geany can offer a list of possible completions for symbols defined in the
tags and for all words in a document.
tags files and for all words in open documents.
The autocompletion list for symbols is presented when the first few
characters of the symbol are typed (configurable, see `Editor Completions
@ -1038,7 +1038,7 @@ When you type ``foo.`` it will show an autocompletion list with 'i' and
'c' symbols.
It only works for languages that set parent scope names for e.g. struct
members. Currently this means C-like languages. The C tag parser only
members. Currently this means C-like languages. The C parser only
parses global scopes, so this won't work for structs or objects declared
in local scope.
@ -1191,8 +1191,8 @@ and the editor window's popup menu:
* Find usage
* Find in files
* Replace
* Go to tag definition
* Go to tag declaration
* Go to symbol definition
* Go to symbol declaration
* Go to line
See also `Search`_ preferences.
@ -1415,27 +1415,27 @@ documents. *Replace All In Selection* will replace all matching text
in the current selection of the current document.
Go to tag definition
^^^^^^^^^^^^^^^^^^^^
Go to symbol definition
^^^^^^^^^^^^^^^^^^^^^^^
If the current word or selection is the name of a tag definition
(e.g. a function name) and the file containing the tag definition is
If the current word or selection is the name of a symbol definition
(e.g. a function name) and the file containing the symbol definition is
open, this command will switch to that file and go to the
corresponding line number. The current word is either the word
nearest the edit cursor, or the word underneath the popup menu click
position when the popup menu is used.
.. note::
If the corresponding tag is on the current line, Geany will first
look for a tag declaration instead, as this is more useful.
Likewise *Go to tag declaration* will search for a tag definition
If the corresponding symbol is on the current line, Geany will first
look for a symbol declaration instead, as this is more useful.
Likewise *Go to symbol declaration* will search for a symbol definition
first in this case also.
Go to tag declaration
^^^^^^^^^^^^^^^^^^^^^
Go to symbol declaration
^^^^^^^^^^^^^^^^^^^^^^^^
Like *Go to tag definition*, but for a forward declaration such as a
Like *Go to symbol definition*, but for a forward declaration such as a
C function prototype or ``extern`` declaration instead of a function
body.
@ -1596,46 +1596,43 @@ translations, e.g.::
key[de]=Hallo
key[fr_FR]=Bonjour
Tags
----
Symbols and tags files
----------------------
Tags are information that relates symbols in a program with the
source file location of the declaration and definition.
Upon opening, files of supported filetypes are parsed to extract the symbol
information (aka "workspace symbols"). You can also have Geany automatically
load external files containing the symbol information (aka "global
tags files") upon startup, or manually using *Tools --> Load Tags File*.
Geany has built-in functionality for generating tag information (aka
"workspace tags") for supported filetypes when you open a file. You
can also have Geany automatically load external tag files (aka "global
tags files") upon startup, or manually using *Tools --> Load Tags*.
Geany uses its own tag file format, similar to what ``ctags`` uses
Geany uses its own tags file format, similar to what ``ctags`` uses
(but is incompatible with ctags). You use Geany to generate global
tags files, as described below.
Workspace tags
^^^^^^^^^^^^^^
Workspace symbols
^^^^^^^^^^^^^^^^^
Tags for each document are parsed whenever a file is loaded, saved or
Each document is parsed for symbols whenever a file is loaded, saved or
modified (see *Symbol list update frequency* preference in the `Editor
Completions preferences`_). These are shown in the Symbol list in the
Sidebar. These tags are also used for autocompletion of symbols and calltips
Sidebar. These symbols are also used for autocompletion and calltips
for all documents open in the current session that have the same filetype.
The *Go to Tag* commands can be used with all workspace tags. See
`Go to tag definition`_.
The *Go to Symbol* commands can be used with all workspace symbols. See
`Go to symbol definition`_.
Global tags
^^^^^^^^^^^
Global tags files
^^^^^^^^^^^^^^^^^
Global tags are used to provide autocompletion of symbols and calltips
without having to open the corresponding source files. This is intended
Global tags files are used to provide symbols for autocompletion and calltips
without having to open the source files containing these symbols. This is intended
for library APIs, as the tags file only has to be updated when you upgrade
the library.
You can load a custom global tags file in two ways:
* Using the *Load Tags* command in the Tools menu.
* Using the *Load Tags File* command in the Tools menu.
* By moving or symlinking tags files to the ``tags`` subdirectory of
one of the `configuration file paths`_ before starting Geany.
@ -1645,15 +1642,16 @@ the format::
name.lang_ext.tags
*lang_ext* is one of the extensions set for the filetype associated
with the tags. See the section called `Filetype extensions`_ for
with the tags parser. See the section called `Filetype extensions`_ for
more information.
Default global tags files
`````````````````````````
For some languages, a list of global tags is loaded when the
corresponding filetype is first used. Currently these are for:
Some global tags files are distributed with Geany and will be loaded
automatically when the corresponding filetype is first used. Currently
this includes global tags files for these languages:
* C
* Pascal
@ -1681,32 +1679,32 @@ might fail.
The Tagmanager format is a bit more complex and is used for files
created by the ``geany -g`` command. There is one tag per line.
Different tag attributes like the return value or the argument list
created by the ``geany -g`` command. There is one symbol per line.
Different symbol attributes like the return value or the argument list
are separated with different characters indicating the type of the
following argument. This is the more complete and recommended tag
following argument. This is the more complete and recommended tags file
format.
Pipe-separated format
*********************
The Pipe-separated format is easier to read and write.
There is one tag per line and different tag attributes are separated
There is one symbol per line and different symbol attributes are separated
by the pipe character (``|``). A line looks like::
basename|string|(string path [, string suffix])|
| The first field is the tag name (usually a function name).
| The first field is the symbol name (usually a function name).
| The second field is the type of the return value.
| The third field is the argument list for this tag.
| The fourth field is the description for this tag but
| The third field is the argument list for this symbol.
| The fourth field is the description for this symbol but
currently unused and should be left empty.
Except for the first field (tag name), all other field can be left
Except for the first field (symbol name), all other field can be left
empty but the pipe separator must appear for them.
You can easily write your own global tag files using this format.
You can easily write your own global tags files using this format.
Just save them in your tags directory, as described earlier in the
section `Global tags`_.
section `Global tags files`_.
CTags format
************
@ -1724,12 +1722,12 @@ Generating a global tags file
You can generate your own global tags files by parsing a list of
source files. The command is::
geany -g [-P] <Tag File> <File list>
geany -g [-P] <Tags File> <File list>
* Tag File filename should be in the format described earlier --
see the section called `Global tags`_.
* Tags File filename should be in the format described earlier --
see the section called `Global tags files`_.
* File list is a list of filenames, each with a full path (unless
you are generating C/C++ tags and have set the CFLAGS environment
you are generating C/C++ tags files and have set the CFLAGS environment
variable appropriately).
* ``-P`` or ``--no-preprocessing`` disables using the C pre-processor
to process ``#include`` directives for C/C++ source files. Use this
@ -1742,17 +1740,17 @@ Example for the wxD library for the D programming language::
geany -g wxd.d.tags /home/username/wxd/wx/*.d
Generating C/C++ tag files
**************************
Generating C/C++ tags files
***************************
You may need to first setup the `C ignore.tags`_ file.
For C/C++ tag files gcc is required by default, so that header files
For C/C++ tags files gcc is required by default, so that header files
can be preprocessed to include any other headers they depend upon. If
you do not want this, use the ``-P`` option described above.
For preprocessing, the environment variable CFLAGS should be set with
appropriate ``-I/path`` include paths. The following example works with
the bash shell, generating tags for the GnomeUI library::
the bash shell, generating a tags file for the GnomeUI library::
CFLAGS=`pkg-config --cflags libgnomeui-2.0` geany -g gnomeui.c.tags \
/usr/include/libgnomeui-2.0/gnome.h
@ -1761,8 +1759,8 @@ You can adapt this command to use CFLAGS and header files appropriate
for whichever libraries you want.
Generating tag files on Windows
*******************************
Generating tags files on Windows
********************************
This works basically the same as on other platforms::
"c:\program files\geany\bin\geany" -g c:\mytags.php.tags c:\code\somefile.php
@ -1771,12 +1769,12 @@ This works basically the same as on other platforms::
C ignore.tags
^^^^^^^^^^^^^
You can ignore certain tags for C-based languages if they would lead
You can ignore certain symbols for C-based languages if they would lead
to wrong parsing of the code. Use the *Tools->Configuration
Files->ignore.tags* menu item to open the user ``ignore.tags`` file.
See also `Configuration file paths`_.
List all tag names you want to ignore in this file, separated by spaces
List all symbol names you want to ignore in this file, separated by spaces
and/or newlines.
Example::
@ -1790,7 +1788,7 @@ This will parse code like:
``gchar **utils_strv_new(const gchar *first, ...)
G_GNUC_NULL_TERMINATED;``
More detailed information about ignore tags usage from the Exuberant Ctags
More detailed information about ignore.tags usage from the Exuberant Ctags
manual page:
Specifies a list of identifiers which are to be specially handled
@ -2222,7 +2220,7 @@ Autocomplete symbols
Autocomplete all words in document
When you start to type a word, Geany will search the whole document for
words starting with the typed part to complete it, assuming there
are no tag names to show.
are no symbol names to show.
Drop rest of word on completion
Remove any word part to the right of the cursor when choosing a
@ -2241,7 +2239,7 @@ Max. symbol name suggestions
Symbol list update frequency
The minimum delay (in milliseconds) between two symbol list updates.
This option determines how frequently the tag list is updated for the
This option determines how frequently the symbol list is updated for the
current document. The smaller the delay, the more up-to-date the symbol
list (and then the completions); but rebuilding the symbol list has a
cost in performance, especially with large files.
@ -3420,9 +3418,9 @@ Scroll up by one line Alt-Up Scrolls the view.
Scroll down by one line Alt-Down Scrolls the view.
Complete word Ctrl-Space Shows the autocompletion list. If already showing
tag completion, it shows document word completion
symbol completion, it shows document word completion
instead, even if it is not enabled for automatic
completion. Likewise if no tag suggestions are
completion. Likewise if no symbol suggestions are
available, it shows document word completion.
Show calltip Ctrl-Shift-Space Shows a calltip for the current function or
@ -3558,7 +3556,7 @@ Smart line indent Indents the current li
Send to Custom Command 1 (2,3) Ctrl-1 (2,3) Passes the current selection to a configured
external command (available for the first
three configured commands, see
9 configured commands, see
`Sending text through custom commands`_ for
details).
@ -3656,11 +3654,11 @@ Goto next marker Ctrl-. Goto the next marker i
Goto previous marker Ctrl-, Goto the previous marker in the current document.
Go to tag definition Ctrl-T Jump to the definition of the current word or
selection. See `Go to tag definition`_.
Go to symbol definition Ctrl-T Jump to the definition of the current word or
selection. See `Go to symbol definition`_.
Go to tag declaration Ctrl-Shift-T Jump to the declaration of the current word or
selection. See `Go to tag declaration`_.
Go to symbol declaration Ctrl-Shift-T Jump to the declaration of the current word or
selection. See `Go to symbol declaration`_.
Go to Start of Line Home Move the caret to the start of the line.
Behaves differently if smart_home_key_ is set.
@ -3786,7 +3784,7 @@ Fold all Folds all contractible
Unfold all Unfolds all contracted code blocks.
Reload symbol list Ctrl-Shift-R Reloads the tag/symbol list.
Reload symbol list Ctrl-Shift-R Reloads the symbol list.
Toggle Line wrapping Enables or disables wrapping of long lines.
@ -4033,7 +4031,7 @@ support for the following has been implemented:
* `Filetype group membership`_.
* Reading filetype settings in the ``[settings]`` section, including:
* Using an existing syntax highlighting lexer (`lexer_filetype`_ key).
* Using an existing tag parser (`tag_parser`_ key).
* Using an existing tags parser (`tag_parser`_ key).
* Build commands (``[build-menu]`` section).
* Loading global tags files (sharing the ``tag_parser`` filetype's namespace).
@ -4266,12 +4264,12 @@ lexer_filetype
symbol_list_sort_mode
What the default symbol list sort order should be.
===== =====================================
===== ========================================
Value Meaning
===== =====================================
0 Sort tags by name
1 Sort tags by appearance (line number)
===== =====================================
===== ========================================
0 Sort symbols by name
1 Sort symbols by appearance (line number)
===== ========================================
.. _xml_indent_tags:
@ -4316,15 +4314,16 @@ As of Geany 0.19 this section is supplemented by the `[build-menu] section`_.
Values that are set in the [build-menu] section will override those in this section.
error_regex
This is a regular expression to parse a filename
and line number from build output. If undefined, Geany will fall
back to its default error message parsing.
This is a Perl-compatible regular expression (PCRE) to parse a filename
(absolute or relative) and line number from the build output.
If undefined, Geany will fall back to its default error message parsing.
Only the first two matches will be read by Geany. Geany will look for
a match that is purely digits, and use this for the line number. The
remaining match will be used as the filename.
Only the first two match groups will be read by Geany. These groups can
occur in any order: the match group consisting of only digits will be used
as the line number, and the other group as the filename. In no group
consists of only digits, the match will fail.
*Example:* ``error_regex=(.+):([0-9]+):[0-9]+``
*Example:* ``error_regex=^(.+):([0-9]+):[0-9]+``
This will parse a message such as:
``test.py:7:24: E202 whitespace before ']'``
@ -4591,7 +4590,7 @@ translucency
*Example:* ``translucency=256;256;false;false``
marker_line
The style for a highlighted line (e.g when using Goto line or goto tag).
The style for a highlighted line (e.g when using Goto line or goto symbol).
The foreground color (first argument) is only used when the Markers margin
is enabled (see View menu).
@ -5334,7 +5333,7 @@ Editor
* Alt-scroll wheel moves up/down a page.
* Ctrl-scroll wheel zooms in/out.
* Shift-scroll wheel scrolls 8 characters right/left.
* Ctrl-click on a word in a document to perform *Go to Tag Definition*.
* Ctrl-click on a word in a document to perform *Go to Symbol Definition*.
* Ctrl-click on a bracket/brace to perform *Go to Matching Brace*.
Interface

1582
po/de.po

File diff suppressed because it is too large Load Diff

1693
po/ja.po

File diff suppressed because it is too large Load Diff

2465
po/ko.po

File diff suppressed because it is too large Load Diff

View File

@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: Geany 1.25\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-11-01 19:03+0100\n"
"PO-Revision-Date: 2014-04-06 08:42+0200\n"
"Last-Translator: Algimantas Margevičius <algimantas@margevicius.lt>\n"
"PO-Revision-Date: 2016-02-08 08:29+0200\n"
"Last-Translator: Zygimantus <zygimantus@gmail.com>\n"
"Language-Team: Lietuvių <>\n"
"Language: lt\n"
"MIME-Version: 1.0\n"
@ -17,7 +17,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n"
"%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Poedit 1.6.4\n"
"X-Generator: Poedit 1.8.4\n"
#: ../geany.desktop.in.h:1 ../data/geany.glade.h:338
msgid "Geany"
@ -2092,8 +2092,8 @@ msgstr "Projekto savybės"
msgid "Filename:"
msgstr "Failo vardas:"
#: ../data/geany.glade.h:460 ../src/project.c:169 ../plugins/classbuilder.c:467
#: ../plugins/classbuilder.c:477
#: ../data/geany.glade.h:460 ../src/project.c:169
#: ../plugins/classbuilder.c:467 ../plugins/classbuilder.c:477
msgid "Name:"
msgstr "Pavadinimas:"
@ -2539,9 +2539,8 @@ msgid "Detect from file"
msgstr "Aptikti iš failo"
#: ../src/dialogs.c:225
#, fuzzy
msgid "Programming Languages"
msgstr "_Programavimo kalbos"
msgstr "Programavimo kalbos"
#: ../src/dialogs.c:227
#, fuzzy
@ -2549,9 +2548,8 @@ msgid "Scripting Languages"
msgstr "_Scenarijų kalbos"
#: ../src/dialogs.c:229
#, fuzzy
msgid "Markup Languages"
msgstr "_Išvaizdos kalbos"
msgstr "Žymėjimo kalbos"
#: ../src/dialogs.c:307
msgid "_More Options"
@ -2776,7 +2774,7 @@ msgstr ", tik skaitymui"
#: ../src/document.c:1627
msgid "Discard history"
msgstr ""
msgstr "Išvalyti istoriją"
#: ../src/document.c:1628
msgid ""
@ -2846,9 +2844,8 @@ msgid "Failed to close file '%s': fclose() failed: %s"
msgstr "Nepavyko užverti failo „%s“: fclose() klaida: %s"
#: ../src/document.c:2058 ../src/document.c:3589
#, fuzzy
msgid "_Overwrite"
msgstr "Perrašyti?"
msgstr "Perrašyti"
#: ../src/document.c:2060 ../src/document.c:3592
#, fuzzy, c-format
@ -3893,7 +3890,7 @@ msgstr "Rasti failo „%s“ nepavyko - bandomas dabartinis dokumento kelias."
#: ../src/msgwindow.c:1109
msgid "The document has been closed."
msgstr ""
msgstr "Dokumentas buvo uždarytas."
#: ../src/notebook.c:199
msgid "Switch to Document"
@ -3931,6 +3928,9 @@ msgid ""
"Author(s):\t%s\n"
"Filename:\t%s"
msgstr ""
"Versija:\t%s\n"
"Autorius(-iai):\t%s\n"
"Failas:\t%s"
#: ../src/plugins.c:1630
msgid "No plugins available."
@ -5326,15 +5326,15 @@ msgstr "Unix (LF)"
#: ../src/utils.c:386
msgid "CRLF"
msgstr ""
msgstr "CRLF"
#: ../src/utils.c:387
msgid "CR"
msgstr ""
msgstr "CR"
#: ../src/utils.c:388
msgid "LF"
msgstr ""
msgstr "LF"
#: ../src/vte.c:489
#, c-format
@ -5483,8 +5483,9 @@ msgstr "HTML simboliai"
msgid "Inserts HTML character entities like '&amp;'."
msgstr "Įterpia HTML simbolių atitikmenis tokius kaip „&amp;“."
#: ../plugins/htmlchars.c:40 ../plugins/export.c:38 ../plugins/filebrowser.c:51
#: ../plugins/saveactions.c:44 ../plugins/splitwindow.c:35
#: ../plugins/htmlchars.c:40 ../plugins/export.c:38
#: ../plugins/filebrowser.c:51 ../plugins/saveactions.c:44
#: ../plugins/splitwindow.c:35
msgid "The Geany developer team"
msgstr "Geany kūrėjų komanda"

1798
po/pt.po

File diff suppressed because it is too large Load Diff

View File

@ -3052,6 +3052,7 @@ sptr_t scintilla_send_message(ScintillaObject *sci, unsigned int iMessage, uptr_
return psci->WndProc(iMessage, wParam, lParam);
}
GEANY_API_SYMBOL
sptr_t scintilla_object_send_message(ScintillaObject *sci, unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
return scintilla_send_message(sci, iMessage, wParam, lParam);
}
@ -3093,6 +3094,7 @@ GType scintilla_get_type() {
return scintilla_type;
}
GEANY_API_SYMBOL
GType scintilla_object_get_type() {
return scintilla_get_type();
}
@ -3210,6 +3212,7 @@ GtkWidget* scintilla_new() {
return widget;
}
GEANY_API_SYMBOL
GtkWidget *scintilla_object_new() {
return scintilla_new();
}

View File

@ -4,7 +4,7 @@ diff --git scintilla/gtk/ScintillaGTK.cxx scintilla/gtk/ScintillaGTK.cxx
index 0871ca2..49dc278 100644
--- scintilla/gtk/ScintillaGTK.cxx
+++ scintilla/gtk/ScintillaGTK.cxx
@@ -3046,6 +3046,7 @@ sptr_t ScintillaGTK::DirectFunction(
@@ -3046,11 +3046,13 @@ sptr_t ScintillaGTK::DirectFunction(
}
/* legacy name for scintilla_object_send_message */
@ -12,7 +12,13 @@ index 0871ca2..49dc278 100644
sptr_t scintilla_send_message(ScintillaObject *sci, unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
ScintillaGTK *psci = static_cast<ScintillaGTK *>(sci->pscin);
return psci->WndProc(iMessage, wParam, lParam);
@@ -3062,6 +3062,7 @@ extern void Platform_Initialise();
}
+GEANY_API_SYMBOL
sptr_t scintilla_object_send_message(ScintillaObject *sci, unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
return scintilla_send_message(sci, iMessage, wParam, lParam);
}
@@ -3062,6 +3064,7 @@ extern void Platform_Initialise();
extern void Platform_Finalise();
/* legacy name for scintilla_object_get_type */
@ -20,7 +26,15 @@ index 0871ca2..49dc278 100644
GType scintilla_get_type() {
static GType scintilla_type = 0;
try {
@@ -3200,6 +3200,7 @@ static void scintilla_init(ScintillaObject *sci) {
@@ -3091,6 +3094,7 @@ GType scintilla_get_type() {
return scintilla_type;
}
+GEANY_API_SYMBOL
GType scintilla_object_get_type() {
return scintilla_get_type();
}
@@ -3200,6 +3204,7 @@ static void scintilla_init(ScintillaObje
}
/* legacy name for scintilla_object_new */
@ -28,6 +42,14 @@ index 0871ca2..49dc278 100644
GtkWidget* scintilla_new() {
GtkWidget *widget = GTK_WIDGET(g_object_new(scintilla_get_type(), NULL));
gtk_widget_set_direction(widget, GTK_TEXT_DIR_LTR);
@@ -3207,6 +3212,7 @@ GtkWidget* scintilla_new() {
return widget;
}
+GEANY_API_SYMBOL
GtkWidget *scintilla_object_new() {
return scintilla_new();
}
diff --git scintilla/gtk/scintilla-marshal.c scintilla/gtk/scintilla-marshal.c
index be57b7c..cee3e73 100644
--- scintilla/gtk/scintilla-marshal.c

View File

@ -1,123 +0,0 @@
/*
* plugin_test.c
*
* Copyright 2010-2011 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
* Copyright 2010-2011 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
/* This code tries to load the passed Geany plugin
* (passed as path, e.g. pluginname.so) and looks up some symbols.
* Example use case for this tool is to test whether a plugin is
* loadable and defines all required symbols.
*
* This file is not built during the normal build process, instead
* compile it on your with the following command in the root of the Geany source tree:
*
* cc -o plugin_test scripts/plugin_test.c `pkg-config --cflags --libs glib-2.0 gmodule-2.0`
*/
#include <stdio.h>
#include <glib.h>
#include <gmodule.h>
static gboolean tp_check_version(GModule *module)
{
/* TODO implement me */
return TRUE;
}
static void tp_close_module(GModule *module)
{
if (! g_module_close(module))
g_warning("%s: %s", g_module_name(module), g_module_error());
}
/* Emulate loading a plugin and looking up some symbols,
* similar to what Geany would do on loading the plugin.
*/
static gboolean test_plugin(const gchar *filename)
{
GModule *module;
void (*plugin_set_info)(void*);
void (*init) (void *data);
void (*cleanup) (void);
g_return_val_if_fail(filename, FALSE);
g_return_val_if_fail(g_module_supported(), FALSE);
module = g_module_open(filename, G_MODULE_BIND_LOCAL);
if (! module)
{
g_warning("Can't load plugin: \"%s\": %s", filename, g_module_error());
return FALSE;
}
if (! tp_check_version(module))
{
tp_close_module(module);
return FALSE;
}
g_module_symbol(module, "plugin_set_info", (void *) &plugin_set_info);
if (plugin_set_info == NULL)
{
g_warning("No plugin_set_info() defined for \"%s\" - consider fixing the plugin!", filename);
tp_close_module(module);
return FALSE;
}
g_module_symbol(module, "plugin_init", (void *) &init);
if (init == NULL)
{
g_warning("Plugin '%s' has no plugin_init() function - consider fixing the plugin!", filename);
tp_close_module(module);
return FALSE;
}
g_module_symbol(module, "plugin_cleanup", (void *) &cleanup);
if (cleanup == NULL)
{
g_warning("Plugin '%s' has no plugin_cleanup() function - there may be memory leaks!", filename);
}
tp_close_module(module);
return TRUE;
}
gint main(gint argc, gchar **argv)
{
gint i;
gint result = 0;
g_set_prgname("plugin_test");
/* we could perform better argument processing here as well as more error checking but
* it's probably not worth at all */
for (i = 1; i < argc; i++)
{
if (! test_plugin(argv[i]))
result = 1;
}
return result;
}

View File

@ -510,8 +510,12 @@ static gint document_get_new_idx(void)
}
static void queue_colourise(GeanyDocument *doc)
static void queue_colourise(GeanyDocument *doc, gboolean full_colourise)
{
/* make sure we don't override previously set full_colourise=TRUE by FALSE */
if (!doc->priv->colourise_needed || !doc->priv->full_colourise)
doc->priv->full_colourise = full_colourise;
/* Colourise the editor before it is next drawn */
doc->priv->colourise_needed = TRUE;
@ -1394,7 +1398,7 @@ GeanyDocument *document_open_file_full(GeanyDocument *doc, const gchar *filename
/* add the text to the ScintillaObject */
sci_set_readonly(doc->editor->sci, FALSE); /* to allow replacing text */
sci_set_text(doc->editor->sci, filedata.data); /* NULL terminated data */
queue_colourise(doc); /* Ensure the document gets colourised. */
queue_colourise(doc, TRUE); /* Ensure the document gets colourised. */
/* detect & set line endings */
editor_mode = utils_get_line_endings(filedata.data, filedata.len);
@ -2750,7 +2754,7 @@ void document_highlight_tags(GeanyDocument *doc)
keywords = g_string_free(keywords_str, FALSE);
sci_set_keywords(doc->editor->sci, keyword_idx, keywords);
g_free(keywords);
queue_colourise(doc); /* force re-highlighting the entire document */
queue_colourise(doc, FALSE); /* re-highlight the visible area */
}
}
@ -2811,7 +2815,7 @@ static void document_load_config(GeanyDocument *doc, GeanyFiletype *type,
highlighting_set_styles(doc->editor->sci, type);
editor_set_indentation_guides(doc->editor);
build_menu_update(doc);
queue_colourise(doc);
queue_colourise(doc, TRUE);
if (type->priv->symbol_list_sort_mode == SYMBOLS_SORT_USE_PREVIOUS)
doc->priv->symbol_list_sort_mode = interface_prefs.symbols_sort_mode;
else

View File

@ -90,6 +90,7 @@ typedef struct GeanyDocumentPrivate
/* Used so Undo/Redo works for encoding changes. */
FileEncoding saved_encoding;
gboolean colourise_needed; /* use document.c:queue_colourise() instead */
gboolean full_colourise;
gint line_count; /* Number of lines in the document. */
gint symbol_list_sort_mode;
/* indicates whether a file is on a remote filesystem, works only with GIO/GVfs */

View File

@ -75,6 +75,7 @@ static GHashTable *snippet_hash = NULL;
static GQueue *snippet_offsets = NULL;
static gint snippet_cursor_insert_pos;
static GtkAccelGroup *snippet_accel_group = NULL;
static gboolean autocomplete_scope_shown = FALSE;
static const gchar geany_cursor_marker[] = "__GEANY_CURSOR_MARKER__";
@ -657,7 +658,9 @@ static gboolean match_last_chars(ScintillaObject *sci, gint pos, const gchar *st
gchar *buf;
g_return_val_if_fail(len < 100, FALSE);
g_return_val_if_fail((gint)len <= pos, FALSE);
if ((gint)len > pos)
return FALSE;
buf = g_alloca(len + 1);
sci_get_text_range(sci, pos - len, pos, buf);
@ -697,51 +700,108 @@ static void request_reshowing_calltip(SCNotification *nt)
}
static void autocomplete_scope(GeanyEditor *editor)
static gboolean autocomplete_scope(GeanyEditor *editor, const gchar *root, gsize rootlen)
{
ScintillaObject *sci = editor->sci;
gint pos = sci_get_current_position(editor->sci);
gchar typed = sci_get_char_at(sci, pos - 1);
gchar brace_char;
gchar *name;
const GPtrArray *tags = NULL;
const TMTag *tag;
GeanyFiletype *ft = editor->document->file_type;
GPtrArray *tags;
gboolean function = FALSE;
gboolean member;
gboolean ret = FALSE;
const gchar *current_scope;
const gchar *context_sep = tm_tag_context_separator(ft->lang);
if (ft->id == GEANY_FILETYPES_C || ft->id == GEANY_FILETYPES_CPP)
if (autocomplete_scope_shown)
{
if (pos >= 2 && (match_last_chars(sci, pos, "->") || match_last_chars(sci, pos, "::")))
/* move at the operator position */
pos -= rootlen;
/* allow for a space between word and operator */
while (pos > 0 && isspace(sci_get_char_at(sci, pos - 1)))
pos--;
else if (ft->id == GEANY_FILETYPES_CPP && pos >= 3 && match_last_chars(sci, pos, "->*"))
pos-=2;
else if (typed != '.')
return;
if (pos > 0)
typed = sci_get_char_at(sci, pos - 1);
}
else if (typed != '.')
return;
/* make sure to keep in sync with similar checks below */
if (typed == '.')
pos -= 1;
else if (match_last_chars(sci, pos, context_sep))
pos -= strlen(context_sep);
else if ((ft->id == GEANY_FILETYPES_C || ft->id == GEANY_FILETYPES_CPP) &&
match_last_chars(sci, pos, "->"))
pos -= 2;
else if (ft->id == GEANY_FILETYPES_CPP && match_last_chars(sci, pos, "->*"))
pos -= 3;
else
return FALSE;
/* allow for a space between word and operator */
if (isspace(sci_get_char_at(sci, pos - 2)))
while (pos > 0 && isspace(sci_get_char_at(sci, pos - 1)))
pos--;
name = editor_get_word_at_pos(editor, pos - 1, NULL);
if (!name)
return;
tags = tm_workspace_find(name, tm_tag_max_t, NULL, FALSE, ft->lang);
g_free(name);
if (!tags || tags->len == 0)
return;
tag = g_ptr_array_index(tags, 0);
name = tag->var_type;
if (name)
/* if function or array index, skip to matching brace */
brace_char = sci_get_char_at(sci, pos - 1);
if (pos > 0 && (brace_char == ')' || brace_char == ']'))
{
TMSourceFile *obj = editor->document->tm_file;
gint brace_pos = sci_find_matching_brace(sci, pos - 1);
tags = tm_workspace_find_scope_members(obj ? obj->tags_array : NULL,
name, TRUE, FALSE);
if (tags)
show_tags_list(editor, tags, 0);
if (brace_pos != -1)
{
pos = brace_pos;
function = brace_char == ')';
}
/* allow for a space between opening brace and name */
while (pos > 0 && isspace(sci_get_char_at(sci, pos - 1)))
pos--;
}
name = editor_get_word_at_pos(editor, pos, NULL);
if (!name)
return FALSE;
/* check if invoked on member */
pos -= strlen(name);
while (pos > 0 && isspace(sci_get_char_at(sci, pos - 1)))
pos--;
/* make sure to keep in sync with similar checks above */
member = match_last_chars(sci, pos, ".") || match_last_chars(sci, pos, context_sep) ||
match_last_chars(sci, pos, "->") || match_last_chars(sci, pos, "->*");
if (symbols_get_current_scope(editor->document, &current_scope) == -1)
current_scope = "";
tags = tm_workspace_find_scope_members(editor->document->tm_file, name, function,
member, current_scope);
if (tags)
{
GPtrArray *filtered = g_ptr_array_new();
TMTag *tag;
guint i;
foreach_ptr_array(tag, i, tags)
{
if (g_str_has_prefix(tag->name, root))
g_ptr_array_add(filtered, tag);
}
if (filtered->len > 0)
{
show_tags_list(editor, filtered, rootlen);
ret = TRUE;
}
g_ptr_array_free(tags, TRUE);
g_ptr_array_free(filtered, TRUE);
}
g_free(name);
return ret;
}
@ -1100,6 +1160,7 @@ static gboolean on_editor_notify(G_GNUC_UNUSED GObject *object, GeanyEditor *edi
case SCN_AUTOCCANCELLED:
/* now that autocomplete is finishing or was cancelled, reshow calltips
* if they were showing */
autocomplete_scope_shown = FALSE;
request_reshowing_calltip(nt);
break;
case SCN_NEEDSHOWN:
@ -1832,10 +1893,9 @@ static gboolean append_calltip(GString *str, const TMTag *tag, GeanyFiletypeID f
static gchar *find_calltip(const gchar *word, GeanyFiletype *ft)
{
const GPtrArray *tags;
GPtrArray *tags;
const TMTagType arg_types = tm_tag_function_t | tm_tag_prototype_t |
tm_tag_method_t | tm_tag_macro_with_arg_t;
TMTagAttrType *attrs = NULL;
TMTag *tag;
GString *str = NULL;
guint i;
@ -1843,20 +1903,26 @@ static gchar *find_calltip(const gchar *word, GeanyFiletype *ft)
g_return_val_if_fail(ft && word && *word, NULL);
/* use all types in case language uses wrong tag type e.g. python "members" instead of "methods" */
tags = tm_workspace_find(word, tm_tag_max_t, attrs, FALSE, ft->lang);
tags = tm_workspace_find(word, NULL, tm_tag_max_t, NULL, ft->lang);
if (tags->len == 0)
{
g_ptr_array_free(tags, TRUE);
return NULL;
}
tag = TM_TAG(tags->pdata[0]);
if (ft->id == GEANY_FILETYPES_D &&
(tag->type == tm_tag_class_t || tag->type == tm_tag_struct_t))
{
g_ptr_array_free(tags, TRUE);
/* user typed e.g. 'new Classname(' so lookup D constructor Classname::this() */
tags = tm_workspace_find_scoped("this", tag->name,
arg_types, attrs, FALSE, ft->lang, TRUE);
tags = tm_workspace_find("this", tag->name, arg_types, NULL, ft->lang);
if (tags->len == 0)
{
g_ptr_array_free(tags, TRUE);
return NULL;
}
}
/* remove tags with no argument list */
@ -1869,7 +1935,10 @@ static gchar *find_calltip(const gchar *word, GeanyFiletype *ft)
}
tm_tags_prune((GPtrArray *) tags);
if (tags->len == 0)
{
g_ptr_array_free(tags, TRUE);
return NULL;
}
else
{ /* remove duplicate calltips */
TMTagAttrType sort_attr[] = {tm_tag_attr_name_t, tm_tag_attr_scope_t,
@ -1906,6 +1975,9 @@ static gchar *find_calltip(const gchar *word, GeanyFiletype *ft)
break;
}
}
g_ptr_array_free(tags, TRUE);
if (str)
{
gchar *result = str->str;
@ -1951,6 +2023,20 @@ gboolean editor_show_calltip(GeanyEditor *editor, gint pos)
if (! highlighting_is_code_style(lexer, style))
return FALSE;
while (pos > 0 && isspace(sci_get_char_at(sci, pos - 1)))
pos--;
/* skip possible generic/template specification, like foo<int>() */
if (sci_get_char_at(sci, pos - 1) == '>')
{
pos = sci_find_matching_brace(sci, pos - 1);
if (pos == -1)
return FALSE;
while (pos > 0 && isspace(sci_get_char_at(sci, pos - 1)))
pos--;
}
word[0] = '\0';
editor_find_current_word(editor, pos - 1, word, sizeof word, NULL);
if (word[0] == '\0')
@ -2027,21 +2113,21 @@ autocomplete_html(ScintillaObject *sci, const gchar *root, gsize rootlen)
static gboolean
autocomplete_tags(GeanyEditor *editor, const gchar *root, gsize rootlen)
{
TMTagAttrType attrs[] = { tm_tag_attr_name_t, 0 };
const GPtrArray *tags;
GPtrArray *tags;
GeanyDocument *doc;
gboolean found;
g_return_val_if_fail(editor, FALSE);
doc = editor->document;
tags = tm_workspace_find(root, tm_tag_max_t, attrs, TRUE, doc->file_type->lang);
if (tags)
{
tags = tm_workspace_find_prefix(root, doc->file_type->lang, editor_prefs.autocompletion_max_entries);
found = tags->len > 0;
if (found)
show_tags_list(editor, tags, rootlen);
return tags->len > 0;
}
return FALSE;
g_ptr_array_free(tags, TRUE);
return found;
}
@ -2201,7 +2287,6 @@ gboolean editor_start_auto_complete(GeanyEditor *editor, gint pos, gboolean forc
if (!force && !highlighting_is_code_style(lexer, style))
return FALSE;
autocomplete_scope(editor);
ret = autocomplete_check_html(editor, style, pos);
if (ft->id == GEANY_FILETYPES_LATEX)
@ -2215,6 +2300,23 @@ gboolean editor_start_auto_complete(GeanyEditor *editor, gint pos, gboolean forc
root = cword;
rootlen = strlen(root);
if (ret || force)
{
if (autocomplete_scope_shown)
{
autocomplete_scope_shown = FALSE;
if (!ret)
sci_send_command(sci, SCI_AUTOCCANCEL);
}
}
else
{
ret = autocomplete_scope(editor, root, rootlen);
if (!ret && autocomplete_scope_shown)
sci_send_command(sci, SCI_AUTOCCANCEL);
autocomplete_scope_shown = ret;
}
if (!ret && rootlen > 0)
{
if (ft->id == GEANY_FILETYPES_PHP && style == SCE_HPHP_DEFAULT &&
@ -4687,12 +4789,28 @@ static gboolean editor_check_colourise(GeanyEditor *editor)
return FALSE;
doc->priv->colourise_needed = FALSE;
sci_colourise(editor->sci, 0, -1);
/* now that the current document is colourised, fold points are now accurate,
* so force an update of the current function/tag. */
symbols_get_current_function(NULL, NULL);
ui_update_statusbar(NULL, -1);
if (doc->priv->full_colourise)
{
sci_colourise(editor->sci, 0, -1);
/* now that the current document is colourised, fold points are now accurate,
* so force an update of the current function/tag. */
symbols_get_current_function(NULL, NULL);
ui_update_statusbar(NULL, -1);
}
else
{
gint start_line, end_line, start, end;
start_line = SSM(doc->editor->sci, SCI_GETFIRSTVISIBLELINE, 0, 0);
end_line = start_line + SSM(editor->sci, SCI_LINESONSCREEN, 0, 0);
start_line = SSM(editor->sci, SCI_DOCLINEFROMVISIBLE, start_line, 0);
end_line = SSM(editor->sci, SCI_DOCLINEFROMVISIBLE, end_line, 0);
start = sci_get_position_from_line(editor->sci, start_line);
end = sci_get_line_end_position(editor->sci, end_line);
sci_colourise(editor->sci, start, end);
}
return TRUE;
}

View File

@ -951,7 +951,7 @@ static void load_settings(guint ft_id, GKeyFile *config, GKeyFile *configh)
{
ft->lang = tm_source_file_get_named_lang(result);
if (ft->lang < 0)
geany_debug("Cannot find tag parser '%s' for custom filetype '%s'.", result, ft->name);
geany_debug("Cannot find tags parser '%s' for custom filetype '%s'.", result, ft->name);
g_free(result);
}

View File

@ -476,6 +476,18 @@ static void init_default_kb(void)
GDK_2, GEANY_PRIMARY_MOD_MASK, "edit_sendtocmd2", _("Send to Custom Command 2"), NULL);
add_kb(group, GEANY_KEYS_FORMAT_SENDTOCMD3, NULL,
GDK_3, GEANY_PRIMARY_MOD_MASK, "edit_sendtocmd3", _("Send to Custom Command 3"), NULL);
add_kb(group, GEANY_KEYS_FORMAT_SENDTOCMD4, NULL,
0, 0, "edit_sendtocmd4", _("Send to Custom Command 4"), NULL);
add_kb(group, GEANY_KEYS_FORMAT_SENDTOCMD5, NULL,
0, 0, "edit_sendtocmd5", _("Send to Custom Command 5"), NULL);
add_kb(group, GEANY_KEYS_FORMAT_SENDTOCMD6, NULL,
0, 0, "edit_sendtocmd6", _("Send to Custom Command 6"), NULL);
add_kb(group, GEANY_KEYS_FORMAT_SENDTOCMD7, NULL,
0, 0, "edit_sendtocmd7", _("Send to Custom Command 7"), NULL);
add_kb(group, GEANY_KEYS_FORMAT_SENDTOCMD8, NULL,
0, 0, "edit_sendtocmd8", _("Send to Custom Command 8"), NULL);
add_kb(group, GEANY_KEYS_FORMAT_SENDTOCMD9, NULL,
0, 0, "edit_sendtocmd9", _("Send to Custom Command 9"), NULL);
/* may fit better in editor group */
add_kb(group, GEANY_KEYS_FORMAT_SENDTOVTE, NULL,
0, 0, "edit_sendtovte", _("_Send Selection to Terminal"), "send_selection_to_vte1");
@ -559,10 +571,10 @@ static void init_default_kb(void)
_("Go to Pre_vious Marker"), "go_to_previous_marker1");
add_kb(group, GEANY_KEYS_GOTO_TAGDEFINITION, NULL,
GDK_t, GEANY_PRIMARY_MOD_MASK, "popup_gototagdefinition",
_("Go to Tag Definition"), "goto_tag_definition1");
_("Go to Symbol Definition"), "goto_tag_definition1");
add_kb(group, GEANY_KEYS_GOTO_TAGDECLARATION, NULL,
GDK_t, GEANY_PRIMARY_MOD_MASK | GDK_SHIFT_MASK, "popup_gototagdeclaration",
_("Go to Tag Declaration"), "goto_tag_declaration1");
_("Go to Symbol Declaration"), "goto_tag_declaration1");
add_kb(group, GEANY_KEYS_GOTO_LINESTART, NULL,
GDK_Home, 0, "edit_gotolinestart", _("Go to Start of Line"), NULL);
add_kb(group, GEANY_KEYS_GOTO_LINEEND, NULL,
@ -2431,6 +2443,30 @@ static gboolean cb_func_format_action(guint key_id)
if (ui_prefs.custom_commands && g_strv_length(ui_prefs.custom_commands) > 2)
tools_execute_custom_command(doc, ui_prefs.custom_commands[2]);
break;
case GEANY_KEYS_FORMAT_SENDTOCMD4:
if (ui_prefs.custom_commands && g_strv_length(ui_prefs.custom_commands) > 3)
tools_execute_custom_command(doc, ui_prefs.custom_commands[3]);
break;
case GEANY_KEYS_FORMAT_SENDTOCMD5:
if (ui_prefs.custom_commands && g_strv_length(ui_prefs.custom_commands) > 4)
tools_execute_custom_command(doc, ui_prefs.custom_commands[4]);
break;
case GEANY_KEYS_FORMAT_SENDTOCMD6:
if (ui_prefs.custom_commands && g_strv_length(ui_prefs.custom_commands) > 5)
tools_execute_custom_command(doc, ui_prefs.custom_commands[5]);
break;
case GEANY_KEYS_FORMAT_SENDTOCMD7:
if (ui_prefs.custom_commands && g_strv_length(ui_prefs.custom_commands) > 6)
tools_execute_custom_command(doc, ui_prefs.custom_commands[6]);
break;
case GEANY_KEYS_FORMAT_SENDTOCMD8:
if (ui_prefs.custom_commands && g_strv_length(ui_prefs.custom_commands) > 7)
tools_execute_custom_command(doc, ui_prefs.custom_commands[7]);
break;
case GEANY_KEYS_FORMAT_SENDTOCMD9:
if (ui_prefs.custom_commands && g_strv_length(ui_prefs.custom_commands) > 8)
tools_execute_custom_command(doc, ui_prefs.custom_commands[8]);
break;
case GEANY_KEYS_FORMAT_SENDTOVTE:
on_send_selection_to_vte1_activate(NULL, NULL);
break;

View File

@ -267,6 +267,12 @@ enum GeanyKeyBindingID
GEANY_KEYS_DOCUMENT_CLONE, /**< Keybinding. */
GEANY_KEYS_FILE_QUIT, /**< Keybinding. */
GEANY_KEYS_FILE_PROPERTIES, /**< Keybinding. */
GEANY_KEYS_FORMAT_SENDTOCMD4, /**< Keybinding. */
GEANY_KEYS_FORMAT_SENDTOCMD5, /**< Keybinding. */
GEANY_KEYS_FORMAT_SENDTOCMD6, /**< Keybinding. */
GEANY_KEYS_FORMAT_SENDTOCMD7, /**< Keybinding. */
GEANY_KEYS_FORMAT_SENDTOCMD8, /**< Keybinding. */
GEANY_KEYS_FORMAT_SENDTOCMD9, /**< Keybinding. */
GEANY_KEYS_COUNT /* must not be used by plugins */
};

View File

@ -119,7 +119,7 @@ static GOptionEntry entries[] =
{ "config", 'c', 0, G_OPTION_ARG_FILENAME, &alternate_config, N_("Use an alternate configuration directory"), NULL },
{ "ft-names", 0, 0, G_OPTION_ARG_NONE, &ft_names, N_("Print internal filetype names"), NULL },
{ "generate-tags", 'g', 0, G_OPTION_ARG_NONE, &generate_tags, N_("Generate global tags file (see documentation)"), NULL },
{ "no-preprocessing", 'P', 0, G_OPTION_ARG_NONE, &no_preprocessing, N_("Don't preprocess C/C++ files when generating tags"), NULL },
{ "no-preprocessing", 'P', 0, G_OPTION_ARG_NONE, &no_preprocessing, N_("Don't preprocess C/C++ files when generating tags file"), NULL },
#ifdef HAVE_SOCKET
{ "new-instance", 'i', 0, G_OPTION_ARG_NONE, &cl_options.new_instance, N_("Don't open files in a running instance, force opening a new instance"), NULL },
{ "socket-file", 0, 0, G_OPTION_ARG_FILENAME, &cl_options.socket_filename, N_("Use this socket filename for communication with a running Geany instance"), NULL },

View File

@ -175,7 +175,7 @@ static void create_default_tag_tree(void)
gtk_scrolled_window_get_hadjustment(scrolled_window),
gtk_scrolled_window_get_vadjustment(scrolled_window));
gtk_viewport_set_shadow_type(GTK_VIEWPORT(tv.default_tag_tree), GTK_SHADOW_NONE);
label = gtk_label_new(_("No tags found"));
label = gtk_label_new(_("No symbols found"));
gtk_misc_set_alignment(GTK_MISC(label), 0.1f, 0.01f);
gtk_container_add(GTK_CONTAINER(tv.default_tag_tree), label);
gtk_widget_show_all(tv.default_tag_tree);

View File

@ -1202,8 +1202,10 @@ gboolean spawn_sync(const gchar *working_directory, const gchar *command_line, g
gchar **envp, SpawnWriteData *stdin_data, GString *stdout_data, GString *stderr_data,
gint *exit_status, GError **error)
{
g_string_truncate(stdout_data, 0);
g_string_truncate(stderr_data, 0);
if (stdout_data)
g_string_truncate(stdout_data, 0);
if (stderr_data)
g_string_truncate(stderr_data, 0);
return spawn_with_callbacks(working_directory, command_line, argv, envp, SPAWN_SYNC |
SPAWN_UNBUFFERED, stdin_data ? (GIOFunc) spawn_write_data : NULL, stdin_data,

View File

@ -123,6 +123,7 @@ typedef struct StashPref StashPref;
struct StashGroup
{
guint refcount; /* ref count for GBoxed implementation */
const gchar *name; /* group name to use in the keyfile */
GPtrArray *entries; /* array of (StashPref*) */
gboolean various; /* mark group for display/edit in stash treeview */
@ -347,17 +348,27 @@ gint stash_group_save_to_file(StashGroup *group, const gchar *filename,
}
static void free_stash_pref(StashPref *pref)
{
if (pref->widget_type == GTK_TYPE_RADIO_BUTTON)
g_free(pref->extra.radio_buttons);
g_slice_free(StashPref, pref);
}
/** Creates a new group.
* @param name Name used for @c GKeyFile group.
* @return Group. */
GEANY_API_SYMBOL
StashGroup *stash_group_new(const gchar *name)
{
StashGroup *group = g_new0(StashGroup, 1);
StashGroup *group = g_slice_new0(StashGroup);
group->name = name;
group->entries = g_ptr_array_new();
group->entries = g_ptr_array_new_with_free_func((GDestroyNotify) free_stash_pref);
group->use_defaults = TRUE;
group->refcount = 1;
return group;
}
@ -386,27 +397,36 @@ void stash_group_free_settings(StashGroup *group)
}
static StashGroup *stash_group_dup(StashGroup *src)
{
g_atomic_int_inc(&src->refcount);
return src;
}
/** Frees a group.
* @param group . */
GEANY_API_SYMBOL
void stash_group_free(StashGroup *group)
{
StashPref *entry;
guint i;
foreach_ptr_array(entry, i, group->entries)
if (g_atomic_int_dec_and_test(&group->refcount))
{
if (entry->widget_type == GTK_TYPE_RADIO_BUTTON)
{
g_free(entry->extra.radio_buttons);
}
g_slice_free(StashPref, entry);
g_ptr_array_free(group->entries, TRUE);
g_slice_free(StashGroup, group);
}
g_ptr_array_free(group->entries, TRUE);
g_free(group);
}
/** Gets the GBoxed-derived GType for StashGroup
*
* @return StashGroup type . */
GEANY_API_SYMBOL
GType stash_group_get_type(void);
G_DEFINE_BOXED_TYPE(StashGroup, stash_group, stash_group_dup, stash_group_free);
/* Used for selecting groups passed to stash_tree_setup().
* @c FALSE by default. */
void stash_group_set_various(StashGroup *group, gboolean various)

View File

@ -33,6 +33,7 @@ typedef struct StashGroup StashGroup;
* stash_group_display() and stash_group_update(). */
typedef gconstpointer StashWidgetID;
GType stash_group_get_type(void);
StashGroup *stash_group_new(const gchar *name);

View File

@ -190,7 +190,7 @@ static gboolean symbols_load_global_tags(const gchar *tags_file, GeanyFiletype *
result = tm_workspace_load_global_tags(tags_file, ft->lang);
if (result)
{
geany_debug("Loaded %s (%s), %u tag(s).", tags_file, ft->name,
geany_debug("Loaded %s (%s), %u symbol(s).", tags_file, ft->name,
(guint) (get_tag_count() - old_tag_count));
}
return result;
@ -281,7 +281,7 @@ GString *symbols_find_typenames_as_string(gint lang, gboolean global)
gint tag_lang;
if (global)
typedefs = tm_tags_extract(app->tm_workspace->global_tags, TM_GLOBAL_TYPE_MASK);
typedefs = app->tm_workspace->global_typename_array;
else
typedefs = app->tm_workspace->typename_array;
@ -305,8 +305,6 @@ GString *symbols_find_typenames_as_string(gint lang, gboolean global)
}
}
}
if (typedefs && global)
g_ptr_array_free(typedefs, TRUE);
return s;
}
@ -324,31 +322,7 @@ GString *symbols_find_typenames_as_string(gint lang, gboolean global)
GEANY_API_SYMBOL
const gchar *symbols_get_context_separator(gint ft_id)
{
switch (ft_id)
{
case GEANY_FILETYPES_C: /* for C++ .h headers or C structs */
case GEANY_FILETYPES_CPP:
case GEANY_FILETYPES_GLSL: /* for structs */
/*case GEANY_FILETYPES_RUBY:*/ /* not sure what to use atm*/
case GEANY_FILETYPES_PHP:
case GEANY_FILETYPES_POWERSHELL:
case GEANY_FILETYPES_RUST:
case GEANY_FILETYPES_ZEPHIR:
return "::";
/* avoid confusion with other possible separators in group/section name */
case GEANY_FILETYPES_CONF:
case GEANY_FILETYPES_REST:
return ":::";
/* no context separator */
case GEANY_FILETYPES_ASCIIDOC:
case GEANY_FILETYPES_TXT2TAGS:
return "\x03";
default:
return ".";
}
return tm_tag_context_separator(filetypes[ft_id]->lang);
}
@ -1779,14 +1753,14 @@ int symbols_generate_global_tags(int argc, char **argv, gboolean want_preprocess
symbols_finalize(); /* free c_tags_ignore data */
if (! status)
{
g_printerr(_("Failed to create tags file, perhaps because no tags "
g_printerr(_("Failed to create tags file, perhaps because no symbols "
"were found.\n"));
return 1;
}
}
else
{
g_printerr(_("Usage: %s -g <Tag File> <File list>\n\n"), argv[0]);
g_printerr(_("Usage: %s -g <Tags File> <File list>\n\n"), argv[0]);
g_printerr(_("Example:\n"
"CFLAGS=`pkg-config gtk+-2.0 --cflags` %s -g gtk2.c.tags"
" /usr/include/gtk-2.0/gtk/gtk.h\n"), argv[0]);
@ -1801,14 +1775,14 @@ void symbols_show_load_tags_dialog(void)
GtkWidget *dialog;
GtkFileFilter *filter;
dialog = gtk_file_chooser_dialog_new(_("Load Tags"), GTK_WINDOW(main_widgets.window),
dialog = gtk_file_chooser_dialog_new(_("Load Tags File"), GTK_WINDOW(main_widgets.window),
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_OK,
NULL);
gtk_widget_set_name(dialog, "GeanyDialog");
filter = gtk_file_filter_new();
gtk_file_filter_set_name(filter, _("Geany tag files (*.*.tags)"));
gtk_file_filter_set_name(filter, _("Geany tags file (*.*.tags)"));
gtk_file_filter_add_pattern(filter, "*.*.tags");
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);

View File

@ -554,6 +554,12 @@ static void cc_insert_custom_command_items(GtkMenu *me, const gchar *label, cons
case 0: key_idx = GEANY_KEYS_FORMAT_SENDTOCMD1; break;
case 1: key_idx = GEANY_KEYS_FORMAT_SENDTOCMD2; break;
case 2: key_idx = GEANY_KEYS_FORMAT_SENDTOCMD3; break;
case 3: key_idx = GEANY_KEYS_FORMAT_SENDTOCMD4; break;
case 4: key_idx = GEANY_KEYS_FORMAT_SENDTOCMD5; break;
case 5: key_idx = GEANY_KEYS_FORMAT_SENDTOCMD6; break;
case 6: key_idx = GEANY_KEYS_FORMAT_SENDTOCMD7; break;
case 7: key_idx = GEANY_KEYS_FORMAT_SENDTOCMD8; break;
case 8: key_idx = GEANY_KEYS_FORMAT_SENDTOCMD9; break;
}
item = gtk_menu_item_new_with_label(label);

View File

@ -518,7 +518,8 @@ static const keywordDesc KeywordTable [] = {
*/
static void createTags (const unsigned int nestLevel, statementInfo *const parent);
static void copyToken (tokenInfo *const dest, const tokenInfo *const src);
static const char *getVarType (const statementInfo *const st);
static const char *getVarType (const statementInfo *const st,
const tokenInfo *const token);
/*
* FUNCTION DEFINITIONS
@ -1186,6 +1187,7 @@ static const char* accessField (const statementInfo *const st)
}
static void addOtherFields (tagEntryInfo* const tag, const tagType type,
const tokenInfo *const nameToken,
const statementInfo *const st, vString *const scope)
{
/* For selected tag types, append an extension flag designating the
@ -1254,40 +1256,90 @@ static void addOtherFields (tagEntryInfo* const tag, const tagType type,
if (((TOKEN_NAME == st->firstToken->type) || isDataTypeKeyword(st->firstToken))
&& (0 != strcmp(vStringValue(st->firstToken->name), tag->name)))
{
tag->extensionFields.varType = getVarType(st);
tag->extensionFields.varType = getVarType(st, nameToken);
}
}
}
static const char *getVarType (const statementInfo *const st)
static const char *getVarType (const statementInfo *const st,
const tokenInfo *const nameToken)
{
static vString *vt = NULL;
unsigned int i;
unsigned int end = st->tokenIndex;
boolean seenType = FALSE;
if (! st->gotArgs)
return vStringValue(st->firstToken->name); /* ignore non-functions */
switch (st->declaration) {
case DECL_BASE:
case DECL_FUNCTION:
case DECL_FUNCTION_TEMPLATE:
break;
default:
return vStringValue(st->firstToken->name);
}
if (vt == NULL)
vt = vStringNew();
else
vStringClear(vt);
/* find the end of the type signature in the token list */
for (i = 0; i < st->tokenIndex; i++)
{
const tokenInfo *const t = st->token[i];
/* stop if we find the token used to generate the tag name, or
* a name token in the middle yet not preceded by a scope separator */
if ((t == nameToken ||
(t->type == nameToken->type &&
t->keyword == nameToken->keyword &&
t->lineNumber == nameToken->lineNumber &&
strcmp(vStringValue(t->name), vStringValue(nameToken->name)) == 0)) ||
(t->type == TOKEN_NAME && seenType &&
(i > 0 && st->token[i - 1]->type != TOKEN_DOUBLE_COLON)))
{
break;
}
if (t->type != TOKEN_DOUBLE_COLON)
end = i + 1;
if (t->type == TOKEN_NAME)
seenType = TRUE;
else if (t->type == TOKEN_KEYWORD && isDataTypeKeyword(t))
seenType = TRUE;
}
/* ugly historic workaround when we can't figure out the type */
if (end < 2 && ! st->gotArgs)
return vStringValue(st->firstToken->name);
for (i = 0; i < end; i++)
{
tokenInfo *t = st->token[i];
switch (t->type)
{
case TOKEN_NAME: /* user typename */
if (strcmp(vStringValue(t->name), vStringValue(st->firstToken->name)) != 0)
continue;
break;
case TOKEN_KEYWORD:
if (t->keyword != KEYWORD_EXTERN && t->keyword != KEYWORD_STATIC) /* uninteresting keywords */
if ((t->keyword != KEYWORD_EXTERN && t->keyword != KEYWORD_STATIC) && /* uninteresting keywords */
(st->gotArgs ||
/* ignore uninteresting keywords for non-functions */
(t->keyword != KEYWORD_PUBLIC &&
t->keyword != KEYWORD_PRIVATE &&
t->keyword != KEYWORD_PROTECTED &&
t->keyword != KEYWORD_FINAL &&
t->keyword != KEYWORD_TYPEDEF &&
/* hack for D static conditions */
t->keyword != KEYWORD_IF)))
{
break;
}
continue;
case TOKEN_STAR: vStringCatS(vt, " *"); continue;
case TOKEN_ARRAY: vStringCatS(vt, "[]"); continue;
case TOKEN_DOUBLE_COLON:
vStringCatS(vt, "::");
continue;
default: continue;
}
if (vStringLength(vt) > 0)
@ -1426,7 +1478,7 @@ static void makeTag (const tokenInfo *const token,
e.type = type;
findScopeHierarchy (scope, st);
addOtherFields (&e, type, st, scope);
addOtherFields (&e, type, token, st, scope);
#ifdef DEBUG_C
printTagEntry(&e);
@ -3120,7 +3172,7 @@ static boolean findCTags (const unsigned int passCount)
contextual_fake_count = 0;
Assert (passCount < 3);
cppInit ((boolean) (passCount > 1), isLanguage (Lang_csharp));
cppInit ((boolean) (passCount > 1), isLanguage (Lang_csharp), isLanguage (Lang_cpp));
exception = (exception_t) setjmp (Exception);
retry = FALSE;

View File

@ -62,6 +62,7 @@ typedef struct sCppState {
int ungetch, ungetch2; /* ungotten characters, if any */
boolean resolveRequired; /* must resolve if/else/elif/endif branch */
boolean hasAtLiteralStrings; /* supports @"c:\" strings */
boolean hasCxxRawLiteralStrings; /* supports R"xxx(...)xxx" strings */
struct sDirective {
enum eState state; /* current directive being processed */
boolean accept; /* is a directive syntactically permitted? */
@ -83,6 +84,7 @@ static cppState Cpp = {
'\0', '\0', /* ungetch characters */
FALSE, /* resolveRequired */
FALSE, /* hasAtLiteralStrings */
FALSE, /* hasCxxRawLiteralStrings */
{
DRCTV_NONE, /* state */
FALSE, /* accept */
@ -106,7 +108,8 @@ extern unsigned int getDirectiveNestLevel (void)
return Cpp.directive.nestLevel;
}
extern void cppInit (const boolean state, const boolean hasAtLiteralStrings)
extern void cppInit (const boolean state, const boolean hasAtLiteralStrings,
const boolean hasCxxRawLiteralStrings)
{
BraceFormat = state;
@ -114,6 +117,7 @@ extern void cppInit (const boolean state, const boolean hasAtLiteralStrings)
Cpp.ungetch2 = '\0';
Cpp.resolveRequired = FALSE;
Cpp.hasAtLiteralStrings = hasAtLiteralStrings;
Cpp.hasCxxRawLiteralStrings = hasCxxRawLiteralStrings;
Cpp.directive.state = DRCTV_NONE;
Cpp.directive.accept = TRUE;
@ -533,6 +537,55 @@ static int skipToEndOfString (boolean ignoreBackslash)
return STRING_SYMBOL; /* symbolic representation of string */
}
static int isCxxRawLiteralDelimiterChar (int c)
{
return (c != ' ' && c != '\f' && c != '\n' && c != '\r' && c != '\t' && c != '\v' &&
c != '(' && c != ')' && c != '\\');
}
static int skipToEndOfCxxRawLiteralString (void)
{
int c = fileGetc ();
if (c != '(' && ! isCxxRawLiteralDelimiterChar (c))
{
fileUngetc (c);
c = skipToEndOfString (FALSE);
}
else
{
char delim[16];
unsigned int delimLen = 0;
boolean collectDelim = TRUE;
do
{
if (collectDelim)
{
if (isCxxRawLiteralDelimiterChar (c) &&
delimLen < (sizeof delim / sizeof *delim))
delim[delimLen++] = c;
else
collectDelim = FALSE;
}
else if (c == ')')
{
unsigned int i = 0;
while ((c = fileGetc ()) != EOF && i < delimLen && delim[i] == c)
i++;
if (i == delimLen && c == DOUBLE_QUOTE)
break;
else
fileUngetc (c);
}
}
while ((c = fileGetc ()) != EOF);
c = STRING_SYMBOL;
}
return c;
}
/* Skips to the end of the three (possibly four) 'c' sequence, returning a
* special character to symbolically represent a generic character.
* Also detects Vera numbers that include a base specifier (ie. 'b1010).
@ -729,6 +782,44 @@ process:
else
fileUngetc (next);
}
else if (c == 'R' && Cpp.hasCxxRawLiteralStrings)
{
/* OMG!11 HACK!!11 Get the previous character.
*
* We need to know whether the previous character was an identifier or not,
* because "R" has to be on its own, not part of an identifier. This allows
* for constructs like:
*
* #define FOUR "4"
* const char *p = FOUR"5";
*
* which is not a raw literal, but a preprocessor concatenation.
*
* FIXME: handle
*
* const char *p = R\
* "xxx(raw)xxx";
*
* which is perfectly valid (yet probably very unlikely). */
int prev = fileGetNthPrevC (1, '\0');
int prev2 = fileGetNthPrevC (2, '\0');
int prev3 = fileGetNthPrevC (3, '\0');
if (! isident (prev) ||
(! isident (prev2) && (prev == 'L' || prev == 'u' || prev == 'U')) ||
(! isident (prev3) && (prev2 == 'u' && prev == '8')))
{
int next = fileGetc ();
if (next != DOUBLE_QUOTE)
fileUngetc (next);
else
{
Cpp.directive.accept = FALSE;
c = skipToEndOfCxxRawLiteralString ();
break;
}
}
}
enter:
Cpp.directive.accept = FALSE;
if (directive)

View File

@ -36,7 +36,8 @@
*/
extern boolean isBraceFormat (void);
extern unsigned int getDirectiveNestLevel (void);
extern void cppInit (const boolean state, const boolean hasAtLiteralStrings);
extern void cppInit (const boolean state, const boolean hasAtLiteralStrings,
const boolean hasCxxRawLiteralStrings);
extern void cppTerminate (void);
extern void cppBeginStatement (void);
extern void cppEndStatement (void);

View File

@ -501,6 +501,19 @@ extern int fileGetc (void)
return c;
}
/* returns the nth previous character (0 meaning current), or def if nth cannot
* be accessed. Note that this can't access previous line data. */
extern int fileGetNthPrevC (unsigned int nth, int def)
{
const unsigned char *base = (unsigned char *) vStringValue (File.line);
const unsigned int offset = File.ungetchIdx + 1 + nth;
if (File.currentLine != NULL && File.currentLine >= base + offset)
return (int) *(File.currentLine - offset);
else
return def;
}
extern int fileSkipToCharacter (int c)
{
int d;

View File

@ -102,6 +102,7 @@ extern boolean fileOpen (const char *const fileName, const langType language);
extern boolean fileEOF (void);
extern void fileClose (void);
extern int fileGetc (void);
extern int fileGetNthPrevC (unsigned int nth, int def);
extern int fileSkipToCharacter (int c);
extern void fileUngetc (int c);
extern const unsigned char *fileReadLine (void);

View File

@ -35,6 +35,14 @@
#include "tm_source_file.h"
#include "tm_tag.h"
typedef struct
{
TMSourceFile public;
guint refcount;
} TMSourceFilePriv;
#define SOURCE_FILE_NEW(S) ((S) = g_slice_new(TMSourceFilePriv))
#define SOURCE_FILE_FREE(S) g_slice_free(TMSourceFilePriv, (TMSourceFilePriv *) S)
static TMSourceFile *current_source_file = NULL;
@ -118,8 +126,7 @@ static int tm_source_file_tags(const tagEntryInfo *tag)
/* Set the argument list of tag identified by its name */
static void tm_source_file_set_tag_arglist(const char *tag_name, const char *arglist)
{
guint count;
TMTag **tags, *tag;
guint i;
if (NULL == arglist ||
NULL == tag_name ||
@ -128,13 +135,16 @@ static void tm_source_file_set_tag_arglist(const char *tag_name, const char *arg
return;
}
tags = tm_tags_find(current_source_file->tags_array, tag_name, FALSE, FALSE,
&count);
if (tags != NULL && count == 1)
/* going in reverse order because the tag was added recently */
for (i = current_source_file->tags_array->len; i > 0; i--)
{
tag = tags[0];
g_free(tag->arglist);
tag->arglist = g_strdup(arglist);
TMTag *tag = (TMTag *) current_source_file->tags_array->pdata[i - 1];
if (g_strcmp0(tag->name, tag_name) == 0)
{
g_free(tag->arglist);
tag->arglist = g_strdup(arglist);
break;
}
}
}
@ -199,12 +209,26 @@ static gboolean tm_source_file_init(TMSourceFile *source_file, const char *file_
GEANY_API_SYMBOL
TMSourceFile *tm_source_file_new(const char *file_name, const char *name)
{
TMSourceFile *source_file = g_new(TMSourceFile, 1);
if (TRUE != tm_source_file_init(source_file, file_name, name))
TMSourceFilePriv *priv;
SOURCE_FILE_NEW(priv);
if (TRUE != tm_source_file_init(&priv->public, file_name, name))
{
g_free(source_file);
SOURCE_FILE_FREE(priv);
return NULL;
}
priv->refcount = 1;
return &priv->public;
}
static TMSourceFile *tm_source_file_dup(TMSourceFile *source_file)
{
TMSourceFilePriv *priv = (TMSourceFilePriv *) source_file;
g_return_val_if_fail(NULL != source_file, NULL);
g_atomic_int_inc(&priv->refcount);
return source_file;
}
@ -223,20 +247,34 @@ static void tm_source_file_destroy(TMSourceFile *source_file)
source_file->tags_array = NULL;
}
/** Frees a TMSourceFile structure, including all contents. Before calling this
function the TMSourceFile has to be removed from the TMWorkspace.
@param source_file The source file to free.
/** Decrements the reference count of @a source_file
*
* If the reference count drops to 0, then @a source_file is freed, including all contents.
* Make sure the @a source_file is already removed from any TMWorkSpace before the
* this happens.
* @param source_file The source file to free.
* @see tm_workspace_remove_source_file()
*/
GEANY_API_SYMBOL
void tm_source_file_free(TMSourceFile *source_file)
{
if (NULL != source_file)
TMSourceFilePriv *priv = (TMSourceFilePriv *) source_file;
if (NULL != priv && g_atomic_int_dec_and_test(&priv->refcount))
{
tm_source_file_destroy(source_file);
g_free(source_file);
SOURCE_FILE_FREE(priv);
}
}
/** Gets the GBoxed-derived GType for TMSourceFile
*
* @return TMSourceFile type . */
GEANY_API_SYMBOL
GType tm_source_file_get_type(void);
G_DEFINE_BOXED_TYPE(TMSourceFile, tm_source_file, tm_source_file_dup, tm_source_file_free);
/* Parses the text-buffer or source file and regenarates the tags.
@param source_file The source file to parse
@param text_buf The text buffer to parse

View File

@ -12,6 +12,7 @@
#include <stdio.h>
#include <glib.h>
#include <glib-object.h>
#ifndef LIBCTAGS_DEFINED
typedef int langType;
@ -44,6 +45,8 @@ typedef struct
GPtrArray *tags_array; /**< Sorted tag array obtained by parsing the object */
} TMSourceFile;
GType tm_source_file_get_type(void);
TMSourceFile *tm_source_file_new(const char *file_name, const char *name);
void tm_source_file_free(TMSourceFile *source_file);

View File

@ -17,6 +17,7 @@
#include "read.h"
#define LIBCTAGS_DEFINED
#include "tm_tag.h"
#include "tm_parser.h"
#define TAG_NEW(T) ((T) = g_slice_new0(TMTag))
@ -108,6 +109,8 @@ typedef struct
{
guint *sort_attrs;
gboolean partial;
const GPtrArray *tags_array;
gboolean first;
} TMSortOptions;
static const char *s_tag_type_names[] = {
@ -860,7 +863,7 @@ void tm_tags_remove_file_tags(TMSourceFile *source_file, GPtrArray *tags_array)
TMTag **found;
TMTag *tag = source_file->tags_array->pdata[i];
found = tm_tags_find(tags_array, tag->name, FALSE, TRUE, &tag_count);
found = tm_tags_find(tags_array, tag->name, FALSE, &tag_count);
for (j = 0; j < tag_count; j++)
{
@ -1081,85 +1084,74 @@ static gpointer binary_search(gpointer key, gpointer base, size_t nmemb,
return NULL;
}
static TMTag **tags_search(const GPtrArray *tags_array, TMTag *tag,
gboolean tags_array_sorted, TMSortOptions *sort_options)
static gint tag_search_cmp(gconstpointer ptr1, gconstpointer ptr2, gpointer user_data)
{
if (tags_array_sorted)
{ /* fast binary search on sorted tags array */
return (TMTag **) binary_search(&tag, tags_array->pdata, tags_array->len,
tm_tag_compare, sort_options);
}
else
{ /* the slow way: linear search (to make it a bit faster, search reverse assuming
* that the tag to search was added recently) */
guint i;
TMTag **t;
for (i = tags_array->len; i > 0; i--)
gint res = tm_tag_compare(ptr1, ptr2, user_data);
if (res == 0)
{
TMSortOptions *sort_options = user_data;
const GPtrArray *tags_array = sort_options->tags_array;
TMTag **tag = (TMTag **) ptr2;
/* if previous/next (depending on sort options) tag equal, we haven't
* found the first/last tag in a sequence of equal tags yet */
if (sort_options->first && ptr2 != &tags_array->pdata[0]) {
if (tm_tag_compare(ptr1, tag - 1, user_data) == 0)
return -1;
}
else if (!sort_options->first && ptr2 != &tags_array->pdata[tags_array->len-1])
{
t = (TMTag **) &tags_array->pdata[i - 1];
if (0 == tm_tag_compare(&tag, t, sort_options))
return t;
if (tm_tag_compare(ptr1, tag + 1, user_data) == 0)
return 1;
}
}
return NULL;
return res;
}
/*
Returns a pointer to the position of the first matching tag in a (sorted) tags array.
The passed array of tags should be already sorted by name for optimal performance. If
\c tags_array_sorted is set to FALSE, it may be unsorted but the lookup will be slower.
@param tags_array Tag array (may be sorted on name)
The passed array of tags must be already sorted by name (searched with binary search).
@param tags_array Tag array (sorted on name)
@param name Name of the tag to locate.
@param partial If TRUE, matches the first part of the name instead of doing exact match.
@param tags_array_sorted If TRUE, the passed \c tags_array is sorted by name so it can be
searched with binary search. Otherwise it is searched linear which is obviously slower.
@param tagCount Return location of the matched tags.
*/
TMTag **tm_tags_find(const GPtrArray *tags_array, const char *name,
gboolean partial, gboolean tags_array_sorted, guint * tagCount)
gboolean partial, guint *tagCount)
{
static TMTag *tag = NULL;
TMTag **result;
guint tagMatches=0;
TMTag *tag, **first;
TMSortOptions sort_options;
*tagCount = 0;
if ((!tags_array) || (!tags_array->len))
if (!tags_array || !tags_array->len)
return NULL;
if (NULL == tag)
tag = g_new0(TMTag, 1);
tag = g_new0(TMTag, 1);
tag->name = (char *) name;
sort_options.sort_attrs = NULL;
sort_options.partial = partial;
sort_options.tags_array = tags_array;
sort_options.first = TRUE;
first = (TMTag **)binary_search(&tag, tags_array->pdata, tags_array->len,
tag_search_cmp, &sort_options);
result = tags_search(tags_array, tag, tags_array_sorted, &sort_options);
/* There can be matches on both sides of result */
if (result)
if (first)
{
TMTag **last = (TMTag **) &tags_array->pdata[tags_array->len - 1];
TMTag **adv;
TMTag **last;
unsigned first_pos;
/* First look for any matches after result */
adv = result;
adv++;
for (; adv <= last && *adv; ++ adv)
{
if (0 != tm_tag_compare(&tag, adv, &sort_options))
break;
++tagMatches;
}
/* Now look for matches from result and below */
for (; result >= (TMTag **) tags_array->pdata; -- result)
{
if (0 != tm_tag_compare(&tag, (TMTag **) result, &sort_options))
break;
++tagMatches;
}
*tagCount=tagMatches;
++ result; /* Correct address for the last successful match */
sort_options.first = FALSE;
first_pos = first - (TMTag **)tags_array->pdata;
/* search between the first element and end */
last = (TMTag **)binary_search(&tag, first, tags_array->len - first_pos,
tag_search_cmp, &sort_options);
*tagCount = last - first + 1;
}
return (TMTag **) result;
g_free(tag);
return (TMTag **) first;
}
/* Returns TMTag which "own" given line
@ -1190,17 +1182,48 @@ tm_get_current_tag (GPtrArray * file_tags, const gulong line, const TMTagType ta
return matching_tag;
}
#if 0
/* Returns TMTag to function or method which "own" given line
@param line Current line in edited file.
@param file_tags A GPtrArray of edited file TMTag pointers.
@return TMTag pointers to owner function. */
static const TMTag *
tm_get_current_function (GPtrArray * file_tags, const gulong line)
const gchar *tm_tag_context_separator(langType lang)
{
return tm_get_current_tag (file_tags, line, tm_tag_function_t | tm_tag_method_t);
switch (lang)
{
case TM_PARSER_C: /* for C++ .h headers or C structs */
case TM_PARSER_CPP:
case TM_PARSER_GLSL: /* for structs */
/*case GEANY_FILETYPES_RUBY:*/ /* not sure what to use atm*/
case TM_PARSER_PHP:
case TM_PARSER_POWERSHELL:
case TM_PARSER_RUST:
case TM_PARSER_ZEPHIR:
return "::";
/* avoid confusion with other possible separators in group/section name */
case TM_PARSER_CONF:
case TM_PARSER_REST:
return ":::";
/* no context separator */
case TM_PARSER_ASCIIDOC:
case TM_PARSER_TXT2TAGS:
return "\x03";
default:
return ".";
}
}
gboolean tm_tag_is_anon(const TMTag *tag)
{
guint i;
char dummy;
if (tag->lang == TM_PARSER_C || tag->lang == TM_PARSER_CPP)
return sscanf(tag->name, "anon_%*[a-z]_%u%c", &i, &dummy) == 1;
else if (tag->lang == TM_PARSER_FORTRAN || tag->lang == TM_PARSER_F77)
return sscanf(tag->name, "Structure#%u%c", &i, &dummy) == 1 ||
sscanf(tag->name, "Interface#%u%c", &i, &dummy) == 1 ||
sscanf(tag->name, "Enum#%u%c", &i, &dummy) == 1;
return FALSE;
}
#endif
#ifdef TM_DEBUG /* various debugging functions */
@ -1343,11 +1366,12 @@ void tm_tags_array_print(GPtrArray *tags, FILE *fp)
*/
gint tm_tag_scope_depth(const TMTag *t)
{
const gchar *context_sep = tm_tag_context_separator(t->lang);
gint depth;
char *s;
if(!(t && t->scope))
return 0;
for (s = t->scope, depth = 0; s; s = strstr(s, "::"))
for (s = t->scope, depth = 0; s; s = strstr(s, context_sep))
{
++ depth;
++ s;

View File

@ -179,7 +179,7 @@ gboolean tm_tags_prune(GPtrArray *tags_array);
gboolean tm_tags_dedup(GPtrArray *tags_array, TMTagAttrType *sort_attributes, gboolean unref_duplicates);
TMTag **tm_tags_find(const GPtrArray *tags_array, const char *name,
gboolean partial, gboolean tags_array_sorted, guint * tagCount);
gboolean partial, guint * tagCount);
void tm_tags_array_free(GPtrArray *tags_array, gboolean free_all);
@ -191,6 +191,10 @@ TMTag *tm_tag_ref(TMTag *tag);
gboolean tm_tags_equal(const TMTag *a, const TMTag *b);
const gchar *tm_tag_context_separator(langType lang);
gboolean tm_tag_is_anon(const TMTag *tag);
#ifdef TM_DEBUG /* various debugging functions */
const char *tm_tag_type_name(const TMTag *tag);

File diff suppressed because it is too large Load Diff

View File

@ -33,6 +33,7 @@ typedef struct
GPtrArray *tags_array; /**< Sorted tags from all source files
(just pointers to source file tags, the tag objects are owned by the source files) */
GPtrArray *typename_array; /* Typename tags for syntax highlighting (pointers owned by source files) */
GPtrArray *global_typename_array; /* Like above for global tags */
} TMWorkspace;
@ -54,17 +55,14 @@ gboolean tm_workspace_load_global_tags(const char *tags_file, gint mode);
gboolean tm_workspace_create_global_tags(const char *pre_process, const char **includes,
int includes_count, const char *tags_file, int lang);
const GPtrArray *tm_workspace_find(const char *name, TMTagType type, TMTagAttrType *attrs,
gboolean partial, langType lang);
GPtrArray *tm_workspace_find(const char *name, const char *scope, TMTagType type,
TMTagAttrType *attrs, langType lang);
const GPtrArray *
tm_workspace_find_scoped (const char *name, const char *scope, TMTagType type,
TMTagAttrType *attrs, gboolean partial, langType lang, gboolean global_search);
GPtrArray *tm_workspace_find_prefix(const char *prefix, langType lang, guint max_num);
GPtrArray *tm_workspace_find_scope_members (TMSourceFile *source_file, const char *name,
gboolean function, gboolean member, const gchar *current_scope);
const GPtrArray *tm_workspace_find_scope_members(const GPtrArray *file_tags,
const char *scope_name,
gboolean find_global,
gboolean no_definitions);
void tm_workspace_add_source_file_noupdate(TMSourceFile *source_file);

View File

@ -135,6 +135,7 @@ test_sources = \
cxx11-final.cpp \
cxx11-noexcept.cpp \
cxx11-override.cpp \
cxx11-raw-strings.cpp \
cxx14-combined.cpp \
db-trig.sql \
debian_432872.f90 \
@ -301,6 +302,7 @@ test_sources = \
ui5.controller.js \
union.f \
value.f \
var-and-return-type.cpp \
whitespaces.php \
$(NULL)
test_results = $(test_sources:=.tags)

View File

@ -1,18 +1,18 @@
# format=tagmanager
aÌ64Îbit_fieldsÖ0Ïint
aÌ64Îbit_fieldsÖ0Ïunsigned int
anon_struct_0Ì2048Ö0
anon_struct_1Ì2048Ö0
anon_struct_2Ì2048Ö0
bÌ64Îbit_fieldsÖ0Ïint
bÌ64Îbit_fieldsÖ0Ïunsigned int
bad2Ì64Îanon_struct_1Ö0ÏBYTE
bit_fieldsÌ2048Ö0
bitfield_flagsÌ4096Ö0Ïanon_struct_1
cÌ64Îbit_fieldsÖ0Ïint
cÌ64Îbit_fieldsÖ0Ïunsigned int
expÌ64Îanon_struct_0Ö0
frac0Ì64Îanon_struct_0Ö0
frac1Ì64Îanon_struct_0Ö0
groupÌ64Îanon_struct_1Ö0ÏBYTE
lowerÌ64Îshortname_infoÖ0Ïchar
lowerÌ64Îshortname_infoÖ0Ïunsigned char
mystructÌ4096Ö0Ïanon_struct_2
personalÌ64Îanon_struct_1Ö0ÏBYTE
privateÌ64Îanon_struct_2Ö0ÏBYTE

View File

@ -1,4 +1,4 @@
# format=tagmanager
f1Ì16Í()Ö0Ïstd
f2Ì16Í()Ö0Ïconst std
f3Ì16Í()ÎstdÖ0Ïstd const
f1Ì16Í()Ö0Ïstd::string
f2Ì16Í()Ö0Ïconst std::string
f3Ì16Í()ÎstdÖ0Ïstd::string const

View File

@ -1,5 +1,5 @@
# format=tagmanager
m1Ì16Í()ÎC::CÖ0ÏC *C
m2Ì16Í()ÎC::CÖ0ÏC *const C
m3Ì16Í()ÎC::CÖ0ÏC const *C
m4Ì16Í()ÎC::CÖ0ÏC const *const C
m1Ì16Í()ÎC::CÖ0ÏC::T *
m2Ì16Í()ÎC::CÖ0ÏC::T *const
m3Ì16Í()ÎC::CÖ0ÏC::T const *
m4Ì16Í()ÎC::CÖ0ÏC::T const *const

View File

@ -1,4 +1,4 @@
# format=tagmanager
MajorVersionÌ64ÎmudÖ0Ïstd
MinorVersionÌ64ÎmudÖ0Ïstd
MajorVersionÌ64ÎmudÖ0Ïstd::string
MinorVersionÌ64ÎmudÖ0Ïstd::string
mudÌ256Ö0

View File

@ -4,8 +4,8 @@ B
M3_INITÌ131072Í(a, b, c)Ö0
STRINGIFYÌ131072Í(x)Ö0
STRINGIFY_INTERNÌ131072Í(x)Ö0
bufÌ64ÎstrÖ0Ïchar
lenÌ64ÎstrÖ0Ïint
bufÌ64ÎstrÖ0Ïchar *
lenÌ64ÎstrÖ0Ïunsigned int
mainÌ16Í(void)Ö0Ïint
matrix3Ì4096Ö0Ïint
sizeÌ64ÎstrÖ0Ïint

View File

@ -7,8 +7,8 @@ F
M3_INITÌ131072Í(a, b, c)Ö0
STRINGIFYÌ131072Í(x)Ö0
STRINGIFY_INTERNÌ131072Í(x)Ö0
bufÌ64ÎstrÖ0Ïchar
lenÌ64ÎstrÖ0Ïint
bufÌ64ÎstrÖ0Ïchar *
lenÌ64ÎstrÖ0Ïunsigned int
mainÌ16Í(void)Ö0Ïint
matrix3Ì4096Ö0Ïint
sizeÌ64ÎstrÖ0Ïint

View File

@ -0,0 +1,34 @@
static const char* str1 = R"blah(
lots
of text
)blah";
struct typ1 { int memb1; };
static const char* str2 = R"blah(
lots
of text including a quote"
)blah";
struct typ2 { int memb2; };
/* check we don't get confused by string concatenation */
#define FOUR "four"
static const char* str3 = FOUR"f(iv)e";
struct typ3 { int memb3; };
/* check for prefixes */
static const char* str4 = LR"blah(";int bug4;)blah";
struct typ4 { int memb4; };
static const char* str5 = u8R"blah(";int bug5;)blah";
struct typ5 { int memb5; };
static const char* str6 = uR"blah(";int bug6;)blah";
struct typ6 { int memb6; };
static const char* str7 = UR"blah(";int bug7;)blah";
struct typ7 { int memb7; };

View File

@ -0,0 +1,23 @@
# format=tagmanager
FOURÌ65536Ö0
memb1Ì64Îtyp1Ö0Ïint
memb2Ì64Îtyp2Ö0Ïint
memb3Ì64Îtyp3Ö0Ïint
memb4Ì64Îtyp4Ö0Ïint
memb5Ì64Îtyp5Ö0Ïint
memb6Ì64Îtyp6Ö0Ïint
memb7Ì64Îtyp7Ö0Ïint
str1Ì16384Ö0Ïconst char *
str2Ì16384Ö0Ïconst char *
str3Ì16384Ö0Ïconst char *
str4Ì16384Ö0Ïconst char *
str5Ì16384Ö0Ïconst char *
str6Ì16384Ö0Ïconst char *
str7Ì16384Ö0Ïconst char *
typ1Ì2048Ö0
typ2Ì2048Ö0
typ3Ì2048Ö0
typ4Ì2048Ö0
typ5Ì2048Ö0
typ6Ì2048Ö0
typ7Ì2048Ö0

View File

@ -2,4 +2,4 @@
IndexerClassÌ1Ö0
MainÌ128Í()ÎMainClassÖ0Ïpublic void
MainClassÌ1Ö0
myArrayĚ8ÎIndexerClassÖ0Ďint
myArrayĚ8ÎIndexerClassÖ0Ďint[]

View File

@ -3,4 +3,4 @@ IMyInterface
IndexerClassÌ1Ö0
MainÌ128Í()ÎMainClassÖ0Ïpublic void
MainClassÌ1Ö0
myArrayĚ8ÎIndexerClassÖ0Ďint
myArrayĚ8ÎIndexerClassÖ0Ďint[]

View File

@ -3,7 +3,7 @@ ConstTest
MainÌ128Í()ÎConstTestÖ0Ïpublic void
MyClassÌ1ÎConstTestÖ0
MyClassÌ128Í(int p1, int p2)ÎConstTest.MyClassÖ0
c1Ì8ÎConstTest.MyClassÖ0Ïint
c2Ì8ÎConstTest.MyClassÖ0Ïint
c1Ì8ÎConstTest.MyClassÖ0Ïconst int
c2Ì8ÎConstTest.MyClassÖ0Ïconst int
xÌ8ÎConstTest.MyClassÖ0Ïint
yÌ8ÎConstTest.MyClassÖ0Ïint

View File

@ -14,6 +14,6 @@ Main
SphereĚ1ÎTestClassÖ0
SphereĚ128Í(double r)ÎTestClass.SphereÖ0
TestClassĚ1Ö0
piÌ8ÎTestClass.DimensionsÖ0Ïdouble
piÌ8ÎTestClass.DimensionsÖ0Ïconst double
xĚ8ÎTestClass.DimensionsÖ0Ďdouble
yĚ8ÎTestClass.DimensionsÖ0Ďdouble

View File

@ -2,4 +2,4 @@
MainÌ128Í()ÎTestÖ0Ïpublic void
TestÌ1Ö0
TestÌ128Í(int _i)ÎTestÖ0
iĚ8ÎTestÖ0Ďint
iÌ8ÎTestÖ0Ïvolatile int

View File

@ -13,7 +13,7 @@ bar
barÌ1024Í()ÎInterfaceÖ0Ïpublic AliasInt
conditionalÌ16384Ö0ÏT
fooÌ4ÎEnumÖ0
globalVarÌ16384Ö0Ï__gshared
globalVarÌ16384Ö0Ï__gshared int
iÌ16384Ö0Ïint
mainÌ16Í(string[] args)Ö0Ïvoid
objÌ16384Ö0ÏObject

View File

@ -0,0 +1,40 @@
const volatile unsigned int func1();
const volatile unsigned int var1 = 0;
struct type1 {
unsigned int memb1;
struct type1 *next;
};
const struct type1 func2();
const struct type1 var2 = { 0, 0 };
typedef type1 type1_t;
const type1_t func3();
const type1_t var3 = { 0, 0 };
struct type1 func4();
struct type1 var4 = { 0, 0 };
type1_t func5();
type1_t var5 = { 0, 0 };
typedef unsigned long int type2_t;
/* scoped stuff */
#include <string>
const std::string func6();
const std::string var6 = "hello";
std::string func7();
std::string var7 = "hello";
/* this shows a different bug in the parser, adding scope std to the symbol.
* ignore this for now.
std::string const func8();
std::string const var8 = "hello";
*/

View File

@ -0,0 +1,20 @@
# format=tagmanager
func1Ì1024Í()Ö0Ïconst volatile unsigned int
func2Ì1024Í()Ö0Ïtype1
func3Ì1024Í()Ö0Ïconst type1_t
func4Ì1024Í()Ö0Ïtype1
func5Ì1024Í()Ö0Ïtype1_t
func6Ì1024Í()Ö0Ïconst std::string
func7Ì1024Í()Ö0Ïstd::string
memb1Ì64Îtype1Ö0Ïunsigned int
nextÌ64Îtype1Ö0Ïtype1
type1Ì2048Ö0
type1_tÌ4096Ö0Ïtype1
type2_tÌ4096Ö0Ïunsigned long int
var1Ì16384Ö0Ïconst volatile unsigned int
var2Ì16384Ö0Ïtype1
var3Ì16384Ö0Ïconst type1_t
var4Ì16384Ö0Ïtype1
var5Ì16384Ö0Ïtype1_t
var6Ì16384Ö0Ïconst std::string
var7Ì16384Ö0Ïstd::string