Merge branch 'master' into gtkbuilder
Conflicts: geany.glade src/Makefile.am src/callbacks.c
This commit is contained in:
commit
088b0bc362
1
AUTHORS
1
AUTHORS
@ -4,6 +4,7 @@ Developers:
|
||||
Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
|
||||
Colomban Wendling <lists(dot)ban(at)herbesfolles(dot)org>
|
||||
Enrico Troeger <enrico(dot)troeger(at)uvena(dot)de>
|
||||
Matthew Brush <mbrush@codebrainz.ca>
|
||||
Frank Lanitz <frank(at)frank(dot)uvena(dot)de>
|
||||
|
||||
Regular Contributors:
|
||||
|
46
HACKING
46
HACKING
@ -419,8 +419,8 @@ Programming languages should have:
|
||||
* [build_settings] for commands to run.
|
||||
|
||||
For languages with a Scintilla lexer, there should be a [styling] section,
|
||||
to correspond to the styles used in styleset_foo() in highlighting.c -
|
||||
see below.
|
||||
to correspond to the styles used in highlighting_styles_FOO[] in
|
||||
highlightingmappings.h - see below.
|
||||
|
||||
Syntax highlighting
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
@ -440,21 +440,33 @@ When adding a lexer, update:
|
||||
* wscript
|
||||
* scintilla/KeyWords.cxx - add a LINK_LEXER command *manually*
|
||||
|
||||
For syntax highlighting, you will need to edit highlighting.c and add
|
||||
the following things:
|
||||
For syntax highlighting, you will need to edit highlighting.c and
|
||||
highlightingmappings.h and add the following things:
|
||||
|
||||
1. Write styleset_foo_init() to setup lexer styles and load style
|
||||
settings from the filetypes.foo configuration file. You should probably
|
||||
start by copying and adapting another filetype's initialization, such
|
||||
as styleset_tcl_init(). You may want to use load_style_entries().
|
||||
2. Write styleset_foo() to apply styles when a new scintilla widget
|
||||
is created. Again you could copy and adapt a function like
|
||||
styleset_tcl(). You may want to use apply_style_entries().
|
||||
3. In highlighting_init_styles(), add
|
||||
``init_styleset_case(GEANY_FILETYPES_FOO, styleset_foo_init);``.
|
||||
4. In highlighting_set_styles(), add
|
||||
``styleset_case(GEANY_FILETYPES_FOO, styleset_foo);``.
|
||||
5. Write data/filetypes.foo configuration file [styling] section. See
|
||||
1. In highlightingmappings.h:
|
||||
|
||||
a. define ``highlighting_lexer_FOO`` to the Scintilla lexer ID for
|
||||
this filtype, e.g. ``SCLEX_CPP``.
|
||||
b. define the ``highlighting_styles_FOO`` array that maps Scintilla
|
||||
style states to style names in the configuration file.
|
||||
c. define ``highlighting_keywords_FOO`` to ``EMPTY_KEYWORDS`` if the
|
||||
filtype has no keywords, or as an ``HLKeyword`` array mapping
|
||||
the Scintilla keyword IDs to names in the configuration file.
|
||||
d. define ``highlighting_properties_FOO`` to ``EMPTY_PROPERTIES``, or
|
||||
as an array of ``HLProperty`` if the filetype requires some lexer
|
||||
properties to be set. However, note that properties should
|
||||
normally be set in the ``[lexer_properties]`` section of the
|
||||
configuration file instead.
|
||||
|
||||
You may look at other filtype's definitions for some examples
|
||||
(Ada, CSS or Diff being good examples).
|
||||
|
||||
2. In highlighting.c:
|
||||
|
||||
a. Add ``init_styleset_case(FOO);`` in ``highlighting_init_styles()``.
|
||||
b. Add ``styleset_case(FOO);`` in ``highlighting_set_styles()``.
|
||||
|
||||
3. Write data/filetypes.foo configuration file [styling] section. See
|
||||
the manual and see data/filetypes.d for a named style example.
|
||||
|
||||
.. note::
|
||||
@ -486,7 +498,7 @@ For brace indentation, update lexer_has_braces() in editor.c;
|
||||
indentation after ':' is done from on_new_line_added().
|
||||
|
||||
If the Scintilla lexer supports user type keyword highlighting (e.g.
|
||||
SCLEX_CPP), update document_update_type_keywords() in document.c.
|
||||
SCLEX_CPP), update document_update_tags() in document.c.
|
||||
|
||||
Adding a TagManager parser
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
3
README
3
README
@ -102,8 +102,9 @@ file.
|
||||
|
||||
|
||||
--
|
||||
2005-2011 by Enrico Tröger, Nick Treleaven, Colomban Wendling and Frank Lanitz
|
||||
2005-2011 by Enrico Tröger, Nick Treleaven, Colomban Wendling, Matthew Brush and Frank Lanitz
|
||||
enrico(dot)troeger(at)uvena(dot)de
|
||||
nick(dot)treleaven(at)btinternet(dot)com
|
||||
lists(dot)ban(at)herbesfolles(dot)org
|
||||
mbrush(at)codebrainz(dot)ca
|
||||
frank(at)frank(dot)uvena(dot)de
|
||||
|
@ -82,8 +82,9 @@ list to stay informed about major changes and of course, new releases.
|
||||
|
||||
|
||||
--
|
||||
2008-2011 by Enrico Tröger, Nick Treleaven, Colomban Wendling and Frank Lanitz
|
||||
2008-2011 by Enrico Tröger, Nick Treleaven, Colomban Wendling, Matthew Brush and Frank Lanitz
|
||||
enrico(dot)troeger(at)uvena(dot)de
|
||||
nick(dot)treleaven(at)btinternet(dot)com
|
||||
lists(dot)ban(at)herbesfolles(dot)org
|
||||
mbrush(at)codebrainz(dot)ca
|
||||
frank(at)frank(dot)uvena(dot)de
|
||||
|
@ -38,6 +38,7 @@ Make=*.mak;*.mk;GNUmakefile;makefile;Makefile;makefile.*;Makefile.*;
|
||||
Markdown=*.mdml;*.markdown;*.md;*.mkd;
|
||||
Matlab/Octave=*.m;
|
||||
NSIS=*.nsi;*.nsh;
|
||||
Objective-C=*.m;*.h;
|
||||
Pascal=*.pas;*.pp;*.inc;*.dpr;*.dpk;
|
||||
Perl=*.pl;*.perl;*.pm;*.agi;*.pod;
|
||||
PHP=*.php;*.php3;*.php4;*.php5;*.phtml;
|
||||
|
@ -1,6 +1,89 @@
|
||||
# For complete documentation of this file, please see Geany's main documentation
|
||||
[styling]
|
||||
# styling for PHP/HTML is done in filetypes.xml
|
||||
# Edit these in the colorscheme .conf file instead
|
||||
html_default=default
|
||||
html_tag=tag
|
||||
html_tagunknown=tag_unknown
|
||||
html_attribute=attribute
|
||||
html_attributeunknown=attribute_unknown
|
||||
html_number=number_1
|
||||
html_doublestring=string_1
|
||||
html_singlestring=string_1
|
||||
html_other=other
|
||||
html_comment=comment
|
||||
html_entity=entity
|
||||
html_tagend=tag_end
|
||||
html_xmlstart=tag
|
||||
html_xmlend=tag_end
|
||||
html_script=tag
|
||||
html_asp=tag
|
||||
html_aspat=tag
|
||||
html_cdata=string_2
|
||||
html_question=number_2
|
||||
html_value=value
|
||||
html_xccomment=comment
|
||||
|
||||
sgml_default=default
|
||||
sgml_comment=comment
|
||||
sgml_special=number_1
|
||||
sgml_command=number_2
|
||||
sgml_doublestring=string_1
|
||||
sgml_simplestring=string_1
|
||||
sgml_1st_param=attribute
|
||||
sgml_entity=entity
|
||||
sgml_block_default=default
|
||||
sgml_1st_param_comment=comment
|
||||
sgml_error=error
|
||||
|
||||
php_default=default
|
||||
php_simplestring=string_1
|
||||
php_hstring=string_1
|
||||
php_number=number_1
|
||||
php_word=keyword_1
|
||||
php_variable=preprocessor
|
||||
php_comment=comment
|
||||
php_commentline=comment_line
|
||||
php_operator=operator
|
||||
php_hstring_variable=string_2
|
||||
php_complex_variable=preprocessor
|
||||
|
||||
jscript_start=tag
|
||||
jscript_default=default
|
||||
jscript_comment=comment
|
||||
jscript_commentline=comment_line
|
||||
jscript_commentdoc=comment_doc
|
||||
jscript_number=number_1
|
||||
jscript_word=keyword_1
|
||||
jscript_keyword=keyword_2
|
||||
jscript_doublestring=string_1
|
||||
jscript_singlestring=string_1
|
||||
|
||||
jscript_symbols=operator
|
||||
jscript_stringeol=string_eol
|
||||
jscript_regex=regex
|
||||
|
||||
python_default=default
|
||||
python_commentline=comment_line
|
||||
python_number=number_1
|
||||
python_string=string_1
|
||||
python_character=character
|
||||
python_word=keyword_1
|
||||
python_triple=string_2
|
||||
python_tripledouble=string_2
|
||||
python_classname=type
|
||||
python_defname=function
|
||||
python_operator=operator
|
||||
python_identifier=identifier_1
|
||||
|
||||
|
||||
[keywords]
|
||||
html=a abbr acronym address applet area b base basefont bdo big blockquote body br button caption center cite code col colgroup dd del dfn dir div dl dt em embed fieldset font form frame frameset h1 h2 h3 h4 h5 h6 head hr html i iframe img input ins isindex kbd label legend li link map menu meta noframes noscript object ol optgroup option p param pre q quality s samp script select small span strike strong style sub sup table tbody td textarea tfoot th thead title tr tt u ul var xmlns leftmargin topmargin abbr accept-charset accept accesskey action align alink alt archive axis background bgcolor border cellpadding cellspacing char charoff charset checked cite class classid clear codebase codetype color cols colspan compact content coords data datafld dataformatas datapagesize datasrc datetime declare defer dir disabled enctype face for frame frameborder selected headers height href hreflang hspace http-equiv id ismap label lang language link longdesc marginwidth marginheight maxlength media framespacing method multiple name nohref noresize noshade nowrap object onblur onchange onclick ondblclick onfocus onkeydown onkeypress onkeyup onload onmousedown onmousemove onmouseover onmouseout onmouseup onreset onselect onsubmit onunload profile prompt pluginspage readonly rel rev rows rowspan rules scheme scope scrolling shape size span src standby start style summary tabindex target text title type usemap valign value valuetype version vlink vspace width text password checkbox radio submit reset file hidden image public doctype xml xml:lang article aside audio canvas command details datalist figure figcaption footer header hgroup keygen mark meter nav output progress section time video wbr async autocomplete autofocus contenteditable contextmenu draggable formaction formenctype formnovalidate formtarget list manifest max min novalidate pattern ping placeholder required reversed role sandbox scoped seamless sizes spellcheck srcdoc step ^data- ^aria-
|
||||
javascript=abs abstract acos anchor asin atan atan2 big bold boolean break byte case catch ceil char charAt charCodeAt class concat const continue cos Date debugger default delete do double else enum escape eval exp export extends false final finally fixed float floor fontcolor fontsize for fromCharCode function goto if implements import in indexOf Infinity instanceof int interface isFinite isNaN italics join lastIndexOf length link log long Math max MAX_VALUE min MIN_VALUE NaN native NEGATIVE_INFINITY new null Number package parseFloat parseInt pop POSITIVE_INFINITY pow private protected public push random return reverse round shift short sin slice small sort splice split sqrt static strike string String sub substr substring sup super switch synchronized tan this throw throws toLowerCase toString toUpperCase transient true try typeof undefined unescape unshift valueOf var void volatile while with
|
||||
vbscript=and as boolean byref byte byval call case class const continue currency date dim do double each else elseif empty end error exit false for function get global goto if in integer long loop me new next not nothing object on optional or private property public put redim rem resume select set single string sub then to true type until variant wend while with
|
||||
python=and assert break class continue complex def del elif else except exec finally for from global if import in inherit is int lambda not or pass print raise return tuple try unicode while yield long float str list
|
||||
php=abstract and array as bool boolean break case catch cfunction __class__ class clone const continue declare default die __dir__ directory do double echo else elseif empty enddeclare endfor endforeach endif endswitch endwhile eval exception exit extends false __file__ final float for foreach __function__ function goto global if implements include include_once instanceof int integer interface isset __line__ list __method__ namespace __namespace__ new null object old_function or parent php_user_filter print private protected public real require require_once resource return __sleep static stdclass string switch this throw true try unset use var __wakeup while xor insteadof trait
|
||||
sgml=ELEMENT DOCTYPE ATTLIST ENTITY NOTATION
|
||||
|
||||
|
||||
[lexer_properties]
|
||||
# default scripting language for ASP
|
||||
|
48
data/filetypes.objectivec
Normal file
48
data/filetypes.objectivec
Normal file
@ -0,0 +1,48 @@
|
||||
# For complete documentation of this file, please see Geany's main documentation
|
||||
[styling=C]
|
||||
|
||||
[keywords]
|
||||
# all items must be in one line
|
||||
primary=asm auto break case char const continue default do double else enum extern float for goto if inline int long register restrict return short signed sizeof static struct switch typedef union unsigned void volatile while FALSE NULL TRUE
|
||||
secondary=@class @defs @dynamic @encode @end @implementation @interface @optional @package @public @private @property @protocol @protected @required @selector @synthesize @synchronized
|
||||
# these are some doxygen keywords (incomplete)
|
||||
docComment=attention author brief bug class code date def enum example exception file fn namespace note param remarks return see since struct throw todo typedef var version warning union
|
||||
|
||||
[lexer_properties=C]
|
||||
|
||||
[settings]
|
||||
# default extension used when saving files
|
||||
extension=m
|
||||
|
||||
# the following characters are these which a "word" can contains, see documentation
|
||||
#wordchars=_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
|
||||
|
||||
# single comments, like # in this file
|
||||
comment_single=//
|
||||
# multiline comments
|
||||
comment_open=/*
|
||||
comment_close=*/
|
||||
|
||||
# set to false if a comment character/string should start at column 0 of a line, true uses any
|
||||
# indentation of the line, e.g. setting to true causes the following on pressing CTRL+d
|
||||
#command_example();
|
||||
# setting to false would generate this
|
||||
# command_example();
|
||||
# This setting works only for single line comments
|
||||
comment_use_indent=true
|
||||
|
||||
# context action command (please see Geany's main documentation for details)
|
||||
context_action_cmd=
|
||||
|
||||
[indentation]
|
||||
#width=4
|
||||
# 0 is spaces, 1 is tabs, 2 is tab & spaces
|
||||
#type=1
|
||||
|
||||
[build_settings]
|
||||
# %f will be replaced by the complete filename
|
||||
# %e will be replaced by the filename without extension
|
||||
# (use only one of it at one time)
|
||||
compiler=gcc -Wall -c "%f"
|
||||
linker=gcc -Wall -o "%e" "%f" -lobjc
|
||||
run_cmd="./%e"
|
@ -1,6 +1,7 @@
|
||||
# For complete documentation of this file, please see Geany's main documentation
|
||||
[styling]
|
||||
# styling for PHP/HTML is done in filetypes.xml
|
||||
[styling=HTML]
|
||||
|
||||
[keywords=HTML]
|
||||
|
||||
[lexer_properties]
|
||||
phpscript.mode=1
|
||||
|
@ -1,75 +1,7 @@
|
||||
# For complete documentation of this file, please see Geany's main documentation
|
||||
[styling]
|
||||
# Edit these in the colorscheme .conf file instead
|
||||
html_default=default
|
||||
html_tag=tag
|
||||
html_tagunknown=tag_unknown
|
||||
html_attribute=attribute
|
||||
html_attributeunknown=attribute_unknown
|
||||
html_number=number_1
|
||||
html_doublestring=string_1
|
||||
html_singlestring=string_1
|
||||
html_other=other
|
||||
html_comment=comment
|
||||
html_entity=entity
|
||||
html_tagend=tag_end
|
||||
html_xmlstart=tag
|
||||
html_xmlend=tag_end
|
||||
html_script=tag
|
||||
html_asp=tag
|
||||
html_aspat=tag
|
||||
html_cdata=string_2
|
||||
html_question=number_2
|
||||
html_value=value
|
||||
html_xccomment=comment
|
||||
|
||||
sgml_default=default
|
||||
sgml_comment=comment
|
||||
sgml_special=number_1
|
||||
sgml_command=number_2
|
||||
sgml_doublestring=string_1
|
||||
sgml_simplestring=string_1
|
||||
sgml_1st_param=attribute
|
||||
sgml_entity=entity
|
||||
sgml_block_default=default
|
||||
sgml_1st_param_comment=comment
|
||||
sgml_error=error
|
||||
|
||||
php_default=default
|
||||
php_simplestring=string_1
|
||||
php_hstring=string_1
|
||||
php_number=number_1
|
||||
php_word=keyword_1
|
||||
php_variable=preprocessor
|
||||
php_comment=comment
|
||||
php_commentline=comment_line
|
||||
php_operator=operator
|
||||
php_hstring_variable=string_2
|
||||
php_complex_variable=preprocessor
|
||||
|
||||
jscript_start=tag
|
||||
jscript_default=default
|
||||
jscript_comment=comment
|
||||
jscript_commentline=comment_line
|
||||
jscript_commentdoc=comment_doc
|
||||
jscript_number=number_1
|
||||
jscript_word=keyword_1
|
||||
jscript_keyword=keyword_2
|
||||
jscript_doublestring=string_1
|
||||
jscript_singlestring=string_1
|
||||
|
||||
jscript_symbols=operator
|
||||
jscript_stringeol=string_eol
|
||||
jscript_regex=regex
|
||||
|
||||
[keywords]
|
||||
html=a abbr acronym address applet area b base basefont bdo big blockquote body br button caption center cite code col colgroup dd del dfn dir div dl dt em embed fieldset font form frame frameset h1 h2 h3 h4 h5 h6 head hr html i iframe img input ins isindex kbd label legend li link map menu meta noframes noscript object ol optgroup option p param pre q quality s samp script select small span strike strong style sub sup table tbody td textarea tfoot th thead title tr tt u ul var xmlns leftmargin topmargin abbr accept-charset accept accesskey action align alink alt archive axis background bgcolor border cellpadding cellspacing char charoff charset checked cite class classid clear codebase codetype color cols colspan compact content coords data datafld dataformatas datapagesize datasrc datetime declare defer dir disabled enctype face for frame frameborder selected headers height href hreflang hspace http-equiv id ismap label lang language link longdesc marginwidth marginheight maxlength media framespacing method multiple name nohref noresize noshade nowrap object onblur onchange onclick ondblclick onfocus onkeydown onkeypress onkeyup onload onmousedown onmousemove onmouseover onmouseout onmouseup onreset onselect onsubmit onunload profile prompt pluginspage readonly rel rev rows rowspan rules scheme scope scrolling shape size span src standby start style summary tabindex target text title type usemap valign value valuetype version vlink vspace width text password checkbox radio submit reset file hidden image public doctype xml xml:lang article aside audio canvas command details datalist figure figcaption footer header hgroup keygen mark meter nav output progress section time video wbr async autocomplete autofocus contenteditable contextmenu draggable formaction formenctype formnovalidate formtarget list manifest max min novalidate pattern ping placeholder required reversed role sandbox scoped seamless sizes spellcheck srcdoc step ^data- ^aria-
|
||||
javascript=abs abstract acos anchor asin atan atan2 big bold boolean break byte case catch ceil char charAt charCodeAt class concat const continue cos Date debugger default delete do double else enum escape eval exp export extends false final finally fixed float floor fontcolor fontsize for fromCharCode function goto if implements import in indexOf Infinity instanceof int interface isFinite isNaN italics join lastIndexOf length link log long Math max MAX_VALUE min MIN_VALUE NaN native NEGATIVE_INFINITY new null Number package parseFloat parseInt pop POSITIVE_INFINITY pow private protected public push random return reverse round shift short sin slice small sort splice split sqrt static strike string String sub substr substring sup super switch synchronized tan this throw throws toLowerCase toString toUpperCase transient true try typeof undefined unescape unshift valueOf var void volatile while with
|
||||
vbscript=and as boolean byref byte byval call case class const continue currency date dim do double each else elseif empty end error exit false for function get global goto if in integer long loop me new next not nothing object on optional or private property public put redim rem resume select set single string sub then to true type until variant wend while with
|
||||
python=and assert break class continue complex def del elif else except exec finally for from global if import in inherit is int lambda not or pass print raise return tuple try unicode while yield long float str list
|
||||
php=abstract and array as bool boolean break case catch cfunction __class__ class clone const continue declare default die __dir__ directory do double echo else elseif empty enddeclare endfor endforeach endif endswitch endwhile eval exception exit extends false __file__ final float for foreach __function__ function goto global if implements include include_once instanceof int integer interface isset __line__ list __method__ namespace __namespace__ new null object old_function or parent php_user_filter print private protected public real require require_once resource return __sleep static stdclass string switch this throw true try unset use var __wakeup while xor insteadof trait
|
||||
sgml=ELEMENT DOCTYPE ATTLIST ENTITY NOTATION
|
||||
[styling=HTML]
|
||||
|
||||
[keywords=HTML]
|
||||
|
||||
[settings]
|
||||
# default extension used when saving files
|
||||
|
@ -1405,12 +1405,12 @@
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="check_ask_suppress_search_dialogs">
|
||||
<property name="label" translatable="yes">Always wrap search and hide the Find dialog</property>
|
||||
<object class="GtkCheckButton" id="check_always_wrap_search">
|
||||
<property name="label" translatable="yes">Always wrap search</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="tooltip_text" translatable="yes">Always wrap search around the document and hide the Find dialog after clicking Find Next/Previous</property>
|
||||
<property name="tooltip_text" translatable="yes">Always wrap search around the document</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
@ -1421,6 +1421,23 @@
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="check_hide_find_dialog">
|
||||
<property name="label" translatable="yes">Hide the Find dialog</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="tooltip_text" translatable="yes">Hide the Find dialog after clicking Find Next/Previous</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="check_search_use_current_word">
|
||||
<property name="label" translatable="yes">Use the current word under the cursor for Find dialogs</property>
|
||||
@ -1435,7 +1452,7 @@
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
@ -1451,7 +1468,7 @@
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
|
@ -60,6 +60,10 @@ Don't load plugin support.
|
||||
Print installation prefix, the data directory, the lib directory and the locale directory (in
|
||||
this order) to stdout, each per line. This is mainly intended for plugin authors to detect
|
||||
installation paths.
|
||||
.IP "\fB-r\fP, \fB\-\-read-only\fP " 10
|
||||
Open all files given on the command line in read-only mode. This only applies to files
|
||||
opened explicitly from the command line, so files from previous sessions or project
|
||||
files are unaffected.
|
||||
.IP "\fB-s\fP, \fB\-\-no-session\fP " 10
|
||||
Don't load the previous session's files.
|
||||
.IP "\fB-t\fP, \fB\-\-no-terminal\fP " 10
|
||||
|
13443
doc/geany.html
13443
doc/geany.html
File diff suppressed because it is too large
Load Diff
106
doc/geany.txt
106
doc/geany.txt
@ -245,7 +245,7 @@ On Unix-like systems this is commonly ``/usr`` if you installed from
|
||||
a binary package, or ``/usr/local`` if you build from source.
|
||||
|
||||
.. note::
|
||||
Editing system files is not necessary as you can use the
|
||||
Editing system files is not necessary as you should use the
|
||||
per-user configuration files instead, which don't need root
|
||||
permissions. See `Configuration files`_.
|
||||
|
||||
@ -362,6 +362,11 @@ Short option Long option Function
|
||||
stdout, one line each. This is mainly intended for plugin
|
||||
authors to detect installation paths.
|
||||
|
||||
-r --read-only Open all files given on the command line in read-only mode.
|
||||
This only applies to files opened explicitly from the command
|
||||
line, so files from previous sessions or project files are
|
||||
unaffected.
|
||||
|
||||
-s --no-session Do not load the previous session's files.
|
||||
|
||||
-t --no-terminal Do not load terminal support. Use this option if you do
|
||||
@ -1351,24 +1356,24 @@ in the current selection of the current document.
|
||||
Go to tag definition
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If the current word is the name of a tag definition (like a function
|
||||
body) and the file containing the tag 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.
|
||||
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
|
||||
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 current word's tag is on the current line, Geany will try
|
||||
to look for a tag declaration instead, as this is more useful.
|
||||
Likewise 'Go to tag declaration' will search for a tag definition
|
||||
in this case also.
|
||||
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
|
||||
first in this case also.
|
||||
|
||||
|
||||
Go to tag declaration
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Like Go to tag definition, but for a forward declaration such as a
|
||||
Like *Go to tag definition*, but for a forward declaration such as a
|
||||
C function prototype or ``extern`` declaration instead of a function
|
||||
body.
|
||||
|
||||
@ -1773,12 +1778,13 @@ Project files
|
||||
Path to start in when opening project files.
|
||||
|
||||
Extra plugin path
|
||||
By default Geany looks in the global installation path and in the
|
||||
configuration directory. In addition the path entered here will be searched
|
||||
for plugins. Usually you do not need to set an additional path to search for
|
||||
plugins. It might be useful when Geany is installed on a multi-user machine
|
||||
and additional plugins are available in a common location for all users.
|
||||
Leave blank to not set an additional lookup path.
|
||||
By default Geany looks in the system installation and the user
|
||||
configuration - see `Plugins`_. In addition the path entered here will be
|
||||
searched.
|
||||
Usually you do not need to set an additional path to search for
|
||||
plugins. It might be useful when Geany is installed on a multi-user machine
|
||||
and additional plugins are available in a common location for all users.
|
||||
Leave blank to not set an additional lookup path.
|
||||
|
||||
|
||||
General Miscellaneous preferences
|
||||
@ -2511,6 +2517,15 @@ send_selection_unsafe By default, Geany strips any trailing f
|
||||
If, for whatever reasons, you really want
|
||||
it to be executed directly, set this option
|
||||
to true.
|
||||
send_cmd_prefix String with which prefix the commands sent Empty immediately
|
||||
to the shell. This may be used to tell
|
||||
some shells (BASH with ``HISTCONTROL`` set
|
||||
to ``ignorespace``, ZSH with
|
||||
``HIST_IGNORE_SPACE`` enabled, etc.) from
|
||||
putting these commands in their history by
|
||||
setting this to a space. Note that leading
|
||||
spaces must be escaped using `\s` in the
|
||||
configuration file.
|
||||
**File related**
|
||||
use_atomic_file_saving Defines the mode how Geany saves files to false immediately
|
||||
disk. If disabled, Geany directly writes
|
||||
@ -3109,7 +3124,8 @@ general preference is set. There is also a command-line option,
|
||||
``-p``, which prevents plugins being loaded. Plugins are scanned in
|
||||
the following directories:
|
||||
|
||||
* ``$prefix/lib/geany`` (see `Installation prefix`_)
|
||||
* ``$prefix/lib/geany`` on Unix-like systems (see `Installation prefix`_)
|
||||
* The ``lib`` subfolder of the installation path on Windows.
|
||||
* The ``plugins`` subfolder of the user configuration directory - see
|
||||
`Configuration file paths`_.
|
||||
* The `Extra plugin path` preference (usually blank) - see `Paths`_.
|
||||
@ -3142,7 +3158,7 @@ by any custom keybindings with the same keyboard shortcut.
|
||||
Switching documents
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
There are a few non-configurable bindings to switch between documents,
|
||||
There are some non-configurable bindings to switch between documents,
|
||||
listed below. These can also be overridden by custom keybindings.
|
||||
|
||||
=============== ==================================
|
||||
@ -3150,10 +3166,10 @@ Key Action
|
||||
=============== ==================================
|
||||
Alt-[1-9] Select left-most tab, from 1 to 9.
|
||||
Alt-0 Select right-most tab.
|
||||
Ctrl-Shift-PgUp Select left-most tab.
|
||||
Ctrl-Shift-PgDn Select right-most tab.
|
||||
=============== ==================================
|
||||
|
||||
See also `Notebook tab keybindings`_.
|
||||
|
||||
|
||||
Configurable keybindings
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -3224,7 +3240,7 @@ Delete to line end Ctrl-Shift-Delete Deletes from the curre
|
||||
|
||||
Duplicate line or selection Ctrl-D Duplicates the current line or selection.
|
||||
|
||||
Transpose current line Ctrl-T Transposes the current line with the previous one.
|
||||
Transpose current line Transposes the current line with the previous one.
|
||||
|
||||
Scroll to current line Ctrl-Shift-L Scrolls the current line into the centre of the
|
||||
view. The cursor position and or an existing
|
||||
@ -3272,10 +3288,10 @@ Word part completion Tab When the autocompletio
|
||||
the currently selected item up to the next word
|
||||
part.
|
||||
|
||||
Move line(s) up Move the current line or selected lines up by
|
||||
Move line(s) up Alt-PageUp Move the current line or selected lines up by
|
||||
one line.
|
||||
|
||||
Move line(s) down Move the current line or selected lines down by
|
||||
Move line(s) down Alt-PageDown Move the current line or selected lines down by
|
||||
one line.
|
||||
=============================== ========================= ==================================================
|
||||
|
||||
@ -3428,12 +3444,12 @@ Next message Jumps to the line with
|
||||
Previous message Jumps to the line with the previous message
|
||||
in the Messages window.
|
||||
|
||||
Find Usage Finds all occurrences of the current word (near
|
||||
Find Usage Ctrl-Shift-E Finds all occurrences of the current word (near
|
||||
the keyboard cursor) or selection in all open
|
||||
documents and displays them in the messages
|
||||
window.
|
||||
|
||||
Find Document Usage Finds all occurrences of the current word (near
|
||||
Find Document Usage Ctrl-Shift-D Finds all occurrences of the current word (near
|
||||
the keyboard cursor) or selection in the current
|
||||
document and displays them in the messages
|
||||
window.
|
||||
@ -3450,11 +3466,11 @@ Go to keybindings
|
||||
=============================== ========================= ==================================================
|
||||
Action Default shortcut Description
|
||||
=============================== ========================= ==================================================
|
||||
Navigate forward a location Switches to the next location in the navigation
|
||||
Navigate forward a location Alt-Right (C) Switches to the next location in the navigation
|
||||
history. See the section called `Code Navigation
|
||||
History`_.
|
||||
|
||||
Navigate back a location Switches to the previous location in the
|
||||
Navigate back a location Alt-Left (C) Switches to the previous location in the
|
||||
navigation history. See the section called
|
||||
`Code navigation history`_.
|
||||
|
||||
@ -3473,17 +3489,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 Jump to the definition of the current word (near
|
||||
the keyboard cursor). If the definition cannot be
|
||||
found (e.g. the relevant file is not open) Geany
|
||||
will beep and do nothing. See the section called
|
||||
`Go to tag definition`_.
|
||||
Go to tag definition Ctrl-T Jump to the definition of the current word or
|
||||
selection. See `Go to tag definition`_.
|
||||
|
||||
Go to tag declaration Jump to the declaration of the current word (near
|
||||
the keyboard cursor). If the declaration cannot be
|
||||
found (e.g. the relevant file is not open) Geany
|
||||
will beep and do nothing. See the section called
|
||||
`Go to tag declaration`_.
|
||||
Go to tag declaration Ctrl-Shift-T Jump to the declaration of the current word or
|
||||
selection. See `Go to tag declaration`_.
|
||||
|
||||
Go to Start of Line Home Move the caret to the end of the line indentation
|
||||
unless it is already there, in which case it moves
|
||||
@ -3575,10 +3585,10 @@ Switch to last used document Ctrl-Tab Switches to the previo
|
||||
used document, 3rd-last, etc. Also known as
|
||||
Most-Recently-Used documents switching.
|
||||
|
||||
Move document left Alt-PageUp Changes the current document with the left hand
|
||||
Move document left Ctrl-Shift-PageUp Changes the current document with the left hand
|
||||
one.
|
||||
|
||||
Move document right Alt-PageDown Changes the current document with the right hand
|
||||
Move document right Ctrl-Shift-PageDown Changes the current document with the right hand
|
||||
one.
|
||||
|
||||
Move document first Moves the current document to the first position.
|
||||
@ -3636,7 +3646,7 @@ Make all Shift-F9 Builds the current fil
|
||||
Make custom target Ctrl-Shift-F9 Builds the current file with the Make tool and a
|
||||
given target.
|
||||
|
||||
Make object Compiles the current file with the Make tool.
|
||||
Make object Shift-F8 Compiles the current file with the Make tool.
|
||||
|
||||
Next error Jumps to the line with the next error from the
|
||||
last build process.
|
||||
@ -3703,8 +3713,16 @@ Paths on Unix-like systems
|
||||
The system path is ``$prefix/share/geany``, where ``$prefix`` is the
|
||||
path where Geany is installed (see `Installation prefix`_).
|
||||
|
||||
The user configuration directory is normally
|
||||
``/home/username/.config/geany/``.
|
||||
The user configuration directory is normally:
|
||||
``/home/username/.config/geany``
|
||||
|
||||
Paths on Windows
|
||||
^^^^^^^^^^^^^^^^
|
||||
The system path is the ``data`` subfolder of the installation path
|
||||
on Windows.
|
||||
|
||||
The user configuration directory might vary, but on Windows XP it's:
|
||||
``C:\Documents and Settings\UserName\Application Data\geany``
|
||||
|
||||
|
||||
Tools menu items
|
||||
|
@ -6,7 +6,7 @@ PREFIX = C:\libs
|
||||
RM = del
|
||||
-include ../localwin32.mk
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .dll
|
||||
.SUFFIXES: .c .o .dll
|
||||
|
||||
GTK_INCLUDES= \
|
||||
-I$(PREFIX)/include/gtk-2.0 \
|
||||
@ -46,9 +46,11 @@ endif
|
||||
|
||||
all: plugins
|
||||
|
||||
.c.dll:
|
||||
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDEDIRS) -o $@.o -c $<
|
||||
$(CC) -shared $@.o $(ALL_GTK_LIBS) $(DLL_LD_FLAGS) -o $@
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDEDIRS) -o $@ -c $<
|
||||
|
||||
.o.dll:
|
||||
$(CC) -shared $< $(ALL_GTK_LIBS) $(DLL_LD_FLAGS) -o $@
|
||||
|
||||
plugins: \
|
||||
htmlchars.dll \
|
||||
|
4
po/sv.po
4
po/sv.po
@ -4781,8 +4781,8 @@ msgid ""
|
||||
"line: %l / %L\t col: %c\t sel: %s\t %w %t %mmode: %M "
|
||||
"encoding: %e filetype: %f scope: %S"
|
||||
msgstr ""
|
||||
"rad: %d\t kolumn: %d\t vald: %d\t %s %s läge: %s kodning: %s "
|
||||
"%s filtyp: %s omfång: %s"
|
||||
"rad: %l / %L\t kol: %c\t vald: %s\t %w %t %mläge: %M "
|
||||
"kodning: %e filtyp: %f omfång: %S"
|
||||
|
||||
#. RO = read-only
|
||||
#: ../src/ui_utils.c:205 ../src/ui_utils.c:212
|
||||
|
@ -309,6 +309,7 @@ next:
|
||||
break;
|
||||
case '}':
|
||||
sc.SetState(SCE_TCL_OPERATOR);
|
||||
expected = true;
|
||||
--currentLevel;
|
||||
break;
|
||||
case '[':
|
||||
|
@ -21,6 +21,7 @@ SRCS = \
|
||||
geanyobject.c geanyobject.h \
|
||||
geanywraplabel.c geanywraplabel.h \
|
||||
highlighting.c highlighting.h \
|
||||
highlightingmappings.h \
|
||||
keybindings.c keybindings.h \
|
||||
keyfile.c keyfile.h \
|
||||
log.c log.h \
|
||||
|
10
src/about.c
10
src/about.c
@ -264,7 +264,7 @@ static GtkWidget *create_dialog(void)
|
||||
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(credits_scrollwin),
|
||||
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
|
||||
|
||||
table = gtk_table_new(20 + translators_len + prev_translators_len, 3, FALSE);
|
||||
table = gtk_table_new(23 + translators_len + prev_translators_len, 3, FALSE);
|
||||
gtk_table_set_col_spacings(GTK_TABLE(table), 10);
|
||||
|
||||
row = 0;
|
||||
@ -302,6 +302,14 @@ static GtkWidget *create_dialog(void)
|
||||
ROW("", row, 0, 0, 0, 0);
|
||||
row++;
|
||||
|
||||
g_snprintf(buffer, sizeof(buffer), "Matthew Brush - %s", _("developer"));
|
||||
ROW(buffer, row, 0, 0, 0, 1);
|
||||
row++;
|
||||
ROW("<mbrush@codebrainz.ca>", row, 0, 0, 0, 1);
|
||||
row++;
|
||||
ROW("", row, 0, 0, 0, 0);
|
||||
row++;
|
||||
|
||||
g_snprintf(buffer, sizeof(buffer), "Frank Lanitz - %s", _("translation maintainer"));
|
||||
ROW(buffer, row, 0, 0, 0, 1);
|
||||
row++;
|
||||
|
15
src/build.c
15
src/build.c
@ -1821,10 +1821,14 @@ static void on_clear_dialog_regex_row(GtkEntry *regex, gpointer unused)
|
||||
static void on_label_button_clicked(GtkWidget *wid, gpointer user_data)
|
||||
{
|
||||
RowWidgets *r = user_data;
|
||||
GtkWidget *top_level = gtk_widget_get_toplevel(wid);
|
||||
const gchar *old = gtk_button_get_label(GTK_BUTTON(wid));
|
||||
/* FIXME: we should pass either build dialog or project dialog instead of NULL for parent */
|
||||
gchar *str = dialogs_show_input(_("Set menu item label"),
|
||||
NULL, NULL, old);
|
||||
gchar *str;
|
||||
|
||||
if (GTK_WIDGET_TOPLEVEL(top_level) && GTK_IS_WINDOW(top_level))
|
||||
str = dialogs_show_input(_("Set menu item label"), GTK_WINDOW(top_level), NULL, old);
|
||||
else
|
||||
str = dialogs_show_input(_("Set menu item label"), NULL, NULL, old);
|
||||
|
||||
if (!str)
|
||||
return;
|
||||
@ -2170,8 +2174,9 @@ static gboolean read_regex(GtkWidget *regexentry, gchar **src, gchar **dst)
|
||||
if (((src == NULL /* originally there was no regex */
|
||||
|| *src == NULL) /* or it was NULL*/
|
||||
&& NZV(reg)) /* and something was typed */
|
||||
|| (src != NULL /* originally there was a regex*/
|
||||
&& strcmp(*src, reg) != 0)) /* and it has been changed */
|
||||
|| (src != NULL /* originally there was a regex*/
|
||||
&& (*src == NULL /* and either it was NULL */
|
||||
|| strcmp(*src, reg) != 0))) /* or it has been changed */
|
||||
{
|
||||
if (dst != NULL)
|
||||
{
|
||||
|
@ -621,7 +621,6 @@ G_MODULE_EXPORT void on_notebook1_switch_page_after(GtkNotebook *notebook, GtkNo
|
||||
ui_document_show_hide(doc); /* update the document menu */
|
||||
build_menu_update(doc);
|
||||
sidebar_update_tag_list(doc, FALSE);
|
||||
document_update_type_keywords(doc);
|
||||
|
||||
/* We delay the check to avoid weird fast, unintended switching of notebook pages when
|
||||
* the 'file has changed' dialog is shown while the switch event is not yet completely
|
||||
@ -1455,7 +1454,7 @@ G_MODULE_EXPORT void on_menu_comment_line1_activate(GtkMenuItem *menuitem, gpoin
|
||||
GeanyDocument *doc = document_get_current();
|
||||
g_return_if_fail(doc != NULL);
|
||||
|
||||
editor_do_comment(doc->editor, -1, FALSE, FALSE);
|
||||
editor_do_comment(doc->editor, -1, FALSE, FALSE, TRUE);
|
||||
}
|
||||
|
||||
|
||||
@ -1882,11 +1881,22 @@ G_MODULE_EXPORT void on_search1_activate(GtkMenuItem *menuitem, gpointer user_da
|
||||
}
|
||||
|
||||
|
||||
/* simple implementation (vs. close all which doesn't close documents if cancelled) */
|
||||
/* simple implementation (vs. close all which doesn't close documents if cancelled),
|
||||
* if user_data is set, it is a GtkNotebook child widget */
|
||||
G_MODULE_EXPORT void on_close_other_documents1_activate(GtkMenuItem *menuitem, gpointer user_data)
|
||||
{
|
||||
guint i;
|
||||
GeanyDocument *doc, *cur_doc = document_get_current();
|
||||
GeanyDocument *doc, *cur_doc;
|
||||
|
||||
if (user_data != NULL)
|
||||
{
|
||||
gint page_num = gtk_notebook_page_num(
|
||||
GTK_NOTEBOOK(main_widgets.notebook), GTK_WIDGET(user_data));
|
||||
cur_doc = document_get_from_page(page_num);
|
||||
}
|
||||
else
|
||||
cur_doc = document_get_current();
|
||||
|
||||
|
||||
for (i = 0; i < documents_array->len; i++)
|
||||
{
|
||||
|
@ -167,19 +167,16 @@ static void open_file_dialog_handle_response(GtkWidget *dialog, gint response)
|
||||
app->project->base_path, NULL);
|
||||
}
|
||||
|
||||
#ifndef G_VALUE_INIT
|
||||
#define G_VALUE_INIT { 0 }
|
||||
#endif
|
||||
|
||||
static void on_file_open_notify(GObject *filechooser, GParamSpec *pspec, gpointer data)
|
||||
static void on_file_open_show_hidden_notify(GObject *filechooser,
|
||||
GParamSpec *pspec, gpointer data)
|
||||
{
|
||||
GValue value = G_VALUE_INIT;
|
||||
GtkWidget *toggle_button;
|
||||
|
||||
g_value_init(&value, pspec->value_type);
|
||||
g_object_get_property(filechooser, pspec->name, &value);
|
||||
toggle_button = ui_lookup_widget(GTK_WIDGET(filechooser), "check_hidden");
|
||||
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
|
||||
ui_lookup_widget(GTK_WIDGET(filechooser), "check_hidden")), g_value_get_boolean(&value));
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle_button),
|
||||
gtk_file_chooser_get_show_hidden(GTK_FILE_CHOOSER(filechooser)));
|
||||
}
|
||||
|
||||
|
||||
@ -416,7 +413,8 @@ static GtkWidget *create_open_file_dialog(void)
|
||||
gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(encoding_combo), encoding_renderer,
|
||||
encoding_combo_cell_data_func, NULL, NULL);
|
||||
|
||||
g_signal_connect(dialog, "notify::show-hidden", G_CALLBACK(on_file_open_notify), NULL);
|
||||
g_signal_connect(dialog, "notify::show-hidden",
|
||||
G_CALLBACK(on_file_open_show_hidden_notify), NULL);
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
191
src/document.c
191
src/document.c
@ -103,7 +103,6 @@ typedef struct
|
||||
|
||||
static void document_undo_clear(GeanyDocument *doc);
|
||||
static void document_redo_add(GeanyDocument *doc, guint type, gpointer data);
|
||||
static gboolean update_tags_from_buffer(GeanyDocument *doc);
|
||||
static gboolean remove_page(guint page_num);
|
||||
|
||||
|
||||
@ -718,11 +717,10 @@ GeanyDocument *document_new_file(const gchar *utf8_filename, GeanyFiletype *ft,
|
||||
if (ft == NULL && utf8_filename != NULL) /* guess the filetype from the filename if one is given */
|
||||
ft = filetypes_detect_from_document(doc);
|
||||
|
||||
document_set_filetype(doc, ft); /* also clears taglist */
|
||||
document_set_filetype(doc, ft); /* also re-parses tags */
|
||||
|
||||
ui_set_window_title(doc);
|
||||
build_menu_update(doc);
|
||||
document_update_tag_list(doc, FALSE);
|
||||
document_set_text_changed(doc, FALSE);
|
||||
ui_document_show_hide(doc); /* update the document menu */
|
||||
|
||||
@ -1487,7 +1485,7 @@ static gsize save_convert_to_encoding(GeanyDocument *doc, gchar **data, gsize *l
|
||||
gsize bytes_read;
|
||||
gsize conv_len;
|
||||
|
||||
g_return_val_if_fail(data != NULL || *data == NULL, FALSE);
|
||||
g_return_val_if_fail(data != NULL && *data != NULL, FALSE);
|
||||
g_return_val_if_fail(len != NULL, FALSE);
|
||||
|
||||
/* try to convert it from UTF-8 to original encoding */
|
||||
@ -1941,7 +1939,7 @@ gint document_find_text(GeanyDocument *doc, const gchar *text, const gchar *orig
|
||||
}
|
||||
|
||||
/* we searched only part of the document, so ask whether to wraparound. */
|
||||
if (search_prefs.suppress_dialogs ||
|
||||
if (search_prefs.always_wrap ||
|
||||
dialogs_show_question_full(parent, GTK_STOCK_FIND, GTK_STOCK_CANCEL,
|
||||
_("Wrap search and find again?"), _("\"%s\" was not found."), original_text))
|
||||
{
|
||||
@ -2207,41 +2205,35 @@ gint document_replace_all(GeanyDocument *doc, const gchar *find_text, const gcha
|
||||
}
|
||||
|
||||
|
||||
static gboolean update_tags_from_buffer(GeanyDocument *doc)
|
||||
/*
|
||||
* Parses or re-parses the document's buffer and updates the type
|
||||
* keywords and symbol list.
|
||||
*
|
||||
* @param doc The document.
|
||||
*/
|
||||
void document_update_tags(GeanyDocument *doc)
|
||||
{
|
||||
guchar *buffer_ptr;
|
||||
gsize len;
|
||||
GString *keywords_str;
|
||||
gchar *keywords;
|
||||
gint keyword_idx;
|
||||
|
||||
len = sci_get_length(doc->editor->sci);
|
||||
g_return_if_fail(DOC_VALID(doc));
|
||||
g_return_if_fail(app->tm_workspace != NULL);
|
||||
|
||||
/* gets a direct character pointer from Scintilla.
|
||||
* this is OK because tm_source_file_buffer_update() does not modify the
|
||||
* buffer, it only requires that buffer doesn't change while it's running,
|
||||
* which it won't since it runs in this thread (ie. synchronously).
|
||||
* see tagmanager/read.c:bufferOpen */
|
||||
buffer_ptr = (guchar *) scintilla_send_message(doc->editor->sci, SCI_GETCHARACTERPOINTER, 0, 0);
|
||||
|
||||
return tm_source_file_buffer_update(doc->tm_file, buffer_ptr, len, TRUE);
|
||||
}
|
||||
|
||||
|
||||
void document_update_tag_list(GeanyDocument *doc, gboolean update)
|
||||
{
|
||||
/* We must call sidebar_update_tag_list() before returning,
|
||||
* to ensure that the symbol list is always updated properly (e.g.
|
||||
* when creating a new document with a partial filename set. */
|
||||
gboolean success = FALSE;
|
||||
|
||||
/* if the filetype doesn't have a tag parser or it is a new file */
|
||||
if (doc == NULL || doc->file_type == NULL || app->tm_workspace == NULL ||
|
||||
! filetype_has_tags(doc->file_type) || ! doc->file_name)
|
||||
/* early out if it's a new file or doesn't support tags */
|
||||
if (! doc->file_name || ! doc->file_type || !filetype_has_tags(doc->file_type))
|
||||
{
|
||||
/* set the default (empty) tag list */
|
||||
/* We must call sidebar_update_tag_list() before returning,
|
||||
* to ensure that the symbol list is always updated properly (e.g.
|
||||
* when creating a new document with a partial filename set. */
|
||||
sidebar_update_tag_list(doc, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (doc->tm_file == NULL)
|
||||
/* create a new TM file if there isn't one yet */
|
||||
if (! doc->tm_file)
|
||||
{
|
||||
gchar *locale_filename = utils_get_locale_from_utf8(doc->file_name);
|
||||
const gchar *name;
|
||||
@ -2251,28 +2243,76 @@ void document_update_tag_list(GeanyDocument *doc, gboolean update)
|
||||
doc->tm_file = tm_source_file_new(locale_filename, FALSE, name);
|
||||
g_free(locale_filename);
|
||||
|
||||
if (doc->tm_file)
|
||||
if (doc->tm_file && !tm_workspace_add_object(doc->tm_file))
|
||||
{
|
||||
if (!tm_workspace_add_object(doc->tm_file))
|
||||
{
|
||||
tm_work_object_free(doc->tm_file);
|
||||
doc->tm_file = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (update)
|
||||
update_tags_from_buffer(doc);
|
||||
success = TRUE;
|
||||
}
|
||||
tm_work_object_free(doc->tm_file);
|
||||
doc->tm_file = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
/* early out if there's no work object and we couldn't create one */
|
||||
if (doc->tm_file == NULL)
|
||||
{
|
||||
success = update_tags_from_buffer(doc);
|
||||
if (G_UNLIKELY(! success))
|
||||
geany_debug("tag list updating failed");
|
||||
/* We must call sidebar_update_tag_list() before returning,
|
||||
* to ensure that the symbol list is always updated properly (e.g.
|
||||
* when creating a new document with a partial filename set. */
|
||||
sidebar_update_tag_list(doc, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
len = sci_get_length(doc->editor->sci);
|
||||
/* tm_source_file_buffer_update() below don't support 0-length data,
|
||||
* so just empty the tags array and leave */
|
||||
if (len < 1)
|
||||
{
|
||||
tm_tags_array_free(doc->tm_file->tags_array, FALSE);
|
||||
sidebar_update_tag_list(doc, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Parse Scintilla's buffer directly using TagManager
|
||||
* Note: this buffer *MUST NOT* be modified */
|
||||
buffer_ptr = (guchar *) scintilla_send_message(doc->editor->sci, SCI_GETCHARACTERPOINTER, 0, 0);
|
||||
tm_source_file_buffer_update(doc->tm_file, buffer_ptr, len, TRUE);
|
||||
|
||||
sidebar_update_tag_list(doc, TRUE);
|
||||
|
||||
/* some filetypes support type keywords (such as struct names), but not
|
||||
* necessarily all filetypes for a particular scintilla lexer. this
|
||||
* tells us whether the filetype supports keywords, and if so
|
||||
* which index to use for the scintilla keywords set. */
|
||||
switch (doc->file_type->id)
|
||||
{
|
||||
case GEANY_FILETYPES_C:
|
||||
case GEANY_FILETYPES_CPP:
|
||||
case GEANY_FILETYPES_CS:
|
||||
case GEANY_FILETYPES_D:
|
||||
case GEANY_FILETYPES_JAVA:
|
||||
case GEANY_FILETYPES_OBJECTIVEC:
|
||||
case GEANY_FILETYPES_VALA:
|
||||
{
|
||||
|
||||
/* index of the keyword set in the Scintilla lexer, for
|
||||
* example in LexCPP.cxx, see "cppWordLists" global array.
|
||||
* TODO: this magic number should be a member of the filetype */
|
||||
keyword_idx = 3;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return; /* early out if type keywords are not supported */
|
||||
}
|
||||
|
||||
/* get any type keywords and tell scintilla about them
|
||||
* this will cause the type keywords to be colourized in scintilla */
|
||||
keywords_str = symbols_find_tags_as_string(app->tm_workspace->work_object.tags_array,
|
||||
TM_GLOBAL_TYPE_MASK, doc->file_type->lang);
|
||||
if (keywords_str)
|
||||
{
|
||||
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 */
|
||||
}
|
||||
sidebar_update_tag_list(doc, success);
|
||||
}
|
||||
|
||||
|
||||
@ -2284,9 +2324,11 @@ static gboolean on_document_update_tag_list_idle(gpointer data)
|
||||
return FALSE;
|
||||
|
||||
if (! main_status.quitting)
|
||||
document_update_tag_list(doc, TRUE);
|
||||
document_update_tags(doc);
|
||||
|
||||
doc->priv->tag_list_update_source = 0;
|
||||
|
||||
/* don't update the tags until another modification of the buffer */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -2296,59 +2338,15 @@ void document_update_tag_list_in_idle(GeanyDocument *doc)
|
||||
if (editor_prefs.autocompletion_update_freq <= 0 || ! filetype_has_tags(doc->file_type))
|
||||
return;
|
||||
|
||||
/* prevent "stacking up" callback handlers, we only need one to run soon */
|
||||
if (doc->priv->tag_list_update_source != 0)
|
||||
g_source_remove(doc->priv->tag_list_update_source);
|
||||
|
||||
doc->priv->tag_list_update_source = g_timeout_add_full(G_PRIORITY_LOW,
|
||||
editor_prefs.autocompletion_update_freq, on_document_update_tag_list_idle, doc, NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Updates the type keywords in the document's Scintilla widget.
|
||||
*
|
||||
* @param doc The document
|
||||
*/
|
||||
void document_update_type_keywords(GeanyDocument *doc)
|
||||
{
|
||||
guint keyword_idx;
|
||||
gchar *keywords;
|
||||
GString *str;
|
||||
GPtrArray *tags_array;
|
||||
|
||||
g_return_if_fail(DOC_VALID(doc));
|
||||
g_return_if_fail(app->tm_workspace != NULL);
|
||||
|
||||
switch (doc->file_type->id)
|
||||
{
|
||||
case GEANY_FILETYPES_C:
|
||||
case GEANY_FILETYPES_CPP:
|
||||
case GEANY_FILETYPES_CS:
|
||||
case GEANY_FILETYPES_D:
|
||||
case GEANY_FILETYPES_JAVA:
|
||||
case GEANY_FILETYPES_VALA:
|
||||
/* index of the keyword set in the Scintilla lexer, for
|
||||
* example in LexCPP.cxx, see "cppWordLists" global array. */
|
||||
keyword_idx = 3;
|
||||
break;
|
||||
/* early out if user type keywords are not supported */
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
tags_array = app->tm_workspace->work_object.tags_array;
|
||||
if (tags_array)
|
||||
{
|
||||
str = symbols_find_tags_as_string(tags_array, TM_GLOBAL_TYPE_MASK, doc->file_type->lang);
|
||||
if (str)
|
||||
{
|
||||
keywords = g_string_free(str, FALSE);
|
||||
sci_set_keywords(doc->editor->sci, keyword_idx, keywords);
|
||||
g_free(keywords);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void document_load_config(GeanyDocument *doc, GeanyFiletype *type,
|
||||
gboolean filetype_changed)
|
||||
{
|
||||
@ -2377,10 +2375,7 @@ static void document_load_config(GeanyDocument *doc, GeanyFiletype *type,
|
||||
doc->priv->symbol_list_sort_mode = type->priv->symbol_list_sort_mode;
|
||||
}
|
||||
|
||||
document_update_tag_list(doc, TRUE);
|
||||
|
||||
/* Update session typename keywords. */
|
||||
document_update_type_keywords(doc);
|
||||
document_update_tags(doc);
|
||||
}
|
||||
|
||||
|
||||
|
@ -232,12 +232,10 @@ gint document_replace_all(GeanyDocument *doc, const gchar *find_text, const gcha
|
||||
void document_replace_sel(GeanyDocument *doc, const gchar *find_text, const gchar *replace_text,
|
||||
const gchar *original_find_text, const gchar *original_replace_text, gint flags);
|
||||
|
||||
void document_update_tag_list(GeanyDocument *doc, gboolean update);
|
||||
void document_update_tags(GeanyDocument *doc);
|
||||
|
||||
void document_update_tag_list_in_idle(GeanyDocument *doc);
|
||||
|
||||
void document_update_type_keywords(GeanyDocument *doc);
|
||||
|
||||
void document_set_encoding(GeanyDocument *doc, const gchar *new_encoding);
|
||||
|
||||
gboolean document_check_disk_status(GeanyDocument *doc, gboolean force);
|
||||
|
93
src/editor.c
93
src/editor.c
@ -1753,14 +1753,13 @@ static gint find_previous_brace(ScintillaObject *sci, gint pos)
|
||||
|
||||
static gint find_start_bracket(ScintillaObject *sci, gint pos)
|
||||
{
|
||||
gchar c;
|
||||
gint brackets = 0;
|
||||
gint orig_pos = pos;
|
||||
|
||||
c = sci_get_char_at(sci, pos);
|
||||
while (pos > 0 && pos > orig_pos - 300)
|
||||
{
|
||||
c = sci_get_char_at(sci, pos);
|
||||
gchar c = sci_get_char_at(sci, pos);
|
||||
|
||||
if (c == ')') brackets++;
|
||||
else if (c == '(') brackets--;
|
||||
pos--;
|
||||
@ -2769,7 +2768,8 @@ static GeanyFiletype *editor_get_filetype_at_current_pos(GeanyEditor *editor)
|
||||
static void real_comment_multiline(GeanyEditor *editor, gint line_start, gint last_line)
|
||||
{
|
||||
const gchar *eol;
|
||||
gchar *str_begin, *str_end, *co, *cc;
|
||||
gchar *str_begin, *str_end;
|
||||
const gchar *co, *cc;
|
||||
gint line_len;
|
||||
GeanyFiletype *ft;
|
||||
|
||||
@ -2778,8 +2778,8 @@ static void real_comment_multiline(GeanyEditor *editor, gint line_start, gint la
|
||||
ft = editor_get_filetype_at_current_pos(editor);
|
||||
|
||||
eol = editor_get_eol_char(editor);
|
||||
co = ft->comment_open;
|
||||
cc = ft->comment_close;
|
||||
if (! filetype_get_comment_open_close(ft, FALSE, &co, &cc))
|
||||
g_return_if_reached();
|
||||
str_begin = g_strdup_printf("%s%s", (co != NULL) ? co : "", eol);
|
||||
str_end = g_strdup_printf("%s%s", (cc != NULL) ? cc : "", eol);
|
||||
|
||||
@ -2800,14 +2800,17 @@ static void real_uncomment_multiline(GeanyEditor *editor)
|
||||
gchar *linebuf;
|
||||
GeanyDocument *doc;
|
||||
GeanyFiletype *ft;
|
||||
const gchar *co, *cc;
|
||||
|
||||
g_return_if_fail(editor != NULL && editor->document->file_type != NULL);
|
||||
doc = editor->document;
|
||||
|
||||
ft = editor_get_filetype_at_current_pos(editor);
|
||||
if (! filetype_get_comment_open_close(ft, FALSE, &co, &cc))
|
||||
g_return_if_reached();
|
||||
|
||||
/* remove comment open chars */
|
||||
pos = document_find_text(doc, ft->comment_open, NULL, 0, TRUE, FALSE, NULL);
|
||||
pos = document_find_text(doc, co, NULL, 0, TRUE, FALSE, NULL);
|
||||
SSM(editor->sci, SCI_DELETEBACK, 0, 0);
|
||||
|
||||
/* check whether the line is empty and can be deleted */
|
||||
@ -2820,7 +2823,7 @@ static void real_uncomment_multiline(GeanyEditor *editor)
|
||||
g_free(linebuf);
|
||||
|
||||
/* remove comment close chars */
|
||||
pos = document_find_text(doc, ft->comment_close, NULL, 0, FALSE, FALSE, NULL);
|
||||
pos = document_find_text(doc, cc, NULL, 0, FALSE, FALSE, NULL);
|
||||
SSM(editor->sci, SCI_DELETEBACK, 0, 0);
|
||||
|
||||
/* check whether the line is empty and can be deleted */
|
||||
@ -2875,8 +2878,9 @@ gint editor_do_uncomment(GeanyEditor *editor, gint line, gboolean toggle)
|
||||
gint sel_start, sel_end;
|
||||
gint count = 0;
|
||||
gsize co_len;
|
||||
gchar sel[256], *co, *cc;
|
||||
gboolean break_loop = FALSE, single_line = FALSE;
|
||||
gchar sel[256];
|
||||
const gchar *co, *cc;
|
||||
gboolean single_line = FALSE;
|
||||
GeanyFiletype *ft;
|
||||
|
||||
g_return_val_if_fail(editor != NULL && editor->document->file_type != NULL, 0);
|
||||
@ -2901,16 +2905,8 @@ gint editor_do_uncomment(GeanyEditor *editor, gint line, gboolean toggle)
|
||||
ft = editor_get_filetype_at_current_pos(editor);
|
||||
eol_char_len = editor_get_eol_char_len(editor);
|
||||
|
||||
co = ft->comment_single;
|
||||
if (NZV(co))
|
||||
cc = NULL;
|
||||
else
|
||||
{
|
||||
co = ft->comment_open;
|
||||
cc = ft->comment_close;
|
||||
if (co == NULL)
|
||||
return 0;
|
||||
}
|
||||
if (! filetype_get_comment_open_close(ft, TRUE, &co, &cc))
|
||||
return 0;
|
||||
|
||||
co_len = strlen(co);
|
||||
if (co_len == 0)
|
||||
@ -2918,7 +2914,7 @@ gint editor_do_uncomment(GeanyEditor *editor, gint line, gboolean toggle)
|
||||
|
||||
sci_start_undo_action(editor->sci);
|
||||
|
||||
for (i = first_line; (i <= last_line) && (! break_loop); i++)
|
||||
for (i = first_line; i <= last_line; i++)
|
||||
{
|
||||
gint buf_len;
|
||||
|
||||
@ -2975,7 +2971,6 @@ gint editor_do_uncomment(GeanyEditor *editor, gint line, gboolean toggle)
|
||||
}
|
||||
|
||||
/* break because we are already on the last line */
|
||||
break_loop = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -3009,7 +3004,8 @@ void editor_do_comment_toggle(GeanyEditor *editor)
|
||||
gint x, i, line_start, line_len, first_line_start;
|
||||
gint sel_start, sel_end;
|
||||
gint count_commented = 0, count_uncommented = 0;
|
||||
gchar sel[256], *co, *cc;
|
||||
gchar sel[256];
|
||||
const gchar *co, *cc;
|
||||
gboolean break_loop = FALSE, single_line = FALSE;
|
||||
gboolean first_line_was_comment = FALSE;
|
||||
gsize co_len;
|
||||
@ -3034,16 +3030,8 @@ void editor_do_comment_toggle(GeanyEditor *editor)
|
||||
|
||||
ft = editor_get_filetype_at_current_pos(editor);
|
||||
|
||||
co = ft->comment_single;
|
||||
if (NZV(co))
|
||||
cc = NULL;
|
||||
else
|
||||
{
|
||||
co = ft->comment_open;
|
||||
cc = ft->comment_close;
|
||||
if (co == NULL)
|
||||
return;
|
||||
}
|
||||
if (! filetype_get_comment_open_close(ft, TRUE, &co, &cc))
|
||||
return;
|
||||
|
||||
co_len = strlen(co);
|
||||
if (co_len == 0)
|
||||
@ -3089,7 +3077,7 @@ void editor_do_comment_toggle(GeanyEditor *editor)
|
||||
}
|
||||
|
||||
/* we are still here, so the above lines were not already comments, so comment it */
|
||||
editor_do_comment(editor, i, TRUE, TRUE);
|
||||
editor_do_comment(editor, i, TRUE, TRUE, TRUE);
|
||||
count_commented++;
|
||||
}
|
||||
/* use multi line comment */
|
||||
@ -3165,12 +3153,14 @@ void editor_do_comment_toggle(GeanyEditor *editor)
|
||||
|
||||
|
||||
/* set toggle to TRUE if the caller is the toggle function, FALSE otherwise */
|
||||
void editor_do_comment(GeanyEditor *editor, gint line, gboolean allow_empty_lines, gboolean toggle)
|
||||
void editor_do_comment(GeanyEditor *editor, gint line, gboolean allow_empty_lines, gboolean toggle,
|
||||
gboolean single_comment)
|
||||
{
|
||||
gint first_line, last_line, eol_char_len;
|
||||
gint x, i, line_start, line_len;
|
||||
gint sel_start, sel_end, co_len;
|
||||
gchar sel[256], *co, *cc;
|
||||
gchar sel[256];
|
||||
const gchar *co, *cc;
|
||||
gboolean break_loop = FALSE, single_line = FALSE;
|
||||
GeanyFiletype *ft;
|
||||
|
||||
@ -3197,16 +3187,8 @@ void editor_do_comment(GeanyEditor *editor, gint line, gboolean allow_empty_line
|
||||
|
||||
ft = editor_get_filetype_at_current_pos(editor);
|
||||
|
||||
co = ft->comment_single;
|
||||
if (NZV(co))
|
||||
cc = NULL;
|
||||
else
|
||||
{
|
||||
co = ft->comment_open;
|
||||
cc = ft->comment_close;
|
||||
if (co == NULL)
|
||||
return;
|
||||
}
|
||||
if (! filetype_get_comment_open_close(ft, single_comment, &co, &cc))
|
||||
return;
|
||||
|
||||
co_len = strlen(co);
|
||||
if (co_len == 0)
|
||||
@ -3234,7 +3216,7 @@ void editor_do_comment(GeanyEditor *editor, gint line, gboolean allow_empty_line
|
||||
if (allow_empty_lines || (x < line_len && sel[x] != '\0'))
|
||||
{
|
||||
/* use single line comment */
|
||||
if (cc == NULL || cc[0] == '\0')
|
||||
if (! NZV(cc))
|
||||
{
|
||||
gint start = line_start;
|
||||
single_line = TRUE;
|
||||
@ -3495,18 +3477,19 @@ void editor_insert_multiline_comment(GeanyEditor *editor)
|
||||
gint pos;
|
||||
gboolean have_multiline_comment = FALSE;
|
||||
GeanyDocument *doc;
|
||||
const gchar *co, *cc;
|
||||
|
||||
g_return_if_fail(editor != NULL && editor->document->file_type != NULL &&
|
||||
(editor->document->file_type->comment_open != NULL ||
|
||||
editor->document->file_type->comment_single != NULL));
|
||||
g_return_if_fail(editor != NULL && editor->document->file_type != NULL);
|
||||
|
||||
if (! filetype_get_comment_open_close(editor->document->file_type, FALSE, &co, &cc))
|
||||
g_return_if_reached();
|
||||
if (NZV(cc))
|
||||
have_multiline_comment = TRUE;
|
||||
|
||||
sci_start_undo_action(editor->sci);
|
||||
|
||||
doc = editor->document;
|
||||
|
||||
if (NZV(doc->file_type->comment_close))
|
||||
have_multiline_comment = TRUE;
|
||||
|
||||
/* insert three lines one line above of the current position */
|
||||
line = sci_get_line_from_position(editor->sci, editor_info.click_pos);
|
||||
pos = sci_get_position_from_line(editor->sci, line);
|
||||
@ -3532,10 +3515,10 @@ void editor_insert_multiline_comment(GeanyEditor *editor)
|
||||
sci_set_selection_start(editor->sci, pos);
|
||||
sci_set_selection_end(editor->sci, pos + text_len);
|
||||
|
||||
editor_do_comment(editor, -1, TRUE, FALSE);
|
||||
editor_do_comment(editor, -1, TRUE, FALSE, FALSE);
|
||||
|
||||
/* set the current position to the start of the first inserted line */
|
||||
pos += strlen(doc->file_type->comment_open);
|
||||
pos += strlen(co);
|
||||
|
||||
/* on multi line comment jump to the next line, otherwise add the length of added indentation */
|
||||
if (have_multiline_comment)
|
||||
|
@ -202,7 +202,8 @@ gboolean editor_show_calltip(GeanyEditor *editor, gint pos);
|
||||
|
||||
void editor_do_comment_toggle(GeanyEditor *editor);
|
||||
|
||||
void editor_do_comment(GeanyEditor *editor, gint line, gboolean allow_empty_lines, gboolean toggle);
|
||||
void editor_do_comment(GeanyEditor *editor, gint line, gboolean allow_empty_lines, gboolean toggle,
|
||||
gboolean single_comment);
|
||||
|
||||
gint editor_do_uncomment(GeanyEditor *editor, gint line, gboolean toggle);
|
||||
|
||||
|
@ -118,6 +118,14 @@ static void init_builtin_filetypes(void)
|
||||
ft->mime_type = g_strdup("text/x-c++src");
|
||||
ft->group = GEANY_FILETYPE_GROUP_COMPILED;
|
||||
|
||||
#define OBJECTIVEC
|
||||
ft = filetypes[GEANY_FILETYPES_OBJECTIVEC];
|
||||
ft->lang = 42;
|
||||
ft->name = g_strdup("Objective-C");
|
||||
filetype_make_title(ft, TITLE_SOURCE_FILE);
|
||||
ft->mime_type = g_strdup("text/x-objc");
|
||||
ft->group = GEANY_FILETYPE_GROUP_COMPILED;
|
||||
|
||||
#define CS
|
||||
ft = filetypes[GEANY_FILETYPES_CS];
|
||||
ft->lang = 25;
|
||||
@ -954,7 +962,8 @@ static GeanyFiletype *find_shebang(const gchar *utf8_filename, const gchar *line
|
||||
}
|
||||
|
||||
|
||||
/* Detect the filetype checking for a shebang, then filename extension. */
|
||||
/* Detect the filetype checking for a shebang, then filename extension.
|
||||
* @lines: an strv of the lines to scan (must containing at least one line) */
|
||||
static GeanyFiletype *filetypes_detect_from_file_internal(const gchar *utf8_filename,
|
||||
gchar **lines)
|
||||
{
|
||||
@ -962,7 +971,7 @@ static GeanyFiletype *filetypes_detect_from_file_internal(const gchar *utf8_file
|
||||
gint i;
|
||||
GRegex *ft_regex;
|
||||
GMatchInfo *match;
|
||||
GError *regerr = NULL;
|
||||
GError *regex_error = NULL;
|
||||
|
||||
/* try to find a shebang and if found use it prior to the filename extension
|
||||
* also checks for <?xml */
|
||||
@ -971,13 +980,11 @@ static GeanyFiletype *filetypes_detect_from_file_internal(const gchar *utf8_file
|
||||
return ft;
|
||||
|
||||
/* try to extract the filetype using a regex capture */
|
||||
ft_regex = g_regex_new( file_prefs.extract_filetype_regex,
|
||||
G_REGEX_RAW | G_REGEX_MULTILINE,
|
||||
0,
|
||||
®err);
|
||||
if (regerr == NULL)
|
||||
ft_regex = g_regex_new(file_prefs.extract_filetype_regex,
|
||||
G_REGEX_RAW | G_REGEX_MULTILINE, 0, ®ex_error);
|
||||
if (ft_regex != NULL)
|
||||
{
|
||||
for (i = 0; i < GEANY_FILETYPE_SEARCH_LINES; i++)
|
||||
for (i = 0; ft == NULL && lines[i] != NULL; i++)
|
||||
{
|
||||
if (g_regex_match(ft_regex, lines[i], 0, &match))
|
||||
{
|
||||
@ -989,15 +996,14 @@ static GeanyFiletype *filetypes_detect_from_file_internal(const gchar *utf8_file
|
||||
}
|
||||
}
|
||||
g_match_info_free(match);
|
||||
if (ft != NULL)
|
||||
break;
|
||||
}
|
||||
g_regex_unref(ft_regex);
|
||||
}
|
||||
else
|
||||
else if (regex_error != NULL)
|
||||
{
|
||||
g_error_free(regerr);
|
||||
geany_debug("Filetype extract regex ignored: %s", regex_error->message);
|
||||
g_error_free(regex_error);
|
||||
}
|
||||
g_regex_unref(ft_regex);
|
||||
if (ft != NULL)
|
||||
return ft;
|
||||
|
||||
@ -1012,7 +1018,7 @@ static GeanyFiletype *filetypes_detect_from_file_internal(const gchar *utf8_file
|
||||
GeanyFiletype *filetypes_detect_from_document(GeanyDocument *doc)
|
||||
{
|
||||
GeanyFiletype *ft;
|
||||
gchar *lines[GEANY_FILETYPE_SEARCH_LINES];
|
||||
gchar *lines[GEANY_FILETYPE_SEARCH_LINES + 1];
|
||||
gint i;
|
||||
|
||||
if (doc == NULL)
|
||||
@ -1022,6 +1028,7 @@ GeanyFiletype *filetypes_detect_from_document(GeanyDocument *doc)
|
||||
{
|
||||
lines[i] = sci_get_line(doc->editor->sci, i);
|
||||
}
|
||||
lines[i] = NULL;
|
||||
ft = filetypes_detect_from_file_internal(doc->file_name, lines);
|
||||
for (i = 0; i < GEANY_FILETYPE_SEARCH_LINES; ++i)
|
||||
{
|
||||
@ -1044,10 +1051,9 @@ GeanyFiletype *filetypes_detect_from_document(GeanyDocument *doc)
|
||||
GeanyFiletype *filetypes_detect_from_file(const gchar *utf8_filename)
|
||||
{
|
||||
gchar line[1024];
|
||||
gchar *lines[GEANY_FILETYPE_SEARCH_LINES];
|
||||
gchar *lines[2];
|
||||
FILE *f;
|
||||
gchar *locale_name = utils_get_locale_from_utf8(utf8_filename);
|
||||
gint i;
|
||||
|
||||
f = g_fopen(locale_name, "r");
|
||||
g_free(locale_name);
|
||||
@ -1056,11 +1062,8 @@ GeanyFiletype *filetypes_detect_from_file(const gchar *utf8_filename)
|
||||
if (fgets(line, sizeof(line), f) != NULL)
|
||||
{
|
||||
fclose(f);
|
||||
for (i = 0; i < GEANY_FILETYPE_SEARCH_LINES; ++i)
|
||||
{
|
||||
lines[i] = NULL;
|
||||
}
|
||||
lines[0] = line;
|
||||
lines[1] = NULL;
|
||||
return filetypes_detect_from_file_internal(utf8_filename, lines);
|
||||
}
|
||||
fclose(f);
|
||||
@ -1430,6 +1433,8 @@ static gchar *filetypes_get_conf_extension(const GeanyFiletype *ft)
|
||||
case GEANY_FILETYPES_NONE: result = g_strdup("common"); break;
|
||||
/* name is Matlab/Octave */
|
||||
case GEANY_FILETYPES_MATLAB: result = g_strdup("matlab"); break;
|
||||
/* name is Objective-C, and we don't want the hyphen */
|
||||
case GEANY_FILETYPES_OBJECTIVEC: result = g_strdup("objectivec"); break;
|
||||
default:
|
||||
result = g_ascii_strdown(ft->name, -1);
|
||||
break;
|
||||
@ -1786,3 +1791,40 @@ const gchar *filetypes_get_display_name(GeanyFiletype *ft)
|
||||
{
|
||||
return ft->id == GEANY_FILETYPES_NONE ? _("None") : ft->name;
|
||||
}
|
||||
|
||||
|
||||
/* gets comment_open/comment_close/comment_single strings from the filetype
|
||||
* @param single_first: whether single comment is preferred if both available
|
||||
* returns true if at least comment_open is set, false otherwise */
|
||||
gboolean filetype_get_comment_open_close(const GeanyFiletype *ft, gboolean single_first,
|
||||
const gchar **co, const gchar **cc)
|
||||
{
|
||||
g_return_val_if_fail(ft != NULL, FALSE);
|
||||
g_return_val_if_fail(co != NULL, FALSE);
|
||||
g_return_val_if_fail(cc != NULL, FALSE);
|
||||
|
||||
if (single_first)
|
||||
{
|
||||
*co = ft->comment_single;
|
||||
if (NZV(*co))
|
||||
*cc = NULL;
|
||||
else
|
||||
{
|
||||
*co = ft->comment_open;
|
||||
*cc = ft->comment_close;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*co = ft->comment_open;
|
||||
if (NZV(*co))
|
||||
*cc = ft->comment_close;
|
||||
else
|
||||
{
|
||||
*co = ft->comment_single;
|
||||
*cc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return NZV(*co);
|
||||
}
|
||||
|
@ -87,6 +87,7 @@ typedef enum
|
||||
GEANY_FILETYPES_LISP,
|
||||
GEANY_FILETYPES_ERLANG,
|
||||
GEANY_FILETYPES_COBOL,
|
||||
GEANY_FILETYPES_OBJECTIVEC,
|
||||
/* ^ append items here */
|
||||
GEANY_MAX_BUILT_IN_FILETYPES /* Don't use this, use filetypes_array->len instead */
|
||||
}
|
||||
@ -208,4 +209,7 @@ gboolean filetype_has_tags(GeanyFiletype *ft);
|
||||
gboolean filetypes_parse_error_message(GeanyFiletype *ft, const gchar *message,
|
||||
gchar **filename, gint *line);
|
||||
|
||||
gboolean filetype_get_comment_open_close(const GeanyFiletype *ft, gboolean single_first,
|
||||
const gchar **co, const gchar **cc);
|
||||
|
||||
#endif
|
||||
|
@ -20,8 +20,8 @@
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __GEANY_ENTRY_ACTION_H__
|
||||
#define __GEANY_ENTRY_ACTION_H__
|
||||
#ifndef GEANY_ENTRY_ACTION_H
|
||||
#define GEANY_ENTRY_ACTION_H
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -60,4 +60,4 @@ GtkWidget* geany_entry_action_get_menu (GeanyEntryAction *action);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEANY_ENTRY_ACTION_H__ */
|
||||
#endif /* GEANY_ENTRY_ACTION_H */
|
||||
|
@ -20,8 +20,8 @@
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __GEANY_MENU_BUTTON_ACTION_H__
|
||||
#define __GEANY_MENU_BUTTON_ACTION_H__
|
||||
#ifndef GEANY_MENU_BUTTON_ACTION_H
|
||||
#define GEANY_MENU_BUTTON_ACTION_H
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -63,4 +63,4 @@ void geany_menu_button_action_set_menu (GeanyMenubuttonAction *action, GtkWidge
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEANY_MENU_BUTTON_ACTION_H__ */
|
||||
#endif /* GEANY_MENU_BUTTON_ACTION_H */
|
||||
|
@ -21,8 +21,8 @@
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __GEANYOBJECT_H__
|
||||
#define __GEANYOBJECT_H__
|
||||
#ifndef GEANYOBJECT_H
|
||||
#define GEANYOBJECT_H
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
@ -105,4 +105,4 @@ GObject* geany_object_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEANYOBJECT_H__ */
|
||||
#endif /* GEANYOBJECT_H */
|
||||
|
@ -19,8 +19,8 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GEANY_WRAP_LABEL_H__
|
||||
#define __GEANY_WRAP_LABEL_H__
|
||||
#ifndef GEANY_WRAP_LABEL_H
|
||||
#define GEANY_WRAP_LABEL_H
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -45,4 +45,4 @@ GtkWidget* geany_wrap_label_new (const gchar *text);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GEANY_WRAP_LABEL_H__ */
|
||||
#endif /* GEANY_WRAP_LABEL_H */
|
||||
|
2813
src/highlighting.c
2813
src/highlighting.c
File diff suppressed because it is too large
Load Diff
1416
src/highlightingmappings.h
Normal file
1416
src/highlightingmappings.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -2574,7 +2574,8 @@ create_prefs_dialog (void)
|
||||
GtkWidget *frame36;
|
||||
GtkWidget *alignment39;
|
||||
GtkWidget *vbox36;
|
||||
GtkWidget *check_ask_suppress_search_dialogs;
|
||||
GtkWidget *check_always_wrap_search;
|
||||
GtkWidget *check_hide_find_dialog;
|
||||
GtkWidget *check_search_use_current_word;
|
||||
GtkWidget *check_fif_current_dir;
|
||||
GtkWidget *label215;
|
||||
@ -3195,10 +3196,15 @@ create_prefs_dialog (void)
|
||||
gtk_widget_show (vbox36);
|
||||
gtk_container_add (GTK_CONTAINER (alignment39), vbox36);
|
||||
|
||||
check_ask_suppress_search_dialogs = gtk_check_button_new_with_mnemonic (_("Always wrap search and hide the Find dialog"));
|
||||
gtk_widget_show (check_ask_suppress_search_dialogs);
|
||||
gtk_box_pack_start (GTK_BOX (vbox36), check_ask_suppress_search_dialogs, FALSE, FALSE, 0);
|
||||
gtk_tooltips_set_tip (tooltips, check_ask_suppress_search_dialogs, _("Always wrap search around the document and hide the Find dialog after clicking Find Next/Previous"), NULL);
|
||||
check_always_wrap_search = gtk_check_button_new_with_mnemonic (_("Always wrap search"));
|
||||
gtk_widget_show (check_always_wrap_search);
|
||||
gtk_box_pack_start (GTK_BOX (vbox36), check_always_wrap_search, FALSE, FALSE, 0);
|
||||
gtk_tooltips_set_tip (tooltips, check_always_wrap_search, _("Always wrap search around the document"), NULL);
|
||||
|
||||
check_hide_find_dialog = gtk_check_button_new_with_mnemonic (_("Hide the Find dialog"));
|
||||
gtk_widget_show (check_hide_find_dialog);
|
||||
gtk_box_pack_start (GTK_BOX (vbox36), check_hide_find_dialog, FALSE, FALSE, 0);
|
||||
gtk_tooltips_set_tip (tooltips, check_hide_find_dialog, _("Hide the Find dialog after clicking Find Next/Previous"), NULL);
|
||||
|
||||
check_search_use_current_word = gtk_check_button_new_with_mnemonic (_("Use the current word under the cursor for Find dialogs"));
|
||||
gtk_widget_show (check_search_use_current_word);
|
||||
@ -5185,7 +5191,8 @@ create_prefs_dialog (void)
|
||||
GLADE_HOOKUP_OBJECT (prefs_dialog, frame36, "frame36");
|
||||
GLADE_HOOKUP_OBJECT (prefs_dialog, alignment39, "alignment39");
|
||||
GLADE_HOOKUP_OBJECT (prefs_dialog, vbox36, "vbox36");
|
||||
GLADE_HOOKUP_OBJECT (prefs_dialog, check_ask_suppress_search_dialogs, "check_ask_suppress_search_dialogs");
|
||||
GLADE_HOOKUP_OBJECT (prefs_dialog, check_always_wrap_search, "check_always_wrap_search");
|
||||
GLADE_HOOKUP_OBJECT (prefs_dialog, check_hide_find_dialog, "check_hide_find_dialog");
|
||||
GLADE_HOOKUP_OBJECT (prefs_dialog, check_search_use_current_word, "check_search_use_current_word");
|
||||
GLADE_HOOKUP_OBJECT (prefs_dialog, check_fif_current_dir, "check_fif_current_dir");
|
||||
GLADE_HOOKUP_OBJECT (prefs_dialog, label215, "label215");
|
||||
|
@ -290,7 +290,7 @@ static void init_default_kb(void)
|
||||
_("Delete to line end"), NULL);
|
||||
/* transpose may fit better in format group */
|
||||
keybindings_set_item(group, GEANY_KEYS_EDITOR_TRANSPOSELINE, NULL,
|
||||
GDK_t, GDK_CONTROL_MASK, "edit_transposeline", _("_Transpose Current Line"),
|
||||
0, 0, "edit_transposeline", _("_Transpose Current Line"),
|
||||
LW(transpose_current_line1));
|
||||
keybindings_set_item(group, GEANY_KEYS_EDITOR_SCROLLTOLINE, NULL,
|
||||
GDK_l, GDK_SHIFT_MASK | GDK_CONTROL_MASK, "edit_scrolltoline", _("Scroll to current line"), NULL);
|
||||
@ -315,9 +315,9 @@ static void init_default_kb(void)
|
||||
keybindings_set_item(group, GEANY_KEYS_EDITOR_WORDPARTCOMPLETION, NULL,
|
||||
GDK_Tab, 0, "edit_wordpartcompletion", _("Word part completion"), NULL);
|
||||
keybindings_set_item(group, GEANY_KEYS_EDITOR_MOVELINEUP, NULL,
|
||||
0, 0, "edit_movelineup", _("Move line(s) up"), NULL);
|
||||
GDK_Page_Up, GDK_MOD1_MASK, "edit_movelineup", _("Move line(s) up"), NULL);
|
||||
keybindings_set_item(group, GEANY_KEYS_EDITOR_MOVELINEDOWN, NULL,
|
||||
0, 0, "edit_movelinedown", _("Move line(s) down"), NULL);
|
||||
GDK_Page_Down, GDK_MOD1_MASK, "edit_movelinedown", _("Move line(s) down"), NULL);
|
||||
|
||||
group = keybindings_get_core_group(GEANY_KEY_GROUP_CLIPBOARD);
|
||||
|
||||
@ -432,18 +432,20 @@ static void init_default_kb(void)
|
||||
keybindings_set_item(group, GEANY_KEYS_SEARCH_PREVIOUSMESSAGE, NULL,
|
||||
0, 0, "menu_previousmessage", _("Previous Message"), LW(previous_message1));
|
||||
keybindings_set_item(group, GEANY_KEYS_SEARCH_FINDUSAGE, NULL,
|
||||
0, 0, "popup_findusage", _("Find Usage"), LW(find_usage1));
|
||||
GDK_e, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "popup_findusage",
|
||||
_("Find Usage"), LW(find_usage1));
|
||||
keybindings_set_item(group, GEANY_KEYS_SEARCH_FINDDOCUMENTUSAGE, NULL,
|
||||
0, 0, "popup_finddocumentusage", _("Find Document Usage"), LW(find_document_usage1));
|
||||
GDK_d, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "popup_finddocumentusage",
|
||||
_("Find Document Usage"), LW(find_document_usage1));
|
||||
keybindings_set_item(group, GEANY_KEYS_SEARCH_MARKALL, NULL,
|
||||
GDK_m, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "find_markall", _("_Mark All"), LW(mark_all1));
|
||||
|
||||
group = keybindings_get_core_group(GEANY_KEY_GROUP_GOTO);
|
||||
|
||||
keybindings_set_item(group, GEANY_KEYS_GOTO_BACK, NULL,
|
||||
0, 0, "nav_back", _("Navigate back a location"), NULL);
|
||||
GDK_Left, GDK_MOD1_MASK, "nav_back", _("Navigate back a location"), NULL);
|
||||
keybindings_set_item(group, GEANY_KEYS_GOTO_FORWARD, NULL,
|
||||
0, 0, "nav_forward", _("Navigate forward a location"), NULL);
|
||||
GDK_Right, GDK_MOD1_MASK, "nav_forward", _("Navigate forward a location"), NULL);
|
||||
keybindings_set_item(group, GEANY_KEYS_GOTO_LINE, NULL,
|
||||
GDK_l, GDK_CONTROL_MASK, "menu_gotoline", _("Go to Line"), LW(go_to_line1));
|
||||
keybindings_set_item(group, GEANY_KEYS_GOTO_MATCHINGBRACE, NULL,
|
||||
@ -459,9 +461,11 @@ static void init_default_kb(void)
|
||||
GDK_comma, GDK_CONTROL_MASK, "edit_gotopreviousmarker",
|
||||
_("_Go to Previous Marker"), LW(go_to_previous_marker1));
|
||||
keybindings_set_item(group, GEANY_KEYS_GOTO_TAGDEFINITION, NULL,
|
||||
0, 0, "popup_gototagdefinition", _("Go to Tag Definition"), LW(goto_tag_definition1));
|
||||
GDK_t, GDK_CONTROL_MASK, "popup_gototagdefinition",
|
||||
_("Go to Tag Definition"), LW(goto_tag_definition1));
|
||||
keybindings_set_item(group, GEANY_KEYS_GOTO_TAGDECLARATION, NULL,
|
||||
0, 0, "popup_gototagdeclaration", _("Go to Tag Declaration"), LW(goto_tag_declaration1));
|
||||
GDK_t, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "popup_gototagdeclaration",
|
||||
_("Go to Tag Declaration"), LW(goto_tag_declaration1));
|
||||
keybindings_set_item(group, GEANY_KEYS_GOTO_LINESTART, NULL,
|
||||
GDK_Home, 0, "edit_gotolinestart", _("Go to Start of Line"), NULL);
|
||||
keybindings_set_item(group, GEANY_KEYS_GOTO_LINEEND, NULL,
|
||||
@ -524,9 +528,11 @@ static void init_default_kb(void)
|
||||
keybindings_set_item(group, GEANY_KEYS_NOTEBOOK_SWITCHTABLASTUSED, cb_func_switch_tablastused,
|
||||
GDK_Tab, GDK_CONTROL_MASK, "switch_tablastused", _("Switch to last used document"), NULL);
|
||||
keybindings_set_item(group, GEANY_KEYS_NOTEBOOK_MOVETABLEFT, cb_func_move_tab,
|
||||
GDK_Page_Up, GDK_MOD1_MASK, "move_tableft", _("Move document left"), NULL);
|
||||
GDK_Page_Up, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "move_tableft",
|
||||
_("Move document left"), NULL);
|
||||
keybindings_set_item(group, GEANY_KEYS_NOTEBOOK_MOVETABRIGHT, cb_func_move_tab,
|
||||
GDK_Page_Down, GDK_MOD1_MASK, "move_tabright", _("Move document right"), NULL);
|
||||
GDK_Page_Down, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "move_tabright",
|
||||
_("Move document right"), NULL);
|
||||
keybindings_set_item(group, GEANY_KEYS_NOTEBOOK_MOVETABFIRST, cb_func_move_tab,
|
||||
0, 0, "move_tabfirst", _("Move document first"), NULL);
|
||||
keybindings_set_item(group, GEANY_KEYS_NOTEBOOK_MOVETABLAST, cb_func_move_tab,
|
||||
@ -569,7 +575,7 @@ static void init_default_kb(void)
|
||||
GDK_F9, GDK_SHIFT_MASK | GDK_CONTROL_MASK, "build_makeowntarget",
|
||||
_("Make custom target"), NULL);
|
||||
keybindings_set_item(group, GEANY_KEYS_BUILD_MAKEOBJECT, NULL,
|
||||
0, 0, "build_makeobject", _("Make object"), NULL);
|
||||
GDK_F8, GDK_SHIFT_MASK, "build_makeobject", _("Make object"), NULL);
|
||||
keybindings_set_item(group, GEANY_KEYS_BUILD_NEXTERROR, NULL,
|
||||
0, 0, "build_nexterror", _("Next error"), NULL);
|
||||
keybindings_set_item(group, GEANY_KEYS_BUILD_PREVIOUSERROR, NULL,
|
||||
@ -967,6 +973,7 @@ static gboolean check_fixed_kb(guint keyval, guint state)
|
||||
gtk_notebook_set_current_page(GTK_NOTEBOOK(main_widgets.notebook), page);
|
||||
return TRUE;
|
||||
}
|
||||
/* note: these are now overridden by default with move tab bindings */
|
||||
if (keyval == GDK_Page_Up || keyval == GDK_Page_Down)
|
||||
{
|
||||
/* switch to first or last document */
|
||||
@ -2544,7 +2551,7 @@ static gboolean cb_func_document_action(guint key_id)
|
||||
ui_document_show_hide(doc);
|
||||
break;
|
||||
case GEANY_KEYS_DOCUMENT_RELOADTAGLIST:
|
||||
document_update_tag_list(doc, TRUE);
|
||||
document_update_tags(doc);
|
||||
break;
|
||||
case GEANY_KEYS_DOCUMENT_FOLDALL:
|
||||
editor_fold_all(doc->editor);
|
||||
|
@ -150,8 +150,6 @@ static void init_pref_groups(void)
|
||||
stash_group_add_toggle_button(group, &interface_prefs.highlighting_invert_all,
|
||||
"highlighting_invert_all", FALSE, "check_highlighting_invert");
|
||||
|
||||
stash_group_add_toggle_button(group, &search_prefs.suppress_dialogs,
|
||||
"pref_main_suppress_search_dialogs", FALSE, "check_ask_suppress_search_dialogs");
|
||||
stash_group_add_toggle_button(group, &search_prefs.use_current_word,
|
||||
"pref_main_search_use_current_word", TRUE, "check_search_use_current_word");
|
||||
|
||||
@ -496,6 +494,8 @@ static void save_dialog_prefs(GKeyFile *config)
|
||||
if (!g_key_file_has_key(config, "VTE", "send_selection_unsafe", NULL)) /* hidden */
|
||||
g_key_file_set_boolean(config, "VTE", "send_selection_unsafe",
|
||||
vc->send_selection_unsafe);
|
||||
if (!g_key_file_has_key(config, "VTE", "send_cmd_prefix", NULL)) /* hidden */
|
||||
g_key_file_set_string(config, "VTE", "send_cmd_prefix", vc->send_cmd_prefix);
|
||||
g_key_file_set_string(config, "VTE", "font", vc->font);
|
||||
g_key_file_set_boolean(config, "VTE", "scroll_on_key", vc->scroll_on_key);
|
||||
g_key_file_set_boolean(config, "VTE", "scroll_on_out", vc->scroll_on_out);
|
||||
@ -691,6 +691,17 @@ static void load_dialog_prefs(GKeyFile *config)
|
||||
utils_get_setting_boolean(config, PACKAGE, "use_safe_file_saving", FALSE));
|
||||
}
|
||||
|
||||
/* compatibility with Geany 0.21 */
|
||||
{
|
||||
gboolean suppress_search_dialogs = utils_get_setting_boolean(config, PACKAGE, "pref_main_suppress_search_dialogs", FALSE);
|
||||
|
||||
if (!g_key_file_has_key(config, "search", "pref_search_always_wrap", NULL))
|
||||
g_key_file_set_boolean(config, "search", "pref_search_always_wrap", suppress_search_dialogs);
|
||||
|
||||
if (!g_key_file_has_key(config, "search", "pref_search_hide_find_dialog", NULL))
|
||||
g_key_file_set_boolean(config, "search", "pref_search_hide_find_dialog", suppress_search_dialogs);
|
||||
}
|
||||
|
||||
/* read stash prefs */
|
||||
settings_action(config, SETTING_READ);
|
||||
|
||||
@ -826,6 +837,7 @@ static void load_dialog_prefs(GKeyFile *config)
|
||||
vc->enable_bash_keys = utils_get_setting_boolean(config, "VTE", "enable_bash_keys", TRUE);
|
||||
vc->ignore_menu_bar_accel = utils_get_setting_boolean(config, "VTE", "ignore_menu_bar_accel", FALSE);
|
||||
vc->follow_path = utils_get_setting_boolean(config, "VTE", "follow_path", FALSE);
|
||||
vc->send_cmd_prefix = utils_get_setting_string(config, "VTE", "send_cmd_prefix", "");
|
||||
vc->run_in_vte = utils_get_setting_boolean(config, "VTE", "run_in_vte", FALSE);
|
||||
vc->skip_run_script = utils_get_setting_boolean(config, "VTE", "skip_run_script", FALSE);
|
||||
vc->cursor_blinks = utils_get_setting_boolean(config, "VTE", "cursor_blinks", FALSE);
|
||||
|
@ -139,6 +139,7 @@ static GOptionEntry entries[] =
|
||||
{ "no-plugins", 'p', 0, G_OPTION_ARG_NONE, &no_plugins, N_("Don't load plugins"), NULL },
|
||||
#endif
|
||||
{ "print-prefix", 0, 0, G_OPTION_ARG_NONE, &print_prefix, N_("Print Geany's installation prefix"), NULL },
|
||||
{ "read-only", 'r', 0, G_OPTION_ARG_NONE, &cl_options.readonly, N_("Open all FILES in read-only mode (see documention)"), NULL },
|
||||
{ "no-session", 's', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &cl_options.load_session, N_("Don't load the previous session's files"), NULL },
|
||||
#ifdef HAVE_VTE
|
||||
{ "no-terminal", 't', 0, G_OPTION_ARG_NONE, &no_vte, N_("Don't load terminal support"), NULL },
|
||||
@ -497,7 +498,7 @@ static void parse_command_line_options(gint *argc, gchar ***argv)
|
||||
GError *error = NULL;
|
||||
GOptionContext *context;
|
||||
gint i;
|
||||
CommandLineOptions def_clo = {FALSE, NULL, TRUE, -1, -1, FALSE, FALSE};
|
||||
CommandLineOptions def_clo = {FALSE, NULL, TRUE, -1, -1, FALSE, FALSE, FALSE};
|
||||
|
||||
/* first initialise cl_options fields with default values */
|
||||
cl_options = def_clo;
|
||||
@ -774,7 +775,7 @@ gboolean main_handle_filename(const gchar *locale_filename)
|
||||
|
||||
if (g_file_test(filename, G_FILE_TEST_IS_REGULAR))
|
||||
{
|
||||
doc = document_open_file(filename, FALSE, NULL, NULL);
|
||||
doc = document_open_file(filename, cl_options.readonly, NULL, NULL);
|
||||
/* add recent file manually if opening_session_files is set */
|
||||
if (doc != NULL && main_status.opening_session_files)
|
||||
ui_add_recent_document(doc);
|
||||
|
@ -32,6 +32,7 @@ typedef struct
|
||||
gint goto_column;
|
||||
gboolean ignore_global_tags;
|
||||
gboolean list_documents;
|
||||
gboolean readonly;
|
||||
}
|
||||
CommandLineOptions;
|
||||
|
||||
|
@ -207,11 +207,12 @@ static void on_open_in_new_window_activate(GtkMenuItem *menuitem, gpointer user_
|
||||
}
|
||||
|
||||
|
||||
static void show_tab_bar_popup_menu(GdkEventButton *event)
|
||||
static void show_tab_bar_popup_menu(GdkEventButton *event, GtkWidget *page)
|
||||
{
|
||||
GtkWidget *menu_item;
|
||||
static GtkWidget *menu = NULL;
|
||||
GeanyDocument *doc = NULL;
|
||||
gint page_num;
|
||||
|
||||
if (menu == NULL)
|
||||
menu = gtk_menu_new();
|
||||
@ -226,24 +227,36 @@ static void show_tab_bar_popup_menu(GdkEventButton *event)
|
||||
gtk_widget_show(menu_item);
|
||||
gtk_container_add(GTK_CONTAINER(menu), menu_item);
|
||||
|
||||
doc = document_get_current();
|
||||
if (page != NULL)
|
||||
{
|
||||
page_num = gtk_notebook_page_num(GTK_NOTEBOOK(main_widgets.notebook), page);
|
||||
doc = document_get_from_page(page_num);
|
||||
}
|
||||
|
||||
menu_item = ui_image_menu_item_new(GTK_STOCK_OPEN, "Open in New _Window");
|
||||
gtk_widget_show(menu_item);
|
||||
gtk_container_add(GTK_CONTAINER(menu), menu_item);
|
||||
g_signal_connect(menu_item, "activate",
|
||||
G_CALLBACK(on_open_in_new_window_activate), doc);
|
||||
/* disable if not on disk */
|
||||
if (!doc->real_path)
|
||||
if (doc == NULL || !doc->real_path)
|
||||
gtk_widget_set_sensitive(menu_item, FALSE);
|
||||
|
||||
menu_item = gtk_separator_menu_item_new();
|
||||
gtk_widget_show(menu_item);
|
||||
gtk_container_add(GTK_CONTAINER(menu), menu_item);
|
||||
|
||||
menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_CLOSE, NULL);
|
||||
gtk_widget_show(menu_item);
|
||||
gtk_container_add(GTK_CONTAINER(menu), menu_item);
|
||||
g_signal_connect(menu_item, "activate", G_CALLBACK(notebook_tab_close_clicked_cb), page);
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(menu_item), (page != NULL));
|
||||
|
||||
menu_item = ui_image_menu_item_new(GTK_STOCK_CLOSE, _("Close Ot_her Documents"));
|
||||
gtk_widget_show(menu_item);
|
||||
gtk_container_add(GTK_CONTAINER(menu), menu_item);
|
||||
g_signal_connect(menu_item, "activate", G_CALLBACK(on_close_other_documents1_activate), NULL);
|
||||
g_signal_connect(menu_item, "activate", G_CALLBACK(on_close_other_documents1_activate), page);
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(menu_item), (page != NULL));
|
||||
|
||||
menu_item = ui_image_menu_item_new(GTK_STOCK_CLOSE, _("C_lose All"));
|
||||
gtk_widget_show(menu_item);
|
||||
@ -270,9 +283,12 @@ static gboolean notebook_tab_bar_click_cb(GtkWidget *widget, GdkEventButton *eve
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
/* right-click is also handled here if it happened on the notebook tab bar but not
|
||||
* on a tab directly */
|
||||
else if (event->button == 3)
|
||||
{
|
||||
show_tab_bar_popup_menu(event);
|
||||
show_tab_bar_popup_menu(event, NULL);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@ -369,6 +385,13 @@ static gboolean notebook_tab_click(GtkWidget *widget, GdkEventButton *event, gpo
|
||||
GEANY_KEYS_NOTEBOOK_SWITCHTABLASTUSED);
|
||||
return TRUE;
|
||||
}
|
||||
/* right-click is first handled here if it happened on a notebook tab */
|
||||
if (event->button == 3)
|
||||
{
|
||||
show_tab_bar_popup_menu(event, data);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -30,8 +30,8 @@
|
||||
* when making changes (see 'Keeping the plugin ABI stable' in the HACKING file). */
|
||||
|
||||
|
||||
#ifndef PLUGINDATA_H
|
||||
#define PLUGINDATA_H
|
||||
#ifndef GEANY_PLUGINDATA_H
|
||||
#define GEANY_PLUGINDATA_H
|
||||
|
||||
/* Compatibility for sharing macros between API and core.
|
||||
* First include geany.h, then plugindata.h, then other API headers. */
|
||||
|
@ -21,8 +21,8 @@
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PLUGINPRIVATE_H
|
||||
#define PLUGINPRIVATE_H
|
||||
#ifndef GEANY_PLUGINPRIVATE_H
|
||||
#define GEANY_PLUGINPRIVATE_H
|
||||
|
||||
#include "plugindata.h"
|
||||
#include "ui_utils.h" /* GeanyAutoSeparator */
|
||||
@ -62,4 +62,4 @@ GeanyPluginPrivate;
|
||||
typedef GeanyPluginPrivate Plugin; /* shorter alias */
|
||||
|
||||
|
||||
#endif /* PLUGINPRIVATE_H */
|
||||
#endif /* GEANY_PLUGINPRIVATE_H */
|
||||
|
108
src/plugins.c
108
src/plugins.c
@ -75,6 +75,7 @@ static GList *failed_plugins_list = NULL; /* plugins the user wants active but c
|
||||
|
||||
static GtkWidget *menu_separator = NULL;
|
||||
|
||||
static gchar *get_plugin_path(void);
|
||||
static void pm_show_dialog(GtkMenuItem *menuitem, gpointer user_data);
|
||||
|
||||
|
||||
@ -658,7 +659,7 @@ plugin_new(const gchar *fname, gboolean init_plugin, gboolean add_to_list)
|
||||
geany_debug("Plugin \"%s\" already loaded.", fname);
|
||||
if (add_to_list)
|
||||
{
|
||||
/* do not add the to list twice */
|
||||
/* do not add to the list twice */
|
||||
if (g_list_find(plugin_list, plugin) != NULL)
|
||||
return NULL;
|
||||
|
||||
@ -839,6 +840,60 @@ plugin_free(Plugin *plugin)
|
||||
}
|
||||
|
||||
|
||||
static gchar *get_custom_plugin_path(const gchar *plugin_path_config,
|
||||
const gchar *plugin_path_system)
|
||||
{
|
||||
gchar *plugin_path_custom;
|
||||
|
||||
if (!NZV(prefs.custom_plugin_path))
|
||||
return NULL;
|
||||
|
||||
plugin_path_custom = utils_get_locale_from_utf8(prefs.custom_plugin_path);
|
||||
utils_tidy_path(plugin_path_custom);
|
||||
|
||||
/* check whether the custom plugin path is one of the system or user plugin paths
|
||||
* and abort if so */
|
||||
if (utils_str_equal(plugin_path_custom, plugin_path_config) ||
|
||||
utils_str_equal(plugin_path_custom, plugin_path_system))
|
||||
{
|
||||
g_free(plugin_path_custom);
|
||||
return NULL;
|
||||
}
|
||||
return plugin_path_custom;
|
||||
}
|
||||
|
||||
|
||||
/* all 3 paths Geany looks for plugins in can change (even system path on Windows)
|
||||
* so we need to check active plugins are in the right place before loading */
|
||||
static gboolean check_plugin_path(const gchar *fname)
|
||||
{
|
||||
gchar *plugin_path_config;
|
||||
gchar *plugin_path_system;
|
||||
gchar *plugin_path_custom;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
plugin_path_config = g_strconcat(app->configdir, G_DIR_SEPARATOR_S, "plugins", NULL);
|
||||
if (g_str_has_prefix(fname, plugin_path_config))
|
||||
ret = TRUE;
|
||||
|
||||
plugin_path_system = get_plugin_path();
|
||||
if (g_str_has_prefix(fname, plugin_path_system))
|
||||
ret = TRUE;
|
||||
|
||||
plugin_path_custom = get_custom_plugin_path(plugin_path_config, plugin_path_system);
|
||||
if (plugin_path_custom)
|
||||
{
|
||||
if (g_str_has_prefix(fname, plugin_path_custom))
|
||||
ret = TRUE;
|
||||
|
||||
g_free(plugin_path_custom);
|
||||
}
|
||||
g_free(plugin_path_config);
|
||||
g_free(plugin_path_system);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* load active plugins at startup */
|
||||
static void
|
||||
load_active_plugins(void)
|
||||
@ -854,7 +909,7 @@ load_active_plugins(void)
|
||||
|
||||
if (NZV(fname) && g_file_test(fname, G_FILE_TEST_EXISTS))
|
||||
{
|
||||
if (plugin_new(fname, TRUE, FALSE) == NULL)
|
||||
if (!check_plugin_path(fname) || plugin_new(fname, TRUE, FALSE) == NULL)
|
||||
failed_plugins_list = g_list_prepend(failed_plugins_list, g_strdup(fname));
|
||||
}
|
||||
}
|
||||
@ -886,7 +941,7 @@ load_plugins_from_path(const gchar *path)
|
||||
g_slist_free(list);
|
||||
|
||||
if (count)
|
||||
geany_debug("Found %d plugin(s) in '%s'.", count, path);
|
||||
geany_debug("Added %d plugin(s) in '%s'.", count, path);
|
||||
}
|
||||
|
||||
|
||||
@ -906,25 +961,12 @@ static gchar *get_plugin_path(void)
|
||||
}
|
||||
|
||||
|
||||
static gboolean validate_custom_plugin_path(const gchar *plugin_path_custom,
|
||||
const gchar *plugin_path_config,
|
||||
const gchar *plugin_path_system)
|
||||
{
|
||||
/* check whether the custom plugin path is one of the system or user plugin paths
|
||||
* and abort if so */
|
||||
if (utils_str_equal(plugin_path_custom, plugin_path_config) ||
|
||||
utils_str_equal(plugin_path_custom, plugin_path_system))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Load (but don't initialize) all plugins for the Plugin Manager dialog */
|
||||
static void load_all_plugins(void)
|
||||
{
|
||||
gchar *plugin_path_config;
|
||||
gchar *plugin_path_system;
|
||||
gchar *plugin_path_custom;
|
||||
|
||||
plugin_path_config = g_strconcat(app->configdir, G_DIR_SEPARATOR_S, "plugins", NULL);
|
||||
plugin_path_system = get_plugin_path();
|
||||
@ -933,14 +975,10 @@ static void load_all_plugins(void)
|
||||
load_plugins_from_path(plugin_path_config);
|
||||
|
||||
/* load plugins from a custom path */
|
||||
if (NZV(prefs.custom_plugin_path))
|
||||
plugin_path_custom = get_custom_plugin_path(plugin_path_config, plugin_path_system);
|
||||
if (plugin_path_custom)
|
||||
{
|
||||
gchar *plugin_path_custom = utils_get_locale_from_utf8(prefs.custom_plugin_path);
|
||||
utils_tidy_path(plugin_path_custom);
|
||||
|
||||
if (validate_custom_plugin_path(plugin_path_custom, plugin_path_config, plugin_path_system))
|
||||
load_plugins_from_path(plugin_path_custom);
|
||||
|
||||
load_plugins_from_path(plugin_path_custom);
|
||||
g_free(plugin_path_custom);
|
||||
}
|
||||
|
||||
@ -1104,7 +1142,7 @@ enum
|
||||
{
|
||||
PLUGIN_COLUMN_CHECK = 0,
|
||||
PLUGIN_COLUMN_NAME,
|
||||
PLUGIN_COLUMN_FILE,
|
||||
PLUGIN_COLUMN_DESCRIPTION,
|
||||
PLUGIN_COLUMN_PLUGIN,
|
||||
PLUGIN_N_COLUMNS,
|
||||
PM_BUTTON_CONFIGURE,
|
||||
@ -1117,7 +1155,7 @@ typedef struct
|
||||
GtkWidget *tree;
|
||||
GtkListStore *store;
|
||||
GtkWidget *plugin_label;
|
||||
GtkWidget *description_label;
|
||||
GtkWidget *filename_label;
|
||||
GtkWidget *author_label;
|
||||
GtkWidget *configure_button;
|
||||
GtkWidget *help_button;
|
||||
@ -1157,7 +1195,7 @@ static void pm_selection_changed(GtkTreeSelection *selection, gpointer user_data
|
||||
/* Translators: <plugin name> <plugin version> */
|
||||
text = g_strdup_printf(_("%s %s"), pi->name, pi->version);
|
||||
gtk_label_set_text(GTK_LABEL(pm_widgets.plugin_label), text);
|
||||
gtk_label_set_text(GTK_LABEL(pm_widgets.description_label), pi->description);
|
||||
gtk_label_set_text(GTK_LABEL(pm_widgets.filename_label), p->filename);
|
||||
gtk_label_set_text(GTK_LABEL(pm_widgets.author_label), pi->author);
|
||||
g_free(text);
|
||||
|
||||
@ -1243,7 +1281,7 @@ static void pm_prepare_treeview(GtkWidget *tree, GtkListStore *store)
|
||||
text_renderer = gtk_cell_renderer_text_new();
|
||||
g_object_set(text_renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
|
||||
column = gtk_tree_view_column_new_with_attributes(
|
||||
_("File"), text_renderer, "text", PLUGIN_COLUMN_FILE, NULL);
|
||||
_("Description"), text_renderer, "text", PLUGIN_COLUMN_DESCRIPTION, NULL);
|
||||
gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
|
||||
|
||||
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tree), TRUE);
|
||||
@ -1262,7 +1300,7 @@ static void pm_prepare_treeview(GtkWidget *tree, GtkListStore *store)
|
||||
gtk_list_store_append(store, &iter);
|
||||
gtk_list_store_set(store, &iter, PLUGIN_COLUMN_CHECK, FALSE,
|
||||
PLUGIN_COLUMN_NAME, _("No plugins available."),
|
||||
PLUGIN_COLUMN_FILE, "", PLUGIN_COLUMN_PLUGIN, NULL, -1);
|
||||
PLUGIN_COLUMN_DESCRIPTION, "", PLUGIN_COLUMN_PLUGIN, NULL, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1275,7 +1313,7 @@ static void pm_prepare_treeview(GtkWidget *tree, GtkListStore *store)
|
||||
gtk_list_store_set(store, &iter,
|
||||
PLUGIN_COLUMN_CHECK, is_active_plugin(p),
|
||||
PLUGIN_COLUMN_NAME, p->info.name,
|
||||
PLUGIN_COLUMN_FILE, p->filename,
|
||||
PLUGIN_COLUMN_DESCRIPTION, p->info.description,
|
||||
PLUGIN_COLUMN_PLUGIN, p,
|
||||
-1);
|
||||
}
|
||||
@ -1396,14 +1434,14 @@ static void pm_show_dialog(GtkMenuItem *menuitem, gpointer user_data)
|
||||
table = gtk_table_new(3, 2, FALSE);
|
||||
gtk_table_set_col_spacings(GTK_TABLE(table), 6);
|
||||
pm_widgets.plugin_label = geany_wrap_label_new(NULL);
|
||||
pm_widgets.description_label = geany_wrap_label_new(NULL);
|
||||
pm_widgets.filename_label = geany_wrap_label_new(NULL);
|
||||
pm_widgets.author_label = geany_wrap_label_new(NULL);
|
||||
gtk_table_attach(GTK_TABLE(table), create_table_label(_("Plugin:")), 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
|
||||
gtk_table_attach(GTK_TABLE(table), create_table_label(_("Description:")), 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
|
||||
gtk_table_attach(GTK_TABLE(table), create_table_label(_("Author(s):")), 0, 1, 2, 3, GTK_FILL, GTK_FILL, 0, 0);
|
||||
gtk_table_attach(GTK_TABLE(table), create_table_label(_("Author(s):")), 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
|
||||
gtk_table_attach(GTK_TABLE(table), create_table_label(_("Filename:")), 0, 1, 2, 3, GTK_FILL, GTK_FILL, 0, 0);
|
||||
gtk_table_attach(GTK_TABLE(table), pm_widgets.plugin_label, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
|
||||
gtk_table_attach(GTK_TABLE(table), pm_widgets.description_label, 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
|
||||
gtk_table_attach(GTK_TABLE(table), pm_widgets.author_label, 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
|
||||
gtk_table_attach(GTK_TABLE(table), pm_widgets.author_label, 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
|
||||
gtk_table_attach(GTK_TABLE(table), pm_widgets.filename_label, 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
|
||||
|
||||
desc_win = gtk_scrolled_window_new(NULL, NULL);
|
||||
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(desc_win),
|
||||
|
@ -21,8 +21,8 @@
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PLUGINS_H
|
||||
#define PLUGINS_H
|
||||
#ifndef GEANY_PLUGINS_H
|
||||
#define GEANY_PLUGINS_H
|
||||
|
||||
#ifdef HAVE_PLUGINS
|
||||
|
||||
|
@ -21,8 +21,8 @@
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PLUGINUTILS_H
|
||||
#define PLUGINUTILS_H
|
||||
#ifndef GEANY_PLUGINUTILS_H
|
||||
#define GEANY_PLUGINUTILS_H
|
||||
|
||||
#ifdef HAVE_PLUGINS
|
||||
|
||||
@ -55,4 +55,4 @@ struct GeanyKeyGroup *plugin_set_key_group(struct GeanyPlugin *plugin,
|
||||
void plugin_show_configure(struct GeanyPlugin *plugin);
|
||||
|
||||
#endif /* HAVE_PLUGINS */
|
||||
#endif /* PLUGINUTILS_H */
|
||||
#endif /* GEANY_PLUGINUTILS_H */
|
||||
|
@ -14,8 +14,8 @@
|
||||
* to br_*", try renaming prefix.c to prefix.cpp
|
||||
*/
|
||||
|
||||
#ifndef _PREFIX_H_
|
||||
#define _PREFIX_H_
|
||||
#ifndef GEANY_PREFIX_H
|
||||
#define GEANY_PREFIX_H
|
||||
|
||||
|
||||
/*
|
||||
@ -93,4 +93,4 @@ char *br_prepend_prefix (void *symbol, char *path);
|
||||
|
||||
#endif /* ENABLE_BINRELOC */
|
||||
|
||||
#endif /* _PREFIX_H_ */
|
||||
#endif /* GEANY_PREFIX_H */
|
||||
|
119
src/prefs.c
119
src/prefs.c
@ -83,7 +83,7 @@ static GtkTreeView *various_treeview = NULL;
|
||||
static void kb_cell_edited_cb(GtkCellRendererText *cellrenderertext, gchar *path, gchar *new_text, gpointer user_data);
|
||||
static gboolean kb_grab_key_dialog_key_press_cb(GtkWidget *dialog, GdkEventKey *event, gpointer user_data);
|
||||
static void kb_grab_key_dialog_response_cb(GtkWidget *dialog, gint response, gpointer user_data);
|
||||
static gboolean kb_find_duplicate(GtkWidget *parent, GeanyKeyBinding *search_kb,
|
||||
static gboolean kb_find_duplicate(GtkWidget *parent, GtkTreeIter *old_iter,
|
||||
guint key, GdkModifierType mods, const gchar *shortcut);
|
||||
static void on_toolbar_show_toggled(GtkToggleButton *togglebutton, gpointer user_data);
|
||||
static void on_show_notebook_tabs_toggled(GtkToggleButton *togglebutton, gpointer user_data);
|
||||
@ -1236,7 +1236,6 @@ on_prefs_dialog_response(GtkDialog *dialog, gint response, gpointer user_data)
|
||||
ui_update_view_editor_menu_items();
|
||||
|
||||
/* various preferences */
|
||||
doc = document_get_current();
|
||||
ui_save_buttons_toggle((doc != NULL) ? doc->changed : FALSE);
|
||||
msgwin_show_hide_tabs();
|
||||
ui_update_statusbar(doc, -1);
|
||||
@ -1312,33 +1311,14 @@ static void on_prefs_font_choosed(GtkFontButton *widget, gpointer user_data)
|
||||
}
|
||||
|
||||
|
||||
static GeanyKeyBinding *kb_lookup_kb_from_iter(G_GNUC_UNUSED GtkTreeModel *model, GtkTreeIter *iter)
|
||||
{
|
||||
guint group_idx, keybinding_idx;
|
||||
GtkTreeIter parent;
|
||||
|
||||
/* get kb index */
|
||||
gtk_tree_model_get(GTK_TREE_MODEL(store), iter, KB_TREE_INDEX, &keybinding_idx, -1);
|
||||
|
||||
/* lookup the parent to get group index */
|
||||
gtk_tree_model_iter_parent(GTK_TREE_MODEL(store), &parent, iter);
|
||||
gtk_tree_model_get(GTK_TREE_MODEL(store), &parent, KB_TREE_INDEX, &group_idx, -1);
|
||||
|
||||
return kb_index(group_idx, keybinding_idx);
|
||||
}
|
||||
|
||||
|
||||
static void kb_change_iter_shortcut(GtkTreeIter *iter, const gchar *new_text)
|
||||
{
|
||||
guint lkey;
|
||||
GdkModifierType lmods;
|
||||
GeanyKeyBinding *kb;
|
||||
|
||||
gtk_accelerator_parse(new_text, &lkey, &lmods);
|
||||
|
||||
kb = kb_lookup_kb_from_iter(GTK_TREE_MODEL(store), iter);
|
||||
|
||||
if (kb_find_duplicate(ui_widgets.prefs_dialog, kb, lkey, lmods, new_text))
|
||||
if (kb_find_duplicate(ui_widgets.prefs_dialog, iter, lkey, lmods, new_text))
|
||||
return;
|
||||
|
||||
/* set the values here, because of the above check, setting it in
|
||||
@ -1396,70 +1376,56 @@ static void kb_grab_key_dialog_response_cb(GtkWidget *dialog, gint response, G_G
|
||||
}
|
||||
|
||||
|
||||
/* Look for a (1st-level) child of parent whose KB_TREE_INDEX matches i,
|
||||
* setting iter to point to the node if found.
|
||||
* If parent is NULL, look for a parent node whose KB_TREE_INDEX matches i. */
|
||||
static gboolean kb_find_child_iter(GtkTreeIter *parent, guint i, GtkTreeIter *iter)
|
||||
{
|
||||
GtkTreeModel *model = GTK_TREE_MODEL(store);
|
||||
guint idx;
|
||||
|
||||
/* get first child of parent */
|
||||
if (! gtk_tree_model_iter_children(model, iter, parent))
|
||||
return FALSE;
|
||||
|
||||
while (TRUE) /* foreach child */
|
||||
{
|
||||
gtk_tree_model_get(model, iter, KB_TREE_INDEX, &idx, -1);
|
||||
if (idx == i)
|
||||
return TRUE;
|
||||
if (! gtk_tree_model_iter_next(model, iter))
|
||||
return FALSE; /* no more children */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void kb_clear_tree_shortcut(gsize group_id, gsize keybinding_id)
|
||||
{
|
||||
GtkTreeIter parent;
|
||||
GtkTreeIter child;
|
||||
|
||||
/* find parent kb group */
|
||||
if (! kb_find_child_iter(NULL, group_id, &parent))
|
||||
return;
|
||||
|
||||
/* find child kb node*/
|
||||
if (! kb_find_child_iter(&parent, keybinding_id, &child))
|
||||
return;
|
||||
|
||||
gtk_tree_store_set(store, &child, KB_TREE_SHORTCUT, NULL, -1); /* clear shortcut */
|
||||
}
|
||||
|
||||
|
||||
/* test if the entered key combination is already used
|
||||
* returns true if cancelling duplicate */
|
||||
static gboolean kb_find_duplicate(GtkWidget *parent, GeanyKeyBinding *search_kb,
|
||||
static gboolean kb_find_duplicate(GtkWidget *parent, GtkTreeIter *old_iter,
|
||||
guint key, GdkModifierType mods, const gchar *shortcut)
|
||||
{
|
||||
gsize g, i;
|
||||
GeanyKeyGroup *group;
|
||||
GeanyKeyBinding *kb;
|
||||
GtkTreeModel *model = GTK_TREE_MODEL(store);
|
||||
GtkTreeIter parent_iter;
|
||||
gchar *kb_str;
|
||||
guint kb_key;
|
||||
GdkModifierType kb_mods;
|
||||
|
||||
/* allow duplicate if there is no key combination */
|
||||
if (key == 0 && mods == 0)
|
||||
return FALSE;
|
||||
|
||||
foreach_ptr_array(group, g, keybinding_groups)
|
||||
/* don't check if the new keybinding is the same as the old one */
|
||||
gtk_tree_model_get(model, old_iter, KB_TREE_SHORTCUT, &kb_str, -1);
|
||||
if (kb_str)
|
||||
{
|
||||
foreach_ptr_array(kb, i, group->key_items)
|
||||
gtk_accelerator_parse(kb_str, &kb_key, &kb_mods);
|
||||
g_free(kb_str);
|
||||
if (key == kb_key && mods == kb_mods)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (! gtk_tree_model_get_iter_first(model, &parent_iter))
|
||||
return FALSE;
|
||||
do /* foreach top level */
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (! gtk_tree_model_iter_children(model, &iter, &parent_iter))
|
||||
continue;
|
||||
do /* foreach children */
|
||||
{
|
||||
/* search another item with the same key,
|
||||
* but don't search the key we're looking for(!) */
|
||||
if (kb->key == key && kb->mods == mods
|
||||
&& ! (kb->key == search_kb->key && kb->mods == search_kb->mods))
|
||||
|
||||
gtk_tree_model_get(model, &iter, KB_TREE_SHORTCUT, &kb_str, -1);
|
||||
if (! kb_str)
|
||||
continue;
|
||||
|
||||
gtk_accelerator_parse(kb_str, &kb_key, &kb_mods);
|
||||
g_free(kb_str);
|
||||
/* search another item with the same key and modifiers */
|
||||
if (kb_key == key && kb_mods == mods)
|
||||
{
|
||||
gchar *label = keybindings_get_label(kb);
|
||||
gint ret = dialogs_show_prompt(parent,
|
||||
gchar *label;
|
||||
gint ret;
|
||||
|
||||
gtk_tree_model_get(model, &iter, KB_TREE_ACTION, &label, -1);
|
||||
ret = dialogs_show_prompt(parent,
|
||||
_("_Allow"), GTK_RESPONSE_APPLY,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_NO,
|
||||
_("_Override"), GTK_RESPONSE_YES,
|
||||
@ -1471,14 +1437,17 @@ static gboolean kb_find_duplicate(GtkWidget *parent, GeanyKeyBinding *search_kb,
|
||||
|
||||
if (ret == GTK_RESPONSE_YES)
|
||||
{
|
||||
kb_clear_tree_shortcut(g, kb->id);
|
||||
gtk_tree_store_set(store, &iter, KB_TREE_SHORTCUT, NULL, -1); /* clear shortcut */
|
||||
/* carry on looking for other duplicates if overriding */
|
||||
continue;
|
||||
}
|
||||
return ret == GTK_RESPONSE_NO;
|
||||
}
|
||||
}
|
||||
while (gtk_tree_model_iter_next(model, &iter));
|
||||
}
|
||||
while (gtk_tree_model_iter_next(model, &parent_iter));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -189,6 +189,10 @@ static void init_prefs(void)
|
||||
|
||||
group = stash_group_new("search");
|
||||
configuration_add_pref_group(group, TRUE);
|
||||
stash_group_add_toggle_button(group, &search_prefs.always_wrap,
|
||||
"pref_search_hide_find_dialog", FALSE, "check_always_wrap_search");
|
||||
stash_group_add_toggle_button(group, &search_prefs.hide_find_dialog,
|
||||
"pref_search_always_wrap", FALSE, "check_hide_find_dialog");
|
||||
stash_group_add_toggle_button(group, &search_prefs.use_current_file_dir,
|
||||
"pref_search_current_file_dir", TRUE, "check_fif_current_dir");
|
||||
stash_group_add_boolean(group, &find_dlg.all_expanded, "find_all_expanded", FALSE);
|
||||
@ -1253,9 +1257,7 @@ on_find_dialog_response(GtkDialog *dialog, gint response, gpointer user_data)
|
||||
gint result = document_find_text(doc, search_data.text, search_data.original_text, search_data.flags,
|
||||
(response == GEANY_RESPONSE_FIND_PREVIOUS), TRUE, GTK_WIDGET(find_dlg.dialog));
|
||||
ui_set_search_entry_background(find_dlg.entry, (result > -1));
|
||||
check_close = FALSE;
|
||||
if (search_prefs.suppress_dialogs)
|
||||
check_close = TRUE;
|
||||
check_close = search_prefs.hide_find_dialog;
|
||||
break;
|
||||
}
|
||||
case GEANY_RESPONSE_FIND_IN_FILE:
|
||||
|
@ -55,9 +55,10 @@ enum GeanyFindSelOptions
|
||||
/** Search preferences */
|
||||
typedef struct GeanySearchPrefs
|
||||
{
|
||||
gboolean suppress_dialogs;
|
||||
gboolean always_wrap; /* don't ask whether to wrap search */
|
||||
gboolean use_current_word; /**< Use current word for default search text */
|
||||
gboolean use_current_file_dir; /* find in files directory to use on showing dialog */
|
||||
gboolean hide_find_dialog; /* hide the find dialog on next or previous */
|
||||
enum GeanyFindSelOptions find_selection_type;
|
||||
}
|
||||
GeanySearchPrefs;
|
||||
|
@ -216,7 +216,7 @@ void sidebar_update_tag_list(GeanyDocument *doc, gboolean update)
|
||||
if (doc->priv->tag_tree == NULL)
|
||||
{
|
||||
doc->priv->tag_store = gtk_tree_store_new(
|
||||
SYMBOLS_N_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, TM_TYPE_TAG, G_TYPE_STRING, G_TYPE_BOOLEAN);
|
||||
SYMBOLS_N_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, TM_TYPE_TAG, G_TYPE_STRING);
|
||||
doc->priv->tag_tree = gtk_tree_view_new();
|
||||
prepare_taglist(doc->priv->tag_tree, doc->priv->tag_store);
|
||||
gtk_widget_show(doc->priv->tag_tree);
|
||||
|
@ -41,7 +41,6 @@ enum
|
||||
SYMBOLS_COLUMN_NAME,
|
||||
SYMBOLS_COLUMN_TAG,
|
||||
SYMBOLS_COLUMN_TOOLTIP,
|
||||
SYMBOLS_COLUMN_VALID,
|
||||
SYMBOLS_N_COLUMNS
|
||||
};
|
||||
|
||||
|
@ -40,7 +40,7 @@
|
||||
* The command window is only available on Windows and takes no additional data, instead it
|
||||
* writes back a Windows handle (HWND) for the main window to set it to the foreground (focus).
|
||||
*
|
||||
* At the moment the commands window, doclist, open, line and column are available.
|
||||
* At the moment the commands window, doclist, open, openro, line and column are available.
|
||||
*
|
||||
* About the socket files on Unix-like systems:
|
||||
* Geany creates a socket in /tmp (or any other directory returned by g_get_tmp_dir()) and
|
||||
@ -146,7 +146,10 @@ static void send_open_command(gint sock, gint argc, gchar **argv)
|
||||
g_free(col);
|
||||
}
|
||||
|
||||
socket_fd_write_all(sock, "open\n", 5);
|
||||
if (cl_options.readonly) /* append "ro" to denote readonly status for new docs */
|
||||
socket_fd_write_all(sock, "openro\n", 7);
|
||||
else
|
||||
socket_fd_write_all(sock, "open\n", 5);
|
||||
|
||||
for (i = 1; i < argc && argv[i] != NULL; i++)
|
||||
{
|
||||
@ -598,6 +601,7 @@ gboolean socket_lock_input_cb(GIOChannel *source, GIOCondition condition, gpoint
|
||||
{
|
||||
if (strncmp(buf, "open", 4) == 0)
|
||||
{
|
||||
cl_options.readonly = strncmp(buf+4, "ro", 2) == 0; /* open in readonly? */
|
||||
while (socket_fd_gets(sock, buf, sizeof(buf)) != -1 && *buf != '.')
|
||||
{
|
||||
handle_input_filename(g_strstrip(buf));
|
||||
|
382
src/symbols.c
382
src/symbols.c
@ -558,14 +558,15 @@ static GdkPixbuf *get_tag_icon(const gchar *icon_name)
|
||||
|
||||
/* finds the next iter at any level
|
||||
* @param iter in/out, the current iter, will be changed to the next one
|
||||
* @param down whether to try the child iter
|
||||
* @return TRUE if there @p iter was set, or FALSE if there is no next iter */
|
||||
static gboolean next_iter(GtkTreeModel *model, GtkTreeIter *iter)
|
||||
static gboolean next_iter(GtkTreeModel *model, GtkTreeIter *iter, gboolean down)
|
||||
{
|
||||
GtkTreeIter guess;
|
||||
GtkTreeIter copy = *iter;
|
||||
|
||||
/* go down if the item has children */
|
||||
if (gtk_tree_model_iter_children(model, &guess, iter))
|
||||
if (down && gtk_tree_model_iter_children(model, &guess, iter))
|
||||
*iter = guess;
|
||||
/* or to the next item at the same level */
|
||||
else if (gtk_tree_model_iter_next(model, ©))
|
||||
@ -654,7 +655,7 @@ tag_list_add_groups(GtkTreeStore *tree_store, ...)
|
||||
gtk_tree_store_set(tree_store, iter, SYMBOLS_COLUMN_ICON, icon, -1);
|
||||
g_object_unref(icon);
|
||||
}
|
||||
gtk_tree_store_set(tree_store, iter, SYMBOLS_COLUMN_NAME, title, SYMBOLS_COLUMN_VALID, TRUE, -1);
|
||||
gtk_tree_store_set(tree_store, iter, SYMBOLS_COLUMN_NAME, title, -1);
|
||||
}
|
||||
va_end(args);
|
||||
}
|
||||
@ -1221,165 +1222,208 @@ static guint tag_hash(gconstpointer v)
|
||||
}
|
||||
|
||||
|
||||
static GHashTable *build_iter_table(GtkTreeStore *store)
|
||||
/* like gtk_tree_view_expand_to_path() but with an iter */
|
||||
static void tree_view_expand_to_iter(GtkTreeView *view, GtkTreeIter *iter)
|
||||
{
|
||||
GtkTreeModel *model = gtk_tree_view_get_model(view);
|
||||
GtkTreePath *path = gtk_tree_model_get_path(model, iter);
|
||||
|
||||
gtk_tree_view_expand_to_path(view, path);
|
||||
gtk_tree_path_free(path);
|
||||
}
|
||||
|
||||
|
||||
/* like gtk_tree_store_remove() but finds the next iter at any level */
|
||||
static gboolean tree_store_remove_row(GtkTreeStore *store, GtkTreeIter *iter)
|
||||
{
|
||||
GtkTreeIter parent;
|
||||
gboolean has_parent;
|
||||
gboolean cont;
|
||||
|
||||
has_parent = gtk_tree_model_iter_parent(GTK_TREE_MODEL(store), &parent, iter);
|
||||
cont = gtk_tree_store_remove(store, iter);
|
||||
/* if there is no next at this level but there is a parent iter, continue from it */
|
||||
if (! cont && has_parent)
|
||||
{
|
||||
*iter = parent;
|
||||
cont = next_iter(GTK_TREE_MODEL(store), iter, FALSE);
|
||||
}
|
||||
|
||||
return cont;
|
||||
}
|
||||
|
||||
|
||||
/* updates @table adding @tag->name:@iter if necessary */
|
||||
static void update_parents_table(GHashTable *table, const TMTag *tag, const gchar *parent_name,
|
||||
const GtkTreeIter *iter)
|
||||
{
|
||||
if (g_hash_table_lookup_extended(table, tag->name, NULL, NULL) &&
|
||||
! utils_str_equal(parent_name, tag->name) /* prevent Foo::Foo from making parent = child */)
|
||||
{
|
||||
g_hash_table_insert(table, tag->name, g_slice_dup(GtkTreeIter, iter));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void free_iter_slice(gpointer iter)
|
||||
{
|
||||
g_slice_free(GtkTreeIter, iter);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Updates the tag tree for a document with the tags in *list.
|
||||
* @param doc a document
|
||||
* @param tags a pointer to a GList* holding the tags to add/update. This
|
||||
* list may be updated, removing updated elements.
|
||||
*
|
||||
* The update is done in two passes:
|
||||
* 1) walking the current tree, update tags that still exist and remove the
|
||||
* obsolescent ones;
|
||||
* 2) walking the remaining (non updated) tags, adds them in the list.
|
||||
*
|
||||
* For better performances, we use 2 hash tables:
|
||||
* - one containing all the tags for lookup in the first pass (actually stores a
|
||||
* reference in the tags list for removing it efficiently), avoiding list search
|
||||
* on each tag;
|
||||
* - the other holding "tag-name":row references for tags having children, used to
|
||||
* lookup for a parent in both passes, avoiding tree traversal.
|
||||
*/
|
||||
static void update_tree_tags(GeanyDocument *doc, GList **tags)
|
||||
{
|
||||
GtkTreeStore *store = doc->priv->tag_store;
|
||||
GtkTreeModel *model = GTK_TREE_MODEL(store);
|
||||
GHashTable *table;
|
||||
GHashTable *parents_table;
|
||||
GHashTable *tags_table;
|
||||
GtkTreeIter iter;
|
||||
gboolean cont;
|
||||
GList *item;
|
||||
|
||||
table = g_hash_table_new_full(tag_hash, tag_equal,
|
||||
(GDestroyNotify)tm_tag_unref, (GDestroyNotify)gtk_tree_path_free);
|
||||
/* Build hash tables holding tags and parents */
|
||||
/* parent table holds "tag-name":GtkTreeIter */
|
||||
parents_table = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, free_iter_slice);
|
||||
/* tags table is another representation of the @tags list, TMTag:GList<TMTag> */
|
||||
tags_table = g_hash_table_new_full(tag_hash, tag_equal, NULL, NULL);
|
||||
foreach_list(item, *tags)
|
||||
{
|
||||
TMTag *tag = item->data;
|
||||
const gchar *name;
|
||||
|
||||
if (!gtk_tree_model_get_iter_first(model, &iter))
|
||||
return table;
|
||||
do
|
||||
g_hash_table_insert(tags_table, tag, item);
|
||||
|
||||
name = get_parent_name(tag, doc->file_type->id);
|
||||
if (name)
|
||||
g_hash_table_insert(parents_table, (gpointer) name, NULL);
|
||||
}
|
||||
|
||||
/* First pass, update existing rows or delete them.
|
||||
* It is OK to delete them since we walk top down so we would remove
|
||||
* parents before checking for their children, thus never implicitly
|
||||
* deleting an updated child */
|
||||
cont = gtk_tree_model_get_iter_first(model, &iter);
|
||||
while (cont)
|
||||
{
|
||||
TMTag *tag;
|
||||
|
||||
gtk_tree_model_get(model, &iter, SYMBOLS_COLUMN_TAG, &tag, -1);
|
||||
if (tag)
|
||||
g_hash_table_insert(table, tag, gtk_tree_model_get_path(model, &iter));
|
||||
}
|
||||
while (next_iter(model, &iter));
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
|
||||
static gboolean find_iter(GtkTreeStore *store, GHashTable *iter_hash, const TMTag *tag,
|
||||
GtkTreeIter *iter)
|
||||
{
|
||||
GtkTreePath *path;
|
||||
|
||||
path = g_hash_table_lookup(iter_hash, tag);
|
||||
if (path)
|
||||
{
|
||||
GtkTreeIter tmp;
|
||||
gboolean valid;
|
||||
|
||||
if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &tmp, path))
|
||||
return FALSE;
|
||||
gtk_tree_model_get(GTK_TREE_MODEL(store), &tmp, SYMBOLS_COLUMN_VALID, &valid, -1);
|
||||
/* if the row is valid it has already been updated, so it's simply a duplicate */
|
||||
if (!valid)
|
||||
if (! tag) /* most probably a toplevel, skip it */
|
||||
cont = next_iter(model, &iter, TRUE);
|
||||
else
|
||||
{
|
||||
*iter = tmp;
|
||||
return TRUE;
|
||||
GList *found_item;
|
||||
|
||||
found_item = g_hash_table_lookup(tags_table, tag);
|
||||
if (! found_item) /* tag doesn't exist, remove it */
|
||||
cont = tree_store_remove_row(store, &iter);
|
||||
else /* tag still exist, update it */
|
||||
{
|
||||
const gchar *name;
|
||||
const gchar *parent_name;
|
||||
TMTag *found = found_item->data;
|
||||
|
||||
parent_name = get_parent_name(found, doc->file_type->id);
|
||||
/* if parent is unknown, ignore it */
|
||||
if (parent_name && ! g_hash_table_lookup(parents_table, parent_name))
|
||||
parent_name = NULL;
|
||||
|
||||
/* only update fields that (can) have changed (name that holds line
|
||||
* number, and the tag itself) */
|
||||
name = get_symbol_name(doc, found, parent_name != NULL);
|
||||
gtk_tree_store_set(store, &iter,
|
||||
SYMBOLS_COLUMN_NAME, name,
|
||||
SYMBOLS_COLUMN_TAG, found,
|
||||
-1);
|
||||
|
||||
update_parents_table(parents_table, found, parent_name, &iter);
|
||||
|
||||
/* remove the updated tag from the table and list */
|
||||
g_hash_table_remove(tags_table, found);
|
||||
*tags = g_list_delete_link(*tags, found_item);
|
||||
|
||||
cont = next_iter(model, &iter, TRUE);
|
||||
}
|
||||
|
||||
tm_tag_unref(tag);
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static void add_tree_tag(GeanyDocument *doc, const TMTag *tag, GHashTable *parent_hash,
|
||||
GHashTable *iter_hash)
|
||||
{
|
||||
filetype_id ft_id = doc->file_type->id;
|
||||
GtkTreeStore *tree_store = doc->priv->tag_store;
|
||||
GtkTreeIter *parent = NULL;
|
||||
|
||||
parent = get_tag_type_iter(tag->type, ft_id);
|
||||
|
||||
if (G_LIKELY(parent))
|
||||
/* Second pass, now we have a tree cleaned up from invalid rows,
|
||||
* we simply add new ones */
|
||||
foreach_list (item, *tags)
|
||||
{
|
||||
const gchar *name;
|
||||
const gchar *parent_name = get_parent_name(tag, ft_id);
|
||||
GtkTreeIter iter;
|
||||
GtkTreeIter *child = NULL;
|
||||
GdkPixbuf *icon = NULL;
|
||||
gchar *tooltip;
|
||||
TMTag *tag = item->data;
|
||||
GtkTreeIter *parent;
|
||||
|
||||
child = &iter;
|
||||
icon = get_child_icon(tree_store, parent);
|
||||
|
||||
if (parent_name)
|
||||
parent = get_tag_type_iter(tag->type, doc->file_type->id);
|
||||
if (G_UNLIKELY(! parent))
|
||||
geany_debug("Missing symbol-tree parent iter for type %d!", tag->type);
|
||||
else
|
||||
{
|
||||
GtkTreeIter *parent_search =
|
||||
(GtkTreeIter *)g_hash_table_lookup(parent_hash, parent_name);
|
||||
gboolean expand;
|
||||
const gchar *name;
|
||||
const gchar *parent_name;
|
||||
gchar *tooltip;
|
||||
GdkPixbuf *icon = get_child_icon(store, parent);
|
||||
|
||||
if (parent_search)
|
||||
parent = parent_search;
|
||||
else
|
||||
parent_name = NULL;
|
||||
}
|
||||
parent_name = get_parent_name(tag, doc->file_type->id);
|
||||
if (parent_name)
|
||||
{
|
||||
GtkTreeIter *parent_search;
|
||||
|
||||
/* check if the current tag is a parent of other tags */
|
||||
if (g_hash_table_lookup_extended(parent_hash, tag->name, NULL, NULL) &&
|
||||
!utils_str_equal(tag->name, parent_name)) /* prevent Foo::Foo from making parent = child */
|
||||
{
|
||||
GtkTreeIter *new_iter = g_new0(GtkTreeIter, 1);
|
||||
|
||||
/* set an iter value for the hash key */
|
||||
g_hash_table_insert(parent_hash, tag->name, new_iter);
|
||||
/* instead of ignoring the appended child iter below, use the one in the hash table */
|
||||
child = new_iter;
|
||||
}
|
||||
|
||||
if (!find_iter(tree_store, iter_hash, tag, child))
|
||||
{
|
||||
gboolean expand = FALSE;
|
||||
parent_search = g_hash_table_lookup(parents_table, parent_name);
|
||||
if (parent_search)
|
||||
parent = parent_search;
|
||||
else
|
||||
parent_name = NULL;
|
||||
}
|
||||
|
||||
/* only expand to the iter if the parent was empty, otherwise we let the
|
||||
* folding as it was before (already expanded, or closed by the user) */
|
||||
expand = !gtk_tree_model_iter_has_child(GTK_TREE_MODEL(tree_store), parent);
|
||||
gtk_tree_store_append(tree_store, child, parent);
|
||||
expand = ! gtk_tree_model_iter_has_child(model, parent);
|
||||
|
||||
/* insert the new element */
|
||||
gtk_tree_store_append(store, &iter, parent);
|
||||
name = get_symbol_name(doc, tag, parent_name != NULL);
|
||||
tooltip = get_symbol_tooltip(doc, tag);
|
||||
gtk_tree_store_set(store, &iter,
|
||||
SYMBOLS_COLUMN_NAME, name,
|
||||
SYMBOLS_COLUMN_TOOLTIP, tooltip,
|
||||
SYMBOLS_COLUMN_ICON, icon,
|
||||
SYMBOLS_COLUMN_TAG, tag,
|
||||
-1);
|
||||
g_free(tooltip);
|
||||
if (G_LIKELY(icon))
|
||||
g_object_unref(icon);
|
||||
|
||||
update_parents_table(parents_table, tag, parent_name, &iter);
|
||||
|
||||
if (expand)
|
||||
{
|
||||
GtkTreePath *path;
|
||||
|
||||
path = gtk_tree_model_get_path(GTK_TREE_MODEL(tree_store), child);
|
||||
gtk_tree_view_expand_to_path(GTK_TREE_VIEW(doc->priv->tag_tree), path);
|
||||
gtk_tree_path_free(path);
|
||||
}
|
||||
tree_view_expand_to_iter(GTK_TREE_VIEW(doc->priv->tag_tree), &iter);
|
||||
}
|
||||
|
||||
name = get_symbol_name(doc, tag, (parent_name != NULL));
|
||||
tooltip = get_symbol_tooltip(doc, tag);
|
||||
gtk_tree_store_set(tree_store, child,
|
||||
SYMBOLS_COLUMN_ICON, icon,
|
||||
SYMBOLS_COLUMN_NAME, name,
|
||||
SYMBOLS_COLUMN_TAG, tag,
|
||||
SYMBOLS_COLUMN_VALID, TRUE,
|
||||
SYMBOLS_COLUMN_TOOLTIP, tooltip,
|
||||
-1);
|
||||
|
||||
g_free(tooltip);
|
||||
if (G_LIKELY(G_IS_OBJECT(icon)))
|
||||
g_object_unref(icon);
|
||||
}
|
||||
else
|
||||
geany_debug("Missing symbol-tree parent iter for type %d!", tag->type);
|
||||
}
|
||||
|
||||
|
||||
static void add_tree_tags(GeanyDocument *doc, const GList *tags)
|
||||
{
|
||||
const GList *item;
|
||||
GHashTable *parent_hash;
|
||||
GHashTable *iter_hash;
|
||||
|
||||
/* Create a hash table "parent_tag_name":(GtkTreeIter*) */
|
||||
parent_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
|
||||
iter_hash = build_iter_table(doc->priv->tag_store);
|
||||
|
||||
/* find and store all parent names in the hash table */
|
||||
for (item = tags; item; item = g_list_next(item))
|
||||
{
|
||||
const TMTag *tag = item->data;
|
||||
const gchar *name = get_parent_name(tag, doc->file_type->id);
|
||||
|
||||
if (name)
|
||||
g_hash_table_insert(parent_hash, (gpointer)name, NULL);
|
||||
}
|
||||
for (item = tags; item; item = g_list_next(item))
|
||||
{
|
||||
const TMTag *tag = item->data;
|
||||
|
||||
add_tree_tag(doc, tag, parent_hash, iter_hash);
|
||||
}
|
||||
g_hash_table_destroy(iter_hash);
|
||||
g_hash_table_destroy(parent_hash);
|
||||
g_hash_table_destroy(parents_table);
|
||||
g_hash_table_destroy(tags_table);
|
||||
}
|
||||
|
||||
|
||||
@ -1390,16 +1434,17 @@ static gint compare_top_level_names(const gchar *a, const gchar *b)
|
||||
guint i;
|
||||
const gchar *name;
|
||||
|
||||
/* This should never happen as it would mean that two or more top
|
||||
* level items have the same name but it can happen by typos in the translations. */
|
||||
if (utils_str_equal(a, b))
|
||||
return 1;
|
||||
|
||||
foreach_ptr_array(name, i, top_level_iter_names)
|
||||
{
|
||||
if (utils_str_equal(name, a))
|
||||
return -1;
|
||||
if (utils_str_equal(name, b))
|
||||
return 1;
|
||||
/* This should never happen as it would mean that two or more top
|
||||
* level items have the same name but it can happen by typos in the translations. */
|
||||
if (utils_str_equal(a, b))
|
||||
return 1;
|
||||
}
|
||||
g_warning("Couldn't find top level node '%s' or '%s'!", a, b);
|
||||
return 0;
|
||||
@ -1450,7 +1495,7 @@ static gint tree_sort_func(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b,
|
||||
/* this is what g_strcmp0() does */
|
||||
if (! astr)
|
||||
cmp = -(astr != bstr);
|
||||
if (! bstr)
|
||||
else if (! bstr)
|
||||
cmp = astr != bstr;
|
||||
else
|
||||
{
|
||||
@ -1483,53 +1528,6 @@ static void sort_tree(GtkTreeStore *store, gboolean sort_by_name)
|
||||
}
|
||||
|
||||
|
||||
static void invalidate_rows(GtkTreeStore *store)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
GtkTreeModel *model = GTK_TREE_MODEL(store);
|
||||
|
||||
if (!gtk_tree_model_get_iter_first(model, &iter))
|
||||
return;
|
||||
do
|
||||
{
|
||||
gtk_tree_store_set(store, &iter, SYMBOLS_COLUMN_VALID, FALSE, -1);
|
||||
}
|
||||
while (next_iter(model, &iter));
|
||||
}
|
||||
|
||||
|
||||
static void remove_invalid_rows(GtkTreeStore *store)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
GtkTreeModel *model = GTK_TREE_MODEL(store);
|
||||
gboolean cont;
|
||||
|
||||
cont = gtk_tree_model_get_iter_first(model, &iter);
|
||||
while (cont)
|
||||
{
|
||||
gboolean valid;
|
||||
|
||||
gtk_tree_model_get(model, &iter, SYMBOLS_COLUMN_VALID, &valid, -1);
|
||||
if (!valid)
|
||||
{
|
||||
GtkTreeIter parent;
|
||||
gboolean have_parent;
|
||||
|
||||
have_parent = gtk_tree_model_iter_parent(model, &parent, &iter);
|
||||
cont = gtk_tree_store_remove(store, &iter);
|
||||
/* if there is no next at this level but there is a parent iter, continue from it */
|
||||
if (!cont && have_parent)
|
||||
{
|
||||
iter = parent;
|
||||
cont = next_iter(model, &iter);
|
||||
}
|
||||
}
|
||||
else
|
||||
cont = next_iter(model, &iter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gboolean symbols_recreate_tag_list(GeanyDocument *doc, gint sort_mode)
|
||||
{
|
||||
GList *tags;
|
||||
@ -1546,16 +1544,12 @@ gboolean symbols_recreate_tag_list(GeanyDocument *doc, gint sort_mode)
|
||||
* models that are currently being built */
|
||||
gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(doc->priv->tag_store), GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, 0);
|
||||
|
||||
/* invalidate all content */
|
||||
invalidate_rows(doc->priv->tag_store);
|
||||
|
||||
/* add grandparent type iters */
|
||||
add_top_level_items(doc);
|
||||
|
||||
add_tree_tags(doc, tags);
|
||||
update_tree_tags(doc, &tags);
|
||||
g_list_free(tags);
|
||||
|
||||
remove_invalid_rows(doc->priv->tag_store);
|
||||
hide_empty_rows(doc->priv->tag_store);
|
||||
|
||||
if (sort_mode == SYMBOLS_SORT_USE_PREVIOUS)
|
||||
|
@ -364,12 +364,7 @@ static void make_comment_block(GString *comment_text, gint filetype_idx, guint i
|
||||
template_eol_mode = utils_get_line_endings(comment_text->str, comment_text->len);
|
||||
template_eol_char = utils_get_eol_char(template_eol_mode);
|
||||
|
||||
co = ft->comment_open;
|
||||
cc = NULL;
|
||||
if (NZV(co))
|
||||
cc = ft->comment_close;
|
||||
else
|
||||
co = ft->comment_single;
|
||||
filetype_get_comment_open_close(ft, FALSE, &co, &cc);
|
||||
if (NZV(co))
|
||||
{
|
||||
if (NZV(cc))
|
||||
|
@ -377,7 +377,7 @@ GtkWidget *toolbar_init(void)
|
||||
gtk_action_group_add_action(group, action_build);
|
||||
|
||||
action_searchentry = geany_entry_action_new(
|
||||
"SearchEntry", _("Search"), _("Find the entered text in the current file"), FALSE);
|
||||
"SearchEntry", _("Search Field"), _("Find the entered text in the current file"), FALSE);
|
||||
g_signal_connect(action_searchentry, "entry-activate",
|
||||
G_CALLBACK(on_toolbar_search_entry_activate), GINT_TO_POINTER(FALSE));
|
||||
g_signal_connect(action_searchentry, "entry-activate-backward",
|
||||
@ -387,7 +387,7 @@ GtkWidget *toolbar_init(void)
|
||||
gtk_action_group_add_action(group, action_searchentry);
|
||||
|
||||
action_gotoentry = geany_entry_action_new(
|
||||
"GotoEntry", _("Goto"), _("Jump to the entered line number"), TRUE);
|
||||
"GotoEntry", _("Goto Field"), _("Jump to the entered line number"), TRUE);
|
||||
g_signal_connect(action_gotoentry, "entry-activate",
|
||||
G_CALLBACK(on_toolbutton_goto_entry_activate), NULL);
|
||||
gtk_action_group_add_action(group, action_gotoentry);
|
||||
|
11
src/utils.h
11
src/utils.h
@ -35,11 +35,14 @@
|
||||
#define NZV(ptr) \
|
||||
((ptr) && (ptr)[0])
|
||||
|
||||
/**
|
||||
* Frees @a ptr (if not @c NULL), then assigns @a result to it.
|
||||
* @a result can be an expression using the 'old' value of @a ptr.
|
||||
* It prevents a memory leak compared with: @code ptr = func(ptr); @endcode
|
||||
/** Assigns @a result to @a ptr, then frees the old value.
|
||||
* @a result can be an expression using the 'old' value of @a ptr.
|
||||
* E.g. @code SETPTR(str, g_strndup(str, 5)); @endcode
|
||||
**/
|
||||
#define SETPTR(ptr, result) \
|
||||
do setptr(ptr, result) while (0)
|
||||
|
||||
/** @deprecated 2011/11/15 - use SETPTR() instead. */
|
||||
#define setptr(ptr, result) \
|
||||
{\
|
||||
gpointer setptr_tmp = ptr;\
|
||||
|
@ -297,6 +297,7 @@ void vte_close(void)
|
||||
g_free(vc->font);
|
||||
g_free(vc->colour_back);
|
||||
g_free(vc->colour_fore);
|
||||
g_free(vc->send_cmd_prefix);
|
||||
g_free(vc);
|
||||
g_free(gtk_menu_key_accel);
|
||||
/* Don't unload the module explicitly because it causes a segfault on FreeBSD. The segfault
|
||||
@ -662,7 +663,7 @@ void vte_cwd(const gchar *filename, gboolean force)
|
||||
{
|
||||
/* use g_shell_quote to avoid problems with spaces, '!' or something else in path */
|
||||
gchar *quoted_path = g_shell_quote(path);
|
||||
gchar *cmd = g_strconcat("cd ", quoted_path, "\n", NULL);
|
||||
gchar *cmd = g_strconcat(vc->send_cmd_prefix, "cd ", quoted_path, "\n", NULL);
|
||||
if (! vte_send_cmd(cmd))
|
||||
{
|
||||
ui_set_statusbar(FALSE,
|
||||
|
@ -55,6 +55,7 @@ typedef struct
|
||||
gchar *emulation;
|
||||
gchar *shell;
|
||||
gchar *font;
|
||||
gchar *send_cmd_prefix;
|
||||
GdkColor *colour_fore;
|
||||
GdkColor *colour_back;
|
||||
} VteConfig;
|
||||
|
@ -1104,9 +1104,8 @@ static gboolean CreateChildProcess(geany_win32_spawn *gw_spawn, TCHAR *szCmdline
|
||||
else
|
||||
{
|
||||
gint i;
|
||||
DWORD dwStatus;
|
||||
|
||||
for (i = 0; i < 2 && (dwStatus = WaitForSingleObject(piProcInfo.hProcess, 30*1000)) == WAIT_TIMEOUT; i++)
|
||||
for (i = 0; i < 2 && WaitForSingleObject(piProcInfo.hProcess, 30*1000) == WAIT_TIMEOUT; i++)
|
||||
{
|
||||
geany_debug("CreateChildProcess: CreateProcess failed");
|
||||
TerminateProcess(piProcInfo.hProcess, WAIT_TIMEOUT); /* NOTE: This will not kill grandkids. */
|
||||
|
@ -53,6 +53,7 @@ libtagmanager_a_SOURCES =\
|
||||
lregex.c\
|
||||
matlab.c\
|
||||
markdown.c\
|
||||
objc.c\
|
||||
pascal.c\
|
||||
perl.c\
|
||||
rest.c\
|
||||
|
@ -40,7 +40,7 @@ clean:
|
||||
-$(RM) deps.mak *.o $(COMPLIB)
|
||||
|
||||
$(COMPLIB): abc.o args.o c.o cobol.o fortran.o make.o conf.o pascal.o perl.o php.o diff.o vhdl.o verilog.o lua.o js.o \
|
||||
actionscript.o nsis.o \
|
||||
actionscript.o nsis.o objc.o \
|
||||
haskell.o haxe.o html.o python.o lregex.o rest.o sh.o ctags.o entry.o get.o keyword.o nestlevel.o \
|
||||
options.o \
|
||||
parse.o basic.o read.o sort.o strlist.o latex.o markdown.o matlab.o docbook.o tcl.o ruby.o asm.o sql.o txt2tags.o css.o \
|
||||
|
1142
tagmanager/objc.c
Normal file
1142
tagmanager/objc.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -56,7 +56,8 @@
|
||||
AbcParser, \
|
||||
VerilogParser, \
|
||||
RParser, \
|
||||
CobolParser
|
||||
CobolParser, \
|
||||
ObjcParser
|
||||
/*
|
||||
langType of each parser
|
||||
0 CParser
|
||||
@ -101,6 +102,7 @@ langType of each parser
|
||||
39 Verilog
|
||||
40 RParser
|
||||
41 CobolParser
|
||||
42 ObjcParser
|
||||
*/
|
||||
#endif /* _PARSERS_H */
|
||||
|
||||
|
2
wscript
2
wscript
@ -66,7 +66,7 @@ tagmanager_sources = set([
|
||||
'tagmanager/haskell.c', 'tagmanager/haxe.c', 'tagmanager/html.c', 'tagmanager/js.c',
|
||||
'tagmanager/keyword.c', 'tagmanager/latex.c', 'tagmanager/lregex.c', 'tagmanager/lua.c',
|
||||
'tagmanager/make.c', 'tagmanager/markdown.c', 'tagmanager/matlab.c', 'tagmanager/nsis.c',
|
||||
'tagmanager/nestlevel.c', 'tagmanager/options.c',
|
||||
'tagmanager/nestlevel.c', 'tagmanager/objc.c', 'tagmanager/options.c',
|
||||
'tagmanager/parse.c', 'tagmanager/pascal.c', 'tagmanager/r.c',
|
||||
'tagmanager/perl.c', 'tagmanager/php.c', 'tagmanager/python.c', 'tagmanager/read.c',
|
||||
'tagmanager/rest.c', 'tagmanager/ruby.c', 'tagmanager/sh.c', 'tagmanager/sort.c',
|
||||
|
Loading…
x
Reference in New Issue
Block a user