summaryrefslogtreecommitdiffstats
path: root/parts/ctags2
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit114a878c64ce6f8223cfd22d76a20eb16d177e5e (patch)
treeacaf47eb0fa12142d3896416a69e74cbf5a72242 /parts/ctags2
downloadtdevelop-114a878c64ce6f8223cfd22d76a20eb16d177e5e.tar.gz
tdevelop-114a878c64ce6f8223cfd22d76a20eb16d177e5e.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdevelop@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'parts/ctags2')
-rw-r--r--parts/ctags2/Makefile.am22
-rw-r--r--parts/ctags2/README.dox16
-rw-r--r--parts/ctags2/ctags2_createtagfile.cpp53
-rw-r--r--parts/ctags2/ctags2_createtagfile.h36
-rw-r--r--parts/ctags2/ctags2_createtagfilebase.ui151
-rw-r--r--parts/ctags2/ctags2_part.cpp371
-rw-r--r--parts/ctags2/ctags2_part.h69
-rw-r--r--parts/ctags2/ctags2_selecttagfile.cpp47
-rw-r--r--parts/ctags2/ctags2_selecttagfile.h33
-rw-r--r--parts/ctags2/ctags2_selecttagfilebase.ui128
-rw-r--r--parts/ctags2/ctags2_settingswidget.cpp173
-rw-r--r--parts/ctags2/ctags2_settingswidget.h69
-rw-r--r--parts/ctags2/ctags2_settingswidgetbase.ui382
-rw-r--r--parts/ctags2/ctags2_widget.cpp199
-rw-r--r--parts/ctags2/ctags2_widget.h56
-rw-r--r--parts/ctags2/ctags2_widgetbase.ui181
-rw-r--r--parts/ctags2/ctagskinds.cpp306
-rw-r--r--parts/ctags2/ctagskinds.h24
-rw-r--r--parts/ctags2/kdevctags2.desktop82
-rw-r--r--parts/ctags2/kdevpart_ctags2.rc12
-rw-r--r--parts/ctags2/readtags.c960
-rw-r--r--parts/ctags2/readtags.h251
-rw-r--r--parts/ctags2/tagitem.cpp23
-rw-r--r--parts/ctags2/tagitem.h29
-rw-r--r--parts/ctags2/tags.cpp171
-rw-r--r--parts/ctags2/tags.h74
26 files changed, 3918 insertions, 0 deletions
diff --git a/parts/ctags2/Makefile.am b/parts/ctags2/Makefile.am
new file mode 100644
index 00000000..06b3cfea
--- /dev/null
+++ b/parts/ctags2/Makefile.am
@@ -0,0 +1,22 @@
+INCLUDES = -I$(top_srcdir)/lib/interfaces \
+ -I$(top_srcdir)/lib/interfaces/extensions -I$(top_srcdir)/lib/util $(all_includes)
+
+kde_module_LTLIBRARIES = libkdevctags2.la
+libkdevctags2_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN)
+libkdevctags2_la_LIBADD = $(top_builddir)/lib/libkdevelop.la
+
+libkdevctags2_la_SOURCES = ctags2_part.cpp readtags.c ctags2_widgetbase.ui \
+ ctags2_widget.cpp tags.cpp ctagskinds.cpp ctags2_settingswidgetbase.ui \
+ ctags2_settingswidget.cpp ctags2_selecttagfilebase.ui ctags2_selecttagfile.cpp \
+ ctags2_createtagfilebase.ui ctags2_createtagfile.cpp
+
+METASOURCES = AUTO
+
+servicedir = $(kde_servicesdir)
+service_DATA = kdevctags2.desktop
+
+rc_DATA = kdevpart_ctags2.rc
+rcdir = $(kde_datadir)/kdevctags2
+
+noinst_HEADERS = ctags2_widget.h tags.h readtags.h ctagskinds.h \
+ ctags2_settingswidget.h
diff --git a/parts/ctags2/README.dox b/parts/ctags2/README.dox
new file mode 100644
index 00000000..e45d0bff
--- /dev/null
+++ b/parts/ctags2/README.dox
@@ -0,0 +1,16 @@
+/** \class ctags2
+This is a CTAGS frontend based on the 'readtags' library.
+
+\authors <a href="mailto:jens.dagerbo AT swipnet.se">Jens Dagerbo</a>
+
+\maintainer <a href="mailto:jens.dagerbo AT swipnet.se">Jens Dagerbo</a>
+
+\feature A very fast CTAGS lookup plugin
+\feature Through the use of regular expressions, it is clever enough to find matches even
+if the match-containing file is open and edited (and the editor contents do not match the file on disk).
+
+\requirement Needs "Exuberant CTAGS" to work. http://ctags.sourceforge.net/
+
+\todo Probably a lot, but mainly configurability.
+
+*/
diff --git a/parts/ctags2/ctags2_createtagfile.cpp b/parts/ctags2/ctags2_createtagfile.cpp
new file mode 100644
index 00000000..b1ced0dd
--- /dev/null
+++ b/parts/ctags2/ctags2_createtagfile.cpp
@@ -0,0 +1,53 @@
+/***************************************************************************
+ * Copyright (C) 2006 by Jens Dagerbo *
+ * jens.dagerbo@swipnet.se *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <kurlrequester.h>
+#include <klineedit.h>
+
+#include "ctags2_createtagfile.h"
+#include "ctags2_part.h"
+
+
+CreateTagFile::CreateTagFile(QWidget* parent, const char* name, bool modal, WFlags fl)
+: CTags2CreateTagFileBase( parent, name, modal, fl )
+{
+ dirToTag->setMode( KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly);
+ newTagFilePath->setMode( KFile::File | KFile::LocalOnly );
+ createTagFileButton->setEnabled( false );
+}
+
+CreateTagFile::~CreateTagFile()
+{
+}
+
+void CreateTagFile::validate()
+{
+ bool valid = ( !displayName->text().isEmpty() && !newTagFilePath->url().isEmpty() && !dirToTag->url().isEmpty() );
+
+ createTagFileButton->setEnabled( valid );
+}
+
+QString CreateTagFile::name( )
+{
+ return displayName->text();
+}
+
+QString CreateTagFile::tagsfilePath( )
+{
+ return newTagFilePath->url();
+}
+
+QString CreateTagFile::directory( )
+{
+ return dirToTag->url();
+}
+
+// kate: space-indent off; indent-width 4; tab-width 4; show-tabs off;
diff --git a/parts/ctags2/ctags2_createtagfile.h b/parts/ctags2/ctags2_createtagfile.h
new file mode 100644
index 00000000..93b530d4
--- /dev/null
+++ b/parts/ctags2/ctags2_createtagfile.h
@@ -0,0 +1,36 @@
+/***************************************************************************
+ * Copyright (C) 2006 by Jens Dagerbo *
+ * jens.dagerbo@swipnet.se *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef CTAGS2_CREATETAGFILE_H
+#define CTAGS2_CREATETAGFILE_H
+
+#include "ctags2_part.h"
+#include "ctags2_createtagfilebase.h"
+
+
+class CreateTagFile : public CTags2CreateTagFileBase {
+
+Q_OBJECT
+
+public:
+ CreateTagFile(QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 );
+ ~CreateTagFile();
+ QString name();
+ QString tagsfilePath();
+ QString directory();
+
+private:
+
+public slots:
+ virtual void validate();
+};
+
+#endif
diff --git a/parts/ctags2/ctags2_createtagfilebase.ui b/parts/ctags2/ctags2_createtagfilebase.ui
new file mode 100644
index 00000000..bf4469f3
--- /dev/null
+++ b/parts/ctags2/ctags2_createtagfilebase.ui
@@ -0,0 +1,151 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>CTags2CreateTagFileBase</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>CTags2CreateTagFileBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>373</width>
+ <height>198</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Create new tags file</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Name:</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>displayName</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1_3</cstring>
+ </property>
+ <property name="text">
+ <string>Target tags file path:</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester">
+ <property name="name">
+ <cstring>newTagFilePath</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Directory to tag:</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester">
+ <property name="name">
+ <cstring>dirToTag</cstring>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>81</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>createTagFileButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Create</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>cancelButton</cstring>
+ </property>
+ <property name="text">
+ <string>C&amp;ancel</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>cancelButton</sender>
+ <signal>clicked()</signal>
+ <receiver>CTags2CreateTagFileBase</receiver>
+ <slot>reject()</slot>
+ </connection>
+ <connection>
+ <sender>createTagFileButton</sender>
+ <signal>clicked()</signal>
+ <receiver>CTags2CreateTagFileBase</receiver>
+ <slot>accept()</slot>
+ </connection>
+ <connection>
+ <sender>displayName</sender>
+ <signal>textChanged(const QString&amp;)</signal>
+ <receiver>CTags2CreateTagFileBase</receiver>
+ <slot>validate()</slot>
+ </connection>
+ <connection>
+ <sender>newTagFilePath</sender>
+ <signal>textChanged(const QString&amp;)</signal>
+ <receiver>CTags2CreateTagFileBase</receiver>
+ <slot>validate()</slot>
+ </connection>
+ <connection>
+ <sender>dirToTag</sender>
+ <signal>textChanged(const QString&amp;)</signal>
+ <receiver>CTags2CreateTagFileBase</receiver>
+ <slot>validate()</slot>
+ </connection>
+</connections>
+<slots>
+ <slot>createTagFile()</slot>
+ <slot>validate()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/parts/ctags2/ctags2_part.cpp b/parts/ctags2/ctags2_part.cpp
new file mode 100644
index 00000000..29b564e6
--- /dev/null
+++ b/parts/ctags2/ctags2_part.cpp
@@ -0,0 +1,371 @@
+/***************************************************************************
+ * Copyright (C) 2004 by Jens Dagerbo *
+ * jens.dagerbo@swipnet.se *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <qwhatsthis.h>
+#include <qpopupmenu.h>
+#include <qtextstream.h>
+#include <qfile.h>
+#include <qregexp.h>
+
+#include <klineedit.h>
+#include <klistview.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kparts/part.h>
+#include <ktexteditor/document.h>
+#include <ktexteditor/editinterface.h>
+#include <ktexteditor/viewcursorinterface.h>
+#include <kprocess.h>
+#include <kdebug.h>
+#include <kstringhandler.h>
+#include <kdialogbase.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kaction.h>
+
+#include "kdevappfrontend.h"
+#include <kdevgenericfactory.h>
+#include <kdevcore.h>
+#include <kdevmainwindow.h>
+#include <kdevproject.h>
+#include <kdevpartcontroller.h>
+#include <kdevplugininfo.h>
+#include "configwidgetproxy.h"
+#include "domutil.h"
+#include "kdeveditorutil.h"
+
+#include "ctags2_settingswidget.h"
+#include "ctags2_widget.h"
+#include "ctags2_part.h"
+#include "tags.h"
+
+#define CTAGSSETTINGSPAGE 1
+
+namespace ctags
+{
+#include "readtags.h"
+}
+
+typedef KDevGenericFactory<CTags2Part> CTags2Factory;
+static const KDevPluginInfo data("kdevctags2");
+K_EXPORT_COMPONENT_FACTORY( libkdevctags2, CTags2Factory( data ) )
+
+CTags2Part::CTags2Part(QObject *parent, const char *name, const QStringList& )
+ : KDevPlugin(&data, parent, name ? name : "ctags2Part" )
+{
+ setInstance(CTags2Factory::instance());
+ setXMLFile("kdevpart_ctags2.rc");
+
+ QDomDocument & dom = *projectDom();
+ QString customTagFile = DomUtil::readEntry( dom, "/ctagspart/customTagfilePath" );
+ if ( customTagFile.isEmpty() )
+ {
+ customTagFile = project()->projectDirectory() + "/tags";
+ }
+ QStringList tagFiles = DomUtil::readListEntry(dom, "/ctagspart/activeTagsFiles", "file");
+ tagFiles.push_front(customTagFile);
+
+ Tags::setTagFiles(tagFiles);
+
+ m_widget = new CTags2Widget(this);
+
+ QWhatsThis::add(m_widget, i18n("<b>CTags</b><p>Result view for a tag lookup. Click a line to go to the corresponding place in the code."));
+ m_widget->setCaption(i18n("CTags Lookup"));
+ mainWindow()->embedOutputView( m_widget, i18n( "CTags" ), i18n( "CTags lookup results" ) );
+
+ connect( core(), SIGNAL(contextMenu(QPopupMenu *, const Context *)), this, SLOT(contextMenu(QPopupMenu *, const Context *)) );
+
+ _configProxy = new ConfigWidgetProxy( core() );
+ _configProxy->createProjectConfigPage( i18n("CTags"), CTAGSSETTINGSPAGE, info()->icon() );
+ connect( _configProxy, SIGNAL(insertConfigWidget(const KDialogBase*, QWidget*, unsigned int )),
+ this, SLOT(insertConfigWidget(const KDialogBase*, QWidget*, unsigned int )) );
+
+ new KAction( i18n("Lookup Current Text"), 0, CTRL+Key_Underscore, this, SLOT(slotLookup()), actionCollection(), "ctags_lookup_shortcut");
+ new KAction( i18n("Lookup Current Text as Declaration"), 0, CTRL+Key_Semicolon, this, SLOT(slotLookupDeclaration()), actionCollection(), "ctags_declaration_shortcut");
+ new KAction( i18n("Lookup Current Text as Definition"), 0, CTRL+Key_Colon, this, SLOT(slotLookupDefinition()), actionCollection(), "ctags_definition_shortcut");
+ new KAction( i18n("Jump to Next Match"), 0, 0, this, SLOT(slotGoToNext()), actionCollection(), "ctags_jump_to_next");
+ new KAction( i18n("Open Lookup Dialog"), 0, 0, this, SLOT(slotOpenLookup()), actionCollection(), "ctags_input_shortcut");
+}
+
+
+CTags2Part::~CTags2Part()
+{
+ if ( m_widget )
+ {
+ mainWindow()->removeView( m_widget );
+ }
+ delete m_widget;
+ delete _configProxy;
+}
+
+void CTags2Part::insertConfigWidget( const KDialogBase * dlg, QWidget * page, unsigned int pagenumber )
+{
+ if ( pagenumber == CTAGSSETTINGSPAGE )
+ {
+ CTags2SettingsWidget * w = new CTags2SettingsWidget( this, page );
+ connect( dlg, SIGNAL(okClicked()), w, SLOT(slotAccept()) );
+ connect( w, SIGNAL(newTagsfileName(const QString& )), this, SLOT(updateTagsfileName(const QString& )) );
+ }
+}
+
+void CTags2Part::updateTagsfileName( const QString & )
+{
+ m_widget->updateDBDateLabel();
+}
+
+// wrapper for creating a tag file for the current project
+bool CTags2Part::createTagsFile()
+{
+ // check if user specified a custom tag file name
+ QDomDocument & dom = *projectDom();
+ QString tagsFileCustom = DomUtil::readEntry( dom, "/ctagspart/customTagfilePath" ).stripWhiteSpace();
+
+ return createTagsFile(tagsFileCustom, project()->projectDirectory());
+}
+
+// creates a new tag file with the specified name for the specified source directory
+bool CTags2Part::createTagsFile(const QString& tagFile, const QString& dir)
+{
+/*
+ KProcess proc;
+ proc.setWorkingDirectory( project()->projectDirectory() );
+
+ proc << "ctags";
+ proc << "-R" << "--c++-types=+px" << "--excmd=pattern" << "--exclude=Makefile";
+
+ bool success = proc.start(KProcess::Block);
+
+ return success;
+*/
+
+ // get name of the ctags binary
+ KConfig * config = kapp->config();
+ config->setGroup( "CTAGS" );
+ QString ctagsBinary = config->readEntry( "ctags binary" ).stripWhiteSpace();
+ if ( ctagsBinary.isEmpty() )
+ {
+ ctagsBinary = "ctags";
+ }
+
+ // set a default argument list
+ QString argsDefault = "-R --c++-types=+px --excmd=pattern --exclude=Makefile --exclude=.";
+
+ QDomDocument & dom = *projectDom();
+ QString argsCustom = DomUtil::readEntry( dom, "/ctagspart/customArguments" ).stripWhiteSpace();
+ QString commandline = ctagsBinary + " " + ( argsCustom.isEmpty() ? argsDefault : argsCustom ) + ( tagFile.isEmpty() ? "" : " -f " + tagFile );
+ commandline += " ";
+ commandline += dir;
+
+ if (KDevAppFrontend *appFrontend = extension<KDevAppFrontend>("KDevelop/AppFrontend"))
+ appFrontend->startAppCommand(dir, commandline, false);
+
+ return true;
+}
+
+void CTags2Part::contextMenu(QPopupMenu *popup, const Context *context)
+{
+ if (!context->hasType( Context::EditorContext ))
+ return;
+
+ const EditorContext *econtext = static_cast<const EditorContext*>(context);
+ QString ident = econtext->currentWord();
+ if (ident.isEmpty())
+ return;
+
+ KConfig * config = kapp->config();
+ config->setGroup( "CTAGS" );
+ bool showDeclaration = config->readBoolEntry( "ShowDeclaration", true );
+ bool showDefinition = config->readBoolEntry( "ShowDefinition", true );
+ bool showLookup = config->readBoolEntry( "ShowLookup", true );
+
+ if ( Tags::hasTag( ident ) && ( showDefinition || showDeclaration || showLookup ) )
+ {
+ m_contextString = ident;
+ QString squeezed = KStringHandler::csqueeze(ident, 30);
+
+ popup->insertSeparator();
+
+ if ( showDeclaration )
+ popup->insertItem( i18n("CTags - Go to Declaration: %1").arg(squeezed), this, SLOT(slotGotoDeclaration()) );
+
+ if ( showDefinition )
+ popup->insertItem( i18n("CTags - Go to Definition: %1").arg(squeezed), this, SLOT(slotGotoDefinition()) );
+
+ if ( showLookup )
+ popup->insertItem( i18n("CTags - Lookup: %1").arg(squeezed), this, SLOT(slotGotoTag()) );
+ }
+}
+
+void CTags2Part::showHits( Tags::TagList const & tags )
+{
+ m_widget->displayHitsAndClear( tags );
+
+ mainWindow()->raiseView( m_widget );
+ m_widget->output_view->setFocus();
+}
+
+void CTags2Part::slotGotoTag( )
+{
+ showHits( Tags::getExactMatches( m_contextString ) );
+}
+
+void CTags2Part::gotoTagForTypes( QStringList const & types )
+{
+ Tags::TagList list = Tags::getMatches( m_contextString, false, types );
+
+ if ( list.count() < 1 ) return;
+
+ KConfig * config = kapp->config();
+ config->setGroup("CTAGS");
+ bool jumpToFirst = config->readBoolEntry( "JumpToFirst", false );
+
+ if ( list.count() == 1 || jumpToFirst )
+ {
+ Tags::TagEntry tag = list.first();
+ KURL url;
+ QString fileWithTagInside;
+ // assume relative path to project directory if path does not start with slash
+ if (tag.file[0] != '/') {
+ fileWithTagInside = project()->projectDirectory() + "/" + tag.file;
+ }
+ else {
+ fileWithTagInside = tag.file;
+ }
+ url.setPath(fileWithTagInside);
+ partController()->editDocument( url, getFileLineFromPattern( url, tag.pattern ) );
+ m_widget->displayHitsAndClear( list );
+ }
+ else
+ {
+ showHits( list );
+ }
+}
+
+void CTags2Part::slotGotoDefinition( )
+{
+ QStringList types;
+ types << "S" << "d" << "f" << "t" << "v";
+ gotoTagForTypes( types );
+}
+
+void CTags2Part::slotGotoDeclaration( )
+{
+ QStringList types;
+ types << "L" << "c" << "e" << "g" << "m" << "n" << "p" << "s" << "u" << "x";
+ gotoTagForTypes( types );
+}
+
+
+int CTags2Part::getFileLineFromStream( QTextStream & istream, QString const & pattern )
+{
+ if ( pattern.isEmpty() ) return -1;
+
+ // ctags interestingly escapes "/", but apparently nothing else. lets revert that
+ QString unescaped = pattern;
+ unescaped.replace( "\\/", "/" );
+
+ // most of the time, the ctags pattern has the form /^foo$/
+ // but this isn't true for some macro definitions
+ // where the form is only /^foo/
+ // I have no idea if this is a ctags bug or not, but we have to deal with it
+
+ QString reduced, escaped, re_string;
+ if ( unescaped.endsWith( "$/" ) )
+ {
+ reduced = unescaped.mid( 2, unescaped.length() -4 );
+ escaped = QRegExp::escape( reduced );
+ re_string = QString( "^" + escaped + "$" );
+ }
+ else
+ {
+ reduced = unescaped.mid( 2, unescaped.length() -3 );
+ escaped = QRegExp::escape( reduced );
+ re_string = QString( "^" + escaped );
+ }
+
+ QRegExp re( re_string );
+
+ int n = 0;
+ while ( !istream.atEnd() )
+ {
+ if ( re.search( istream.readLine() ) > -1 )
+ {
+ return n;
+ }
+ n++;
+ }
+ return -1;
+}
+
+int CTags2Part::getFileLineFromPattern( KURL const & url, QString const & pattern )
+{
+ // if the file is open - get the line from the editor buffer
+ if ( KTextEditor::EditInterface * ei = dynamic_cast<KTextEditor::EditInterface*>( partController()->partForURL( url ) ) )
+ {
+ QString ibuffer = ei->text();
+ QTextStream istream( &ibuffer, IO_ReadOnly );
+ return getFileLineFromStream( istream, pattern );
+ }
+ else // else the file is not open - get the line from the file on disk
+ {
+ QFile file( url.path() );
+ QString buffer;
+
+ if ( file.open( IO_ReadOnly ) )
+ {
+ QTextStream istream( &file );
+ return getFileLineFromStream( istream, pattern );
+ }
+ }
+ return -1;
+}
+
+void CTags2Part::slotLookupDeclaration( )
+{
+ m_contextString = KDevEditorUtil::currentWord( dynamic_cast<KTextEditor::Document*>( partController()->activePart() ) );
+ if ( !m_contextString.isEmpty() )
+ {
+ slotGotoDeclaration();
+ }
+}
+
+void CTags2Part::slotLookupDefinition( )
+{
+ m_contextString = KDevEditorUtil::currentWord( dynamic_cast<KTextEditor::Document*>( partController()->activePart() ) );
+ if ( !m_contextString.isEmpty() )
+ {
+ slotGotoDefinition();
+ }
+}
+
+void CTags2Part::slotLookup( )
+{
+ m_contextString = KDevEditorUtil::currentWord( dynamic_cast<KTextEditor::Document*>( partController()->activePart() ) );
+ if ( !m_contextString.isEmpty() )
+ {
+ slotGotoTag();
+ }
+}
+
+void CTags2Part::slotOpenLookup( )
+{
+ mainWindow()->raiseView( m_widget );
+ m_widget->input_edit->setFocus();
+}
+
+void CTags2Part::slotGoToNext( )
+{
+ m_widget->goToNext();
+}
+
+#include "ctags2_part.moc"
+
+// kate: space-indent off; indent-width 4; tab-width 4; show-tabs off;
diff --git a/parts/ctags2/ctags2_part.h b/parts/ctags2/ctags2_part.h
new file mode 100644
index 00000000..77725500
--- /dev/null
+++ b/parts/ctags2/ctags2_part.h
@@ -0,0 +1,69 @@
+/***************************************************************************
+ * Copyright (C) 2004 by Jens Dagerbo *
+ * jens.dagerbo@swipnet.se *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __KDEVPART_CTAGS2_H__
+#define __KDEVPART_CTAGS2_H__
+
+#include <qguardedptr.h>
+#include <qstring.h>
+
+#include <kdevplugin.h>
+#include "tags.h"
+
+class QPopupMenu;
+class Context;
+class KURL;
+class QTextStream;
+class CTags2Widget;
+class ConfigWidgetProxy;
+class KDialogBase;
+
+class CTags2Part : public KDevPlugin
+{
+ Q_OBJECT
+
+public:
+
+ CTags2Part(QObject *parent, const char *name, const QStringList &);
+ ~CTags2Part();
+
+ int getFileLineFromPattern( KURL const & url, QString const & pattern);
+ bool createTagsFile();
+ bool createTagsFile(const QString& tagFile, const QString& dir);
+
+private slots:
+ void slotLookupDeclaration();
+ void slotLookupDefinition();
+ void slotLookup();
+ void slotOpenLookup();
+ void slotGoToNext();
+ void slotGotoDefinition();
+ void slotGotoDeclaration();
+ void slotGotoTag();
+ void contextMenu(QPopupMenu *, const Context *);
+ void insertConfigWidget( const KDialogBase * dlg, QWidget * page, unsigned int );
+ void updateTagsfileName( const QString & name );
+
+private:
+ int getFileLineFromStream( QTextStream & stream, QString const & pattern);
+ void gotoTagForTypes( QStringList const & types );
+ void showHits( Tags::TagList const & tags );
+
+ QGuardedPtr<CTags2Widget> m_widget;
+ QString m_contextString ;
+
+ ConfigWidgetProxy * _configProxy;
+};
+
+
+#endif
+
+// kate: space-indent off; indent-width 4; tab-width 4; show-tabs off;
diff --git a/parts/ctags2/ctags2_selecttagfile.cpp b/parts/ctags2/ctags2_selecttagfile.cpp
new file mode 100644
index 00000000..d9ae94be
--- /dev/null
+++ b/parts/ctags2/ctags2_selecttagfile.cpp
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * Copyright (C) 2006 by Jens Dagerbo *
+ * jens.dagerbo@swipnet.se *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <kurlrequester.h>
+#include <klineedit.h>
+
+#include "ctags2_selecttagfile.h"
+
+
+SelectTagFile::SelectTagFile( QWidget* parent, const char* name, bool modal, WFlags fl)
+: SelectTagFileBase( parent, name, modal, fl )
+{
+ tagFile->setMode( KFile::File | KFile::ExistingOnly | KFile::LocalOnly );
+ okButton->setEnabled( false );
+}
+
+SelectTagFile::~SelectTagFile()
+{
+}
+
+void SelectTagFile::validate()
+{
+ bool valid = ( !displayName->text().isEmpty() && !tagFile->url().isEmpty() );
+
+ okButton->setEnabled( valid );
+}
+
+QString SelectTagFile::name( )
+{
+ return displayName->text();
+}
+
+QString SelectTagFile::tagsfilePath( )
+{
+ return tagFile->url();
+}
+
+
+// kate: space-indent off; indent-width 4; tab-width 4; show-tabs off;
diff --git a/parts/ctags2/ctags2_selecttagfile.h b/parts/ctags2/ctags2_selecttagfile.h
new file mode 100644
index 00000000..103ba98c
--- /dev/null
+++ b/parts/ctags2/ctags2_selecttagfile.h
@@ -0,0 +1,33 @@
+/***************************************************************************
+ * Copyright (C) 2006 by Jens Dagerbo *
+ * jens.dagerbo@swipnet.se *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef CTAGS2_SELECTTAGFILE_H
+#define CTAGS2_SELECTTAGFILE_H
+
+#include "ctags2_selecttagfilebase.h"
+
+class SelectTagFile : public SelectTagFileBase {
+ Q_OBJECT
+
+ public:
+ SelectTagFile( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 );
+ ~SelectTagFile();
+ QString name();
+ QString tagsfilePath();
+
+public slots:
+ virtual void validate();
+};
+
+
+#endif
+
+// kate: space-indent off; indent-width 4; tab-width 4; show-tabs off;
diff --git a/parts/ctags2/ctags2_selecttagfilebase.ui b/parts/ctags2/ctags2_selecttagfilebase.ui
new file mode 100644
index 00000000..cddd5f26
--- /dev/null
+++ b/parts/ctags2/ctags2_selecttagfilebase.ui
@@ -0,0 +1,128 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>SelectTagFileBase</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>SelectTagFileBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>373</width>
+ <height>146</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Add tags file</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Name:</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>displayName</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Tags file:</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester">
+ <property name="name">
+ <cstring>tagFile</cstring>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>101</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>okButton</cstring>
+ </property>
+ <property name="text">
+ <string>O&amp;K</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>cancelButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>cancelButton</sender>
+ <signal>clicked()</signal>
+ <receiver>SelectTagFileBase</receiver>
+ <slot>reject()</slot>
+ </connection>
+ <connection>
+ <sender>okButton</sender>
+ <signal>clicked()</signal>
+ <receiver>SelectTagFileBase</receiver>
+ <slot>accept()</slot>
+ </connection>
+ <connection>
+ <sender>displayName</sender>
+ <signal>textChanged(const QString&amp;)</signal>
+ <receiver>SelectTagFileBase</receiver>
+ <slot>validate()</slot>
+ </connection>
+ <connection>
+ <sender>tagFile</sender>
+ <signal>textChanged(const QString&amp;)</signal>
+ <receiver>SelectTagFileBase</receiver>
+ <slot>validate()</slot>
+ </connection>
+</connections>
+<slots>
+ <slot>validate()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/parts/ctags2/ctags2_settingswidget.cpp b/parts/ctags2/ctags2_settingswidget.cpp
new file mode 100644
index 00000000..4bcdb122
--- /dev/null
+++ b/parts/ctags2/ctags2_settingswidget.cpp
@@ -0,0 +1,173 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Jens Dagerbo *
+ * jens.dagerbo@swipnet.se *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <qcheckbox.h>
+#include <qradiobutton.h>
+#include <qheader.h>
+
+#include <klineedit.h>
+#include <klistview.h>
+#include <kdevproject.h>
+#include <kapplication.h>
+#include <kurlcompletion.h>
+#include <kurlrequester.h>
+#include <kconfig.h>
+#include <kurl.h>
+#include <kdevplugin.h>
+#include <domutil.h>
+
+#include "ctags2_settingswidget.h"
+#include "ctags2_part.h"
+#include "ctags2_selecttagfile.h"
+#include "ctags2_createtagfile.h"
+
+
+CTags2SettingsWidget::CTags2SettingsWidget( CTags2Part * part, QWidget* parent, const char* name, WFlags fl )
+ : CTags2SettingsWidgetBase( parent, name, fl ), m_part( part )
+{
+ binaryPath->completionObject()->setMode( KURLCompletion::FileCompletion );
+ binaryPath->setMode( KFile::File | KFile::LocalOnly );
+ binaryPath->setShowLocalProtocol( false );
+
+ tagfilePath->completionObject()->setMode( KURLCompletion::FileCompletion );
+ tagfilePath->setMode( KFile::File | KFile::ExistingOnly | KFile::LocalOnly );
+ tagfilePath->setShowLocalProtocol( false );
+
+ otherTagFiles->setSorting( -1 );
+// otherTagFiles->addColumn( "" );
+// otherTagFiles->header()->hide();
+ otherTagFiles->setFullWidth( true );
+
+ loadSettings();
+}
+
+CTags2SettingsWidget::~CTags2SettingsWidget()
+{
+}
+
+void CTags2SettingsWidget::loadSettings()
+{
+ QDomDocument & dom = *m_part->projectDom();
+
+ QString customArgs = DomUtil::readEntry( dom, "/ctagspart/customArguments" );
+ if ( !customArgs.isEmpty() )
+ {
+ tagfileCustomBox->setChecked( true );
+ tagfileCustomEdit->setText( customArgs );
+ }
+
+ QString customTagfile = DomUtil::readEntry( dom, "/ctagspart/customTagfilePath" );
+ if (customTagfile.isEmpty())
+ {
+ customTagfile = m_part->project()->projectDirectory() + "/tags";
+ }
+ tagfilePath->setURL(customTagfile);
+
+ QStringList activeTagsFiles = DomUtil::readListEntry(dom, "/ctagspart/activeTagsFiles", "file");
+
+ KConfig * config = kapp->config();
+ config->setGroup( "CTAGS" );
+ showDeclarationBox->setChecked( config->readBoolEntry( "ShowDeclaration", true ) );
+ showDefinitionBox->setChecked( config->readBoolEntry( "ShowDefinition", true ) );
+ showLookupBox->setChecked( config->readBoolEntry( "ShowLookup", true ) );
+ jumpToFirstBox->setChecked( config->readBoolEntry( "JumpToFirst", false ) );
+ QString ctagsBinary = config->readEntry( "ctags binary" ).stripWhiteSpace();
+ if ( !ctagsBinary.isEmpty() )
+ {
+ binaryPath->setURL( ctagsBinary );
+ }
+
+ config->setGroup( "CTAGS-tagsfiles" );
+ QMap<QString,QString> entryMap = config->entryMap( "CTAGS-tagsfiles" );
+ QMap<QString,QString>::const_iterator it = entryMap.begin();
+ while ( it != entryMap.end() )
+ {
+ QString file = config->readPathEntry( it.key() );
+ new TagsItem( otherTagFiles, it.key(), file, activeTagsFiles.contains( file ) );
+ ++it;
+ }
+}
+
+void CTags2SettingsWidget::storeSettings()
+{
+ QDomDocument & dom = *m_part->projectDom();
+ DomUtil::writeEntry( dom, "/ctagspart/customArguments", tagfileCustomEdit->text() );
+ DomUtil::writeEntry( dom, "/ctagspart/customTagfilePath", tagfilePath->url() );
+
+ KConfig * config = kapp->config();
+ config->setGroup( "CTAGS" );
+ config->writeEntry( "ShowDeclaration", showDeclarationBox->isChecked() );
+ config->writeEntry( "ShowDefinition", showDefinitionBox->isChecked() );
+ config->writeEntry( "ShowLookup", showLookupBox->isChecked() );
+ config->writeEntry( "JumpToFirst", jumpToFirstBox->isChecked() );
+ config->writeEntry( "ctags binary", binaryPath->url() );
+
+ config->deleteGroup( "CTAGS-tagsfiles" );
+ config->setGroup( "CTAGS-tagsfiles" );
+
+ QStringList activeTagsFiles;
+ TagsItem * item = static_cast<TagsItem*>( otherTagFiles->firstChild() );
+ while ( item )
+ {
+ config->writePathEntry( item->name(), item->tagsfilePath() );
+ if ( item->isOn() )
+ {
+ activeTagsFiles.append( item->tagsfilePath() );
+ }
+ item = static_cast<TagsItem*>( item->nextSibling() );
+ }
+ DomUtil::writeListEntry( dom, "/ctagspart/activeTagsFiles", "file", activeTagsFiles );
+
+ activeTagsFiles.push_front( tagfilePath->url() );
+ Tags::setTagFiles( activeTagsFiles );
+
+ config->sync();
+
+ emit newTagsfileName( tagfilePath->url() );
+}
+
+void CTags2SettingsWidget::slotAccept( )
+{
+ storeSettings();
+}
+
+void CTags2SettingsWidget::createNewTagSlot()
+{
+ CreateTagFile* dlg = new CreateTagFile;
+ if ( dlg->exec() == QDialog::Accepted )
+ {
+ m_part->createTagsFile( dlg->tagsfilePath(), dlg->directory() );
+ new TagsItem( otherTagFiles, dlg->name(), dlg->tagsfilePath(), true );
+ }
+}
+
+void CTags2SettingsWidget::addNewTagFile()
+{
+ SelectTagFile* dlg = new SelectTagFile;
+
+ if ( dlg->exec() == QDialog::Accepted )
+ {
+ new TagsItem( otherTagFiles, dlg->name(), dlg->tagsfilePath(), true );
+ }
+}
+
+void CTags2SettingsWidget::removeTagFile()
+{
+ if (!otherTagFiles->selectedItem())
+ return;
+
+ delete otherTagFiles->selectedItem();
+}
+
+
+#include "ctags2_settingswidget.moc"
+
+// kate: space-indent off; indent-width 4; tab-width 4; show-tabs off;
diff --git a/parts/ctags2/ctags2_settingswidget.h b/parts/ctags2/ctags2_settingswidget.h
new file mode 100644
index 00000000..ac208ad4
--- /dev/null
+++ b/parts/ctags2/ctags2_settingswidget.h
@@ -0,0 +1,69 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Jens Dagerbo *
+ * jens.dagerbo@swipnet.se *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef CTAGS2_SETTINGSWIDGET_H
+#define CTAGS2_SETTINGSWIDGET_H
+
+#include <qlistview.h>
+
+#include "ctags2_settingswidgetbase.h"
+
+class CTags2Part;
+
+class TagsItem : public QCheckListItem
+{
+public:
+ TagsItem( QListView * parent, QString name, QString tagsfilePath, bool active )
+ : QCheckListItem( parent, name, QCheckListItem::CheckBox ), m_name( name ), m_tagsfilePath( tagsfilePath )
+ {
+ setOn( active );
+ setText( 1, tagsfilePath );
+ }
+ QString name() { return m_name; }
+ QString tagsfilePath() { return m_tagsfilePath; }
+
+private:
+ QString m_name;
+ QString m_tagsfilePath;
+};
+
+
+
+class CTags2SettingsWidget : public CTags2SettingsWidgetBase
+{
+ Q_OBJECT
+
+public:
+ CTags2SettingsWidget( CTags2Part * part, QWidget* parent = 0, const char* name = 0, WFlags fl = 0 );
+ ~CTags2SettingsWidget();
+
+signals:
+ void newTagsfileName( const QString & name );
+
+public slots:
+ void slotAccept();
+ void createNewTagSlot();
+ void addNewTagFile();
+ void removeTagFile();
+
+protected:
+
+protected slots:
+
+private:
+ void loadSettings();
+ void storeSettings();
+
+ CTags2Part * m_part;
+};
+
+#endif
+
diff --git a/parts/ctags2/ctags2_settingswidgetbase.ui b/parts/ctags2/ctags2_settingswidgetbase.ui
new file mode 100644
index 00000000..27898206
--- /dev/null
+++ b/parts/ctags2/ctags2_settingswidgetbase.ui
@@ -0,0 +1,382 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>CTags2SettingsWidgetBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>CTags2SettingsWidgetBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>460</width>
+ <height>456</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QTabWidget">
+ <property name="name">
+ <cstring>tabWidget8</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Ge&amp;neral</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Editor Context Menu</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>showDeclarationBox</cstring>
+ </property>
+ <property name="text">
+ <string>Show "&amp;Go To Declaration"</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If checked, an option to go directly to the matching tag declaration will be shown. If more than one match, all matches will be shown in the main ctags result view.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>showDefinitionBox</cstring>
+ </property>
+ <property name="text">
+ <string>Show "Go To &amp;Definition"</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If checked, an option to go directly to the matching tag definition will be shown. If more than one match, all matches will be shown in the main ctags result view.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>showLookupBox</cstring>
+ </property>
+ <property name="text">
+ <string>Show "CT&amp;ags Lookup"</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If checked, an option to do a full lookup of all macthing tags is shown in the context menu. The results will be shown in the main ctags results view.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox3_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Options</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>jumpToFirstBox</cstring>
+ </property>
+ <property name="text">
+ <string>When more than one hit, go directl&amp;y to the first</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If more than one hit was produced from an attempt to find an exact match, go to the first match in the list. Note: the &lt;i&gt;Go To Next Match&lt;/i&gt; shortcut can be used to step between the matches.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>tagfileCustomBox</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Use custom tagfile generation arguments</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The default arguments should be fine, but if needed a custom generation arguments string can be used.</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>tagfileCustomEdit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="readOnly">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter custom arguments to ctags database creation here. Note: do not set a custom tags file filename here, do that below instead.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox3</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Paths</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter the path to the exuberant ctags binary. If empty, &lt;i&gt;ctags&lt;/i&gt; will be executed via $PATH. Note that it is sometimes installed as &lt;i&gt;exuberant-ctags&lt;/i&gt;.</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Path to ctags binary:</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester">
+ <property name="name">
+ <cstring>binaryPath</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter the path to the exuberant ctags binary. If empty, &lt;i&gt;ctags&lt;/i&gt; will be executed via $PATH. Note that it is sometimes installed as &lt;i&gt;exuberant-ctags&lt;/i&gt;.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>31</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Mana&amp;ge tag files</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout15</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Path to project tag file:</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="1" column="0">
+ <property name="name">
+ <cstring>tagfilePath</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter the full path of the project tagfile. If empty, the file will be called &lt;i&gt;tags&lt;/i&gt; and reside in the root of the project.</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Other tag files:</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="2" column="1">
+ <property name="name">
+ <cstring>layout21</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton" row="0" column="0">
+ <property name="name">
+ <cstring>createButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Create...</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="0">
+ <property name="name">
+ <cstring>addButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Add...</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="2" column="0">
+ <property name="name">
+ <cstring>removeButton</cstring>
+ </property>
+ <property name="text">
+ <string>Remo&amp;ve</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer row="3" column="1">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>61</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KListView" row="2" column="0" rowspan="2" colspan="1">
+ <column>
+ <property name="text">
+ <string>Name</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Tags file</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>otherTagFiles</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>addButton</sender>
+ <signal>clicked()</signal>
+ <receiver>CTags2SettingsWidgetBase</receiver>
+ <slot>addNewTagFile()</slot>
+ </connection>
+ <connection>
+ <sender>removeButton</sender>
+ <signal>clicked()</signal>
+ <receiver>CTags2SettingsWidgetBase</receiver>
+ <slot>removeTagFile()</slot>
+ </connection>
+ <connection>
+ <sender>createButton</sender>
+ <signal>clicked()</signal>
+ <receiver>CTags2SettingsWidgetBase</receiver>
+ <slot>createNewTagSlot()</slot>
+ </connection>
+ <connection>
+ <sender>tagfileCustomBox</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>tagfileCustomEdit</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>tagfileCustomBox</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>tagfileCustomEdit</receiver>
+ <slot>clear()</slot>
+ </connection>
+</connections>
+<slots>
+ <slot>createNewTagSlot()</slot>
+ <slot>addNewTagFile()</slot>
+ <slot>removeTagFile()</slot>
+ <slot>moveUpTagFile()</slot>
+ <slot>moveDownTagFile()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klineedit.h</includehint>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klistview.h</includehint>
+</includehints>
+</UI>
diff --git a/parts/ctags2/ctags2_widget.cpp b/parts/ctags2/ctags2_widget.cpp
new file mode 100644
index 00000000..7196ed1b
--- /dev/null
+++ b/parts/ctags2/ctags2_widget.cpp
@@ -0,0 +1,199 @@
+/***************************************************************************
+ * Copyright (C) 2004 by Jens Dagerbo *
+ * jens.dagerbo@swipnet.se *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <qtimer.h>
+#include <qlabel.h>
+#include <qfileinfo.h>
+#include <qdatetime.h>
+#include <qfocusdata.h>
+
+#include <klineedit.h>
+#include <klistview.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kurl.h>
+#include <kapplication.h>
+
+#include <kdevproject.h>
+#include <kdevpartcontroller.h>
+
+#include "ctags2_widget.h"
+#include "tags.h"
+
+class TagItem : public QListViewItem
+{
+public:
+ TagItem(QListView * lv, QString const & tag, QString const & type, QString const & file, QString const & pattern );
+
+ QString tag;
+ QString type;
+ QString file;
+ QString pattern;
+};
+
+TagItem::TagItem( QListView * lv, QString const & tag, QString const & type, QString const & file, QString const & pattern )
+ : QListViewItem( lv, tag, type, file ), tag(tag), type(type), file(file), pattern(pattern)
+{
+}
+
+CTags2Widget::CTags2Widget( CTags2Part * part, const char* name, WFlags fl)
+: CTags2WidgetBase(0,name,fl), _part(part)
+{
+ output_view->setColumnWidthMode(0,QListView::Maximum);
+ output_view->setColumnWidthMode(1,QListView::Maximum);
+ output_view->setColumnWidthMode(2,QListView::Maximum);
+
+ _typeTimeout = new QTimer( this );
+ connect( _typeTimeout, SIGNAL(timeout()), this, SLOT(line_edit_changed()) );
+
+ connect( output_view, SIGNAL(executed(QListViewItem*)), this, SLOT(itemExecuted(QListViewItem*)) );
+ connect( output_view, SIGNAL(returnPressed(QListViewItem*)), this, SLOT(itemExecuted(QListViewItem*)) );
+
+ updateDBDateLabel();
+}
+
+CTags2Widget::~CTags2Widget()
+{
+}
+
+void CTags2Widget::displayHits( Tags::TagList const & list )
+{
+ output_view->clear();
+ showHitCount( list.count() );
+
+ Tags::TagList::ConstIterator it = list.begin();
+ while( it != list.end() )
+ {
+ new TagItem( output_view, (*it).tag, (*it).type, (*it).file, (*it).pattern );
+ ++it;
+ }
+
+ output_view->adjustColumn(0);
+ output_view->adjustColumn(1);
+ output_view->adjustColumn(2);
+
+}
+
+void CTags2Widget::displayHitsAndClear( Tags::TagList const & list )
+{
+ input_edit->blockSignals( true );
+ input_edit->clear();
+ input_edit->blockSignals( false );
+
+ displayHits( list );
+}
+
+void CTags2Widget::line_edit_changed( )
+{
+ displayHits( Tags::getPartialMatches( input_edit->text() ) );
+}
+
+void CTags2Widget::line_edit_changed_delayed( )
+{
+ showHitCount( calculateHitCount() );
+ _typeTimeout->start( 500, true );
+}
+
+void CTags2Widget::showHitCount( int n )
+{
+ hitcount_label->setText( i18n("Hits: %1").arg( n ) );
+}
+
+int CTags2Widget::calculateHitCount( )
+{
+ return Tags::numberOfPartialMatches( input_edit->text() ) ;
+}
+
+void CTags2Widget::itemExecuted( QListViewItem * item )
+{
+ TagItem * tagItem = static_cast<TagItem*>( item );
+
+ KURL url;
+ QString fileWithTagInside;
+ // assume relative path to project directory if path does not start with slash
+ if (tagItem->file[0] != '/') {
+ fileWithTagInside = _part->project()->projectDirectory() + "/" + tagItem->file;
+ }
+ else {
+ fileWithTagInside = tagItem->file;
+ }
+
+ url.setPath(fileWithTagInside);
+
+ _part->partController()->editDocument( url, _part->getFileLineFromPattern( url, tagItem->pattern ) );
+}
+
+void CTags2Widget::regeneratebutton_clicked()
+{
+ QApplication::setOverrideCursor(Qt::waitCursor);
+
+ _part->createTagsFile();
+
+ QApplication::restoreOverrideCursor();
+
+ updateDBDateLabel();
+}
+
+void CTags2Widget::updateDBDateLabel( )
+{
+ QStringList tagFiles = Tags::getTagFiles();
+ QFileInfo tagsdb(tagFiles[0]);
+ if ( tagsdb.exists() )
+ {
+ datetime_label->setText( tagsdb.created().date().toString( Qt::ISODate ) );
+ }
+ else
+ {
+ datetime_label->setText( i18n("No CTags database found") );
+ }
+}
+
+void CTags2Widget::focusInEvent( QFocusEvent* )
+{
+ updateDBDateLabel();
+ input_edit->setFocus();
+}
+
+void CTags2Widget::goToNext( )
+{
+ QListViewItem * item = output_view->firstChild();
+ while( item )
+ {
+ if ( item->isSelected() )
+ {
+ // found the current, take the next
+ item->setSelected( false );
+ if ( (item = item->nextSibling()) != NULL )
+ {
+ item->setSelected( true );
+ output_view->repaint( true );
+ itemExecuted( item );
+ return;
+ }
+ else
+ {
+ break;
+ }
+ }
+ item = item->nextSibling();
+ }
+ // use the first
+ if ( (item = output_view->firstChild()) != NULL )
+ {
+ item->setSelected( true );
+ itemExecuted( item );
+ }
+}
+
+#include "ctags2_widget.moc"
+
+// kate: space-indent off; indent-width 4; tab-width 4; show-tabs off;
+
diff --git a/parts/ctags2/ctags2_widget.h b/parts/ctags2/ctags2_widget.h
new file mode 100644
index 00000000..2a4423a4
--- /dev/null
+++ b/parts/ctags2/ctags2_widget.h
@@ -0,0 +1,56 @@
+/***************************************************************************
+ * Copyright (C) 2004 by Jens Dagerbo *
+ * jens.dagerbo@swipnet.se *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef CTAGS2_WIDGET_H
+#define CTAGS2_WIDGET_H
+
+#include "ctags2_widgetbase.h"
+#include "ctags2_part.h"
+#include "tags.h"
+
+class QTimer;
+class QListViewItem;
+
+class CTags2Widget : public CTags2WidgetBase
+{
+ Q_OBJECT
+
+public:
+ CTags2Widget( CTags2Part * part, const char* name = 0, WFlags fl = 0 );
+ ~CTags2Widget();
+
+ void displayHits( Tags::TagList const & );
+ void displayHitsAndClear( Tags::TagList const & );
+
+ void updateDBDateLabel();
+ void goToNext();
+
+protected:
+ void focusInEvent( QFocusEvent *e );
+
+private slots:
+ virtual void line_edit_changed();
+ virtual void line_edit_changed_delayed();
+ virtual void regeneratebutton_clicked();
+ void itemExecuted( QListViewItem * );
+
+private:
+ void showHitCount( int );
+ int calculateHitCount();
+
+ CTags2Part * _part;
+ QTimer * _typeTimeout;
+
+};
+
+#endif
+
+// kate: space-indent off; indent-width 4; tab-width 4; show-tabs off;
diff --git a/parts/ctags2/ctags2_widgetbase.ui b/parts/ctags2/ctags2_widgetbase.ui
new file mode 100644
index 00000000..ef564767
--- /dev/null
+++ b/parts/ctags2/ctags2_widgetbase.ui
@@ -0,0 +1,181 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>CTags2WidgetBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>CTags2WidgetBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>780</width>
+ <height>397</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string></string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>2</number>
+ </property>
+ <widget class="KListView">
+ <column>
+ <property name="text">
+ <string>Tag</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Type</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>File</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>output_view</cstring>
+ </property>
+ <property name="allColumnsShowFocus">
+ <bool>true</bool>
+ </property>
+ <property name="resizeMode">
+ <enum>AllColumns</enum>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Result view for a tag lookup. Click a line to go to the corresponding place in the code.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Lookup:</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>input_edit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Type the identifier you want to lookup. &lt;p&gt; The identifier will populate and display a reducing list as you type.</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>hitcount_label</cstring>
+ </property>
+ <property name="text">
+ <string>Hits:</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>80</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>datetime_label</cstring>
+ </property>
+ <property name="text">
+ <string>Date:</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>generate_button</cstring>
+ </property>
+ <property name="focusPolicy">
+ <enum>NoFocus</enum>
+ </property>
+ <property name="text">
+ <string>Regenerate</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Press to regenerate CTags database.&lt;p&gt;This will take some time on a large project.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>input_edit</sender>
+ <signal>returnPressed()</signal>
+ <receiver>CTags2WidgetBase</receiver>
+ <slot>line_edit_changed()</slot>
+ </connection>
+ <connection>
+ <sender>input_edit</sender>
+ <signal>textChanged(const QString&amp;)</signal>
+ <receiver>CTags2WidgetBase</receiver>
+ <slot>line_edit_changed_delayed()</slot>
+ </connection>
+ <connection>
+ <sender>generate_button</sender>
+ <signal>clicked()</signal>
+ <receiver>CTags2WidgetBase</receiver>
+ <slot>regeneratebutton_clicked()</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>input_edit</tabstop>
+ <tabstop>output_view</tabstop>
+</tabstops>
+<slots>
+ <slot access="private">line_edit_changed_delayed()</slot>
+ <slot access="private">line_edit_changed()</slot>
+ <slot access="private">regeneratebutton_clicked()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klistview.h</includehint>
+ <includehint>klineedit.h</includehint>
+</includehints>
+</UI>
diff --git a/parts/ctags2/ctagskinds.cpp b/parts/ctags2/ctagskinds.cpp
new file mode 100644
index 00000000..c8d5ef93
--- /dev/null
+++ b/parts/ctags2/ctagskinds.cpp
@@ -0,0 +1,306 @@
+/***************************************************************************
+ * Copyright (C) 2001-2002 by Bernd Gehrmann *
+ * bernd@kdevelop.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "ctagskinds.h"
+
+#include <klocale.h>
+
+struct CTagsKindMapping {
+ char abbrev;
+ const char *verbose;
+};
+
+
+struct CTagsExtensionMapping {
+ const char *extension;
+ CTagsKindMapping *kinds;
+};
+
+
+static CTagsKindMapping kindMappingAsm[] = {
+ { 'd', I18N_NOOP("define") },
+ { 'l', I18N_NOOP("label") },
+ { 'm', I18N_NOOP("macro") },
+ { 0 , 0 }
+};
+
+
+static CTagsKindMapping kindMappingAsp[] = {
+ { 'f', I18N_NOOP("function") },
+ { 's', I18N_NOOP("subroutine") },
+ { 0 , 0 }
+};
+
+
+static CTagsKindMapping kindMappingAwk[] = {
+ { 'f', I18N_NOOP("function") },
+ { 0 , 0 }
+};
+
+
+static CTagsKindMapping kindMappingBeta[] = {
+ { 'f', I18N_NOOP("fragment definition") },
+ { 'p', I18N_NOOP("any pattern") },
+ { 's', I18N_NOOP("slot") },
+ { 'v', I18N_NOOP("pattern") },
+ { 0 , 0 }
+};
+
+
+static CTagsKindMapping kindMappingC[] = {
+ { 'c', I18N_NOOP("class") },
+ { 'd', I18N_NOOP("macro") },
+ { 'e', I18N_NOOP("enumerator") },
+ { 'f', I18N_NOOP("function") },
+ { 'g', I18N_NOOP("enumeration") },
+ { 'l', I18N_NOOP("local variable") },
+ { 'm', I18N_NOOP("member") },
+ { 'n', I18N_NOOP("namespace") },
+ { 'p', I18N_NOOP("prototype") },
+ { 's', I18N_NOOP("struct") },
+ { 't', I18N_NOOP("typedef") },
+ { 'u', I18N_NOOP("union") },
+ { 'v', I18N_NOOP("variable") },
+ { 'x', I18N_NOOP("external variable") },
+ { 0 , 0 }
+};
+
+
+static CTagsKindMapping kindMappingCobol[] = {
+ { 'p', I18N_NOOP("paragraph") },
+ { 0 , 0 }
+};
+
+
+static CTagsKindMapping kindMappingEiffel[] = {
+ { 'c', I18N_NOOP("class") },
+ { 'f', I18N_NOOP("feature") },
+ { 'l', I18N_NOOP("local entity") },
+ { 0 , 0 }
+};
+
+
+static CTagsKindMapping kindMappingFortran[] = {
+ { 'b', I18N_NOOP("block") },
+ { 'c', I18N_NOOP("common") },
+ { 'e', I18N_NOOP("entry") },
+ { 'f', I18N_NOOP("function") },
+ { 'i', I18N_NOOP("interface") },
+ { 'k', I18N_NOOP("type component") },
+ { 'l', I18N_NOOP("label") },
+ { 'L', I18N_NOOP("local") },
+ { 'm', I18N_NOOP("module") },
+ { 'n', I18N_NOOP("namelist") },
+ { 'p', I18N_NOOP("program") },
+ { 's', I18N_NOOP("subroutine") },
+ { 't', I18N_NOOP("type") },
+ { 'v', I18N_NOOP("variable") },
+ { 0 , 0 }
+};
+
+
+static CTagsKindMapping kindMappingJava[] = {
+ { 'c', I18N_NOOP("class") },
+ { 'f', I18N_NOOP("field") },
+ { 'i', I18N_NOOP("interface") },
+ { 'm', I18N_NOOP("method") },
+ { 'p', I18N_NOOP("package") },
+ { 0 , 0 }
+};
+
+
+static CTagsKindMapping kindMappingLisp[] = {
+ { 'f', I18N_NOOP("function") },
+ { 0 , 0 }
+};
+
+
+static CTagsKindMapping kindMappingMake[] = {
+ { 'm', I18N_NOOP("macro") },
+ { 0 , 0 }
+};
+
+
+static CTagsKindMapping kindMappingPascal[] = {
+ { 'f', I18N_NOOP("function") },
+ { 'p', I18N_NOOP("procedure") },
+ { 0 , 0 }
+};
+
+
+static CTagsKindMapping kindMappingPerl[] = {
+ { 's', I18N_NOOP("subroutine") },
+ { 0 , 0 }
+};
+
+
+static CTagsKindMapping kindMappingPHP[] = {
+ { 'c', I18N_NOOP("class") },
+ { 'f', I18N_NOOP("function") },
+ { 0 , 0 }
+};
+
+
+static CTagsKindMapping kindMappingPython[] = {
+ { 'c', I18N_NOOP("class") },
+ { 'f', I18N_NOOP("function") },
+ { 0 , 0 }
+};
+
+
+static CTagsKindMapping kindMappingRexx[] = {
+ { 's', I18N_NOOP("subroutine") },
+ { 0 , 0 }
+};
+
+
+static CTagsKindMapping kindMappingRuby[] = {
+ { 'c', I18N_NOOP("class") },
+ { 'f', I18N_NOOP("function") },
+ { 'm', I18N_NOOP("mixin") },
+ { 0 , 0 }
+};
+
+
+static CTagsKindMapping kindMappingScheme[] = {
+ { 'f', I18N_NOOP("function") },
+ { 's', I18N_NOOP("set") },
+ { 0 , 0 }
+};
+
+
+static CTagsKindMapping kindMappingSh[] = {
+ { 'f', I18N_NOOP("function") },
+ { 0 , 0 }
+};
+
+
+static CTagsKindMapping kindMappingSlang[] = {
+ { 'f', I18N_NOOP("function") },
+ { 'n', I18N_NOOP("namespace") },
+ { 0 , 0 }
+};
+
+
+static CTagsKindMapping kindMappingTcl[] = {
+ { 'p', I18N_NOOP("procedure") },
+ { 0 , 0 }
+};
+
+
+static CTagsKindMapping kindMappingVim[] = {
+ { 'f', I18N_NOOP("function") },
+ { 0 , 0 }
+};
+
+
+static CTagsExtensionMapping extensionMapping[] = {
+ { "asm", kindMappingAsm },
+ { "s", kindMappingAsm },
+ { "S", kindMappingAsm },
+ { "asp", kindMappingAsp },
+ { "asa", kindMappingAsp },
+ { "awk", kindMappingAwk },
+ { "c++", kindMappingC },
+ { "cc", kindMappingC },
+ { "cp" , kindMappingC },
+ { "cpp", kindMappingC },
+ { "cxx", kindMappingC },
+ { "h" , kindMappingC },
+ { "h++", kindMappingC },
+ { "hh" , kindMappingC },
+ { "hp" , kindMappingC },
+ { "hpp", kindMappingC },
+ { "hxx", kindMappingC },
+ { "beta", kindMappingBeta },
+ { "cob", kindMappingCobol },
+ { "COB", kindMappingCobol },
+ { "e", kindMappingEiffel },
+ { "f" , kindMappingFortran },
+ { "for" , kindMappingFortran },
+ { "ftn" , kindMappingFortran },
+ { "f77" , kindMappingFortran },
+ { "f90" , kindMappingFortran },
+ { "f95" , kindMappingFortran },
+ { "java", kindMappingJava },
+ { "cl", kindMappingLisp },
+ { "clisp", kindMappingLisp },
+ { "el", kindMappingLisp },
+ { "l", kindMappingLisp },
+ { "lisp", kindMappingLisp },
+ { "lsp", kindMappingLisp },
+ { "ml", kindMappingLisp },
+ { "mak", kindMappingMake },
+ { "p", kindMappingPascal },
+ { "pas", kindMappingPascal },
+ { "pl", kindMappingPerl },
+ { "pm", kindMappingPerl },
+ { "perl", kindMappingPerl },
+ { "php", kindMappingPHP },
+ { "php3", kindMappingPHP },
+ { "phtml", kindMappingPHP },
+ { "py", kindMappingPython },
+ { "python", kindMappingPython },
+ { "cmd", kindMappingRexx },
+ { "rexx", kindMappingRexx },
+ { "rx", kindMappingRexx },
+ { "rb", kindMappingRuby },
+ { "sch", kindMappingScheme },
+ { "scheme", kindMappingScheme },
+ { "scm", kindMappingScheme },
+ { "sm", kindMappingScheme },
+ { "SCM", kindMappingScheme },
+ { "SM", kindMappingScheme },
+ { "sh", kindMappingSh },
+ { "SH", kindMappingSh },
+ { "bsh", kindMappingSh },
+ { "bash", kindMappingSh },
+ { "ksh", kindMappingSh },
+ { "zsh", kindMappingSh },
+ { "sl", kindMappingSlang },
+ { "tcl", kindMappingTcl },
+ { "wish", kindMappingTcl },
+ { "vim", kindMappingVim },
+ { 0 , 0 }
+};
+
+
+static CTagsKindMapping *findKindMapping(const QString &extension)
+{
+ const char *pextension = extension.latin1();
+
+ CTagsExtensionMapping *pem = extensionMapping;
+ while (pem->extension != 0) {
+ if (strcmp(pem->extension, pextension) == 0)
+ return pem->kinds;
+ ++pem;
+ }
+
+ return 0;
+}
+
+
+QString CTagsKinds::findKind( const char * kindChar, const QString &extension )
+{
+ if ( kindChar == 0 ) return QString::null;
+
+ CTagsKindMapping *kindMapping = findKindMapping(extension);
+ if (kindMapping) {
+ CTagsKindMapping *pkm = kindMapping;
+ while (pkm->verbose != 0) {
+ if (pkm->abbrev == *kindChar)
+ return i18n(pkm->verbose);
+ ++pkm;
+ }
+ }
+
+ return QString::null;
+}
diff --git a/parts/ctags2/ctagskinds.h b/parts/ctags2/ctagskinds.h
new file mode 100644
index 00000000..de695319
--- /dev/null
+++ b/parts/ctags2/ctagskinds.h
@@ -0,0 +1,24 @@
+/***************************************************************************
+ * Copyright (C) 2001-2002 by Bernd Gehrmann *
+ * bernd@kdevelop.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef _CTAGSKINDS_H_
+#define _CTAGSKINDS_H_
+
+#include <qstring.h>
+
+
+class CTagsKinds
+{
+public:
+ static QString findKind( const char * kindChar, const QString &extension);
+};
+
+#endif
diff --git a/parts/ctags2/kdevctags2.desktop b/parts/ctags2/kdevctags2.desktop
new file mode 100644
index 00000000..a63d45de
--- /dev/null
+++ b/parts/ctags2/kdevctags2.desktop
@@ -0,0 +1,82 @@
+[Desktop Entry]
+Type=Service
+Exec=blubb
+Icon=kdevelop
+Comment=CTags is a source navigation tool with support for many languages. When loaded it provides a context menu for finding type declarations/definitions and also a query dialog. http://ctags.sourceforge.net/
+Comment[ca]=CTags és una eina de navegació de codi font amb suport per a diversos llenguatges. En carregar-se proporciona un menú de context per a localitzar les declaracions/definicions de tipus i també un diàleg de consultes. http://ctags.sourceforge.net/
+Comment[da]=CTags er et kildenavigationsværktøj med støtte for mange sprog. Når det er indlæst sørger det for en sammenhængsmenu til at finde type-deklarationer/definitioner og også en forespørgselsdialog. http://ctags.sourceforge.net/
+Comment[de]=CTags ist ein Navigationswerkzeug, das viele Sprachen unterstützt. Ist es geladen, bietet es ein Kontextmenü zum Suchen von Typ-Deklarationen und -Definitionen und einen Abfragedialog im Menü "Werkzeuge". http://ctags.sourceforge.net/
+Comment[el]=Το CTags είναι ένα εργαλείο πλοήγησης κώδικα με υποστήριξη πολλών γλωσσών. Όταν φορτωθεί προσφέρει ένα σχετικό μενού εύρεσης δηλώσεων/ορισμών τύπων και ένα διάλογο αναζήτησης. http://ctags.sourceforge.net/
+Comment[en_GB]=CTags is a source navigation tool with support for many languages. When loaded it provides a context menu for finding type declarations/definitions and also a query dialogue. http://ctags.sourceforge.net/
+Comment[es]=CTags es una herramienta de navegación del código fuente con soporte para varios lenguajes. Al cargarse, proporciona un menú contextual para localizar las declaraciones/definiciones de tipos y también un diálogo de consultas. http://ctags.sourceforge.net/
+Comment[et]=CTags on liikumisvahend paljude keelte toega. Laadimisel pakub see kontekstimenüüd deklaratsioonide/definitsioonide tüübi leidmiseks, samuti päringudialoogi tööriistade menüü vahendusel. Vaata internetis http://ctags.sourceforge.net/
+Comment[eu]=CTags hizkuntza askotako euskarria duen iturburu nabigazio tresna bat da. Kargatzean mota deklarazio/definizioak aurkitzeko testuinguru menu bat eskeintzen du eta baita kontsulta elkarrizketa-koadro bat ere Tresnak menuan.http://ctags.sourceforge.net/
+Comment[fa]=CTags یک ابزار ناوش منبع با پشتیبانی از زبانهای زیادی است. در هنگام بارگذاری، یک گزینگان متن برای یافتن تعاریف/اعلانهای نوع و همچنین یک محاورۀ پرس‌وجو فراهم می‌کند. http://ctags.sourceforge.net/
+Comment[fr]=CTags est un outil de navigation dans les sources comprenant une prise en charge pour de nombreux langages. Une fois chargé, il fournit un menu contextuel pour la recherche de déclarations / définitions de types, ainsi qu'une boîte de dialogue de requête. http://ctags.sourceforge.net/
+Comment[gl]=CTags é unha ferramenta para a navegación de código con soporte para moitas linguaxes. Cando se carga proporciona un menú contextual para atopar declaracións/definicións de tipos e tamén un diálogo de peticións. http://ctags.sourceforge.net/
+Comment[hu]=A CTags egy többféle nyelvet is támogató forrásnavigációs eszköz. Lehetővé teszi felbukkanó menüből típusdeklarációk és -megvalósítások keresését, lekérdezését. http://ctags.sourceforge.net/
+Comment[it]=CTags è uno strumento per la navigazione nel codice sorgente con supporto per molti linguaggi. Quando caricato offre un menu contestuale per ricercare i tipi di dichiarazioni/definizioni e anche una finestra per compiere interrogazioni. http://ctags.sourceforge.net/
+Comment[ja]=CTags は色々な言語をサポートしたソースナビゲーションツールです。読み込まれると、型の宣言や定義を見つけたり、ツールメニューの中で対話的な問い合わせを行うコンテキストメニューを提供します。http://ctags.sourceforge.net/
+Comment[ms]=CTags adalah alatan pengemudi sumber dengan sokongan untuk banyak bahasa. Apabila dimuatkan ia menyediakan menu konteks untuk mencari pengisytiharan/definisi dan juga dialog pertanyaan. http://ctags.sourceforge.net/
+Comment[nds]=CTags is en Navigatschoonwarktüüch, wat vele Spraken ünnerstütt. Wenn dat laadt is, stellt dat en Rechtsklickmenü för't Söken na Typ-Deklaratschonen un -Definitschonen praat, un ok noch en Affraagdialoog. http://ctags.sourceforge.net/
+Comment[ne]=CTags स्रोत नेभिगेसन उपकरण हो जसले धेरै भाषा समर्थन गर्दछ । लोड गरेपछि यसले टाइप घोषणा/परिभाषा र क्वेरी संवाद पनि फेला पार्नका लागि प्रसङ्ग मेनु प्रदान गर्दछ । http://ctags.sourceforge.net/
+Comment[nl]=CTags is een krachtige tool voor het navigeren in broncode met ondersteuning voor veel talen. Wanneer de plugin geladen is biedt deze een contextmenu voor het vinden van typedeclaraties, en ook een ondervragingsdialoog. Web: http://ctags.sourceforge.net/
+Comment[pl]=CTags to narzędzie do nawigacji w kodzie źródłowym obsługujące wiele języków. Po wczytaniu udostępnia menu kontekstowe pozwalające znajdować deklaracje/definicje oraz okno dialogowe w menu Narzędzia. http://ctags.sourceforge.net/
+Comment[pt]=O CTags é uma ferramenta de navegação no código com suporte para várias linguagens. Quando é carregado, oferece um menu de contexto para encontrar as declarações/definições de tipos, assim como uma janela de pesquisa. http://ctags.sourceforge.net/
+Comment[pt_BR]=CTags é uma ferramenta de navegação de código com suporte para muitas linguagens. Quando carregada ela oferece um menu de contexto para encontrar declarações/definições de tipo e também um diálogo de consulta no menu Ferramentas. http://ctags.sourceforge.net/
+Comment[ru]=CTags - это средство навигации по коду, поддерживающее многие языки. Будучи загружено, оно предоставляет контекстное меню для нахождения описания и определения типа выбранного символа, а также диалог запроса. http://ctags.sourceforge.net/
+Comment[sk]=CTags je navigačný nástroj pre zdrojový kód pre veľa jazykov.Po načítaní poskytuje kontextové menu pre hľadanie deklarácie/definície a tiež vyhľadávací dialóg. http://ctags.sourceforge.net/
+Comment[sr]=CTags је алат за навигацију кроз изворни кôд са подршком за многе језике. Када је учитан, обезбеђује контекстни мени за проналажење декларација/дефиниција типова, а такође и дијалог за упите. http://ctags.sourceforge.net/
+Comment[sr@Latn]=CTags je alat za navigaciju kroz izvorni kôd sa podrškom za mnoge jezike. Kada je učitan, obezbeđuje kontekstni meni za pronalaženje deklaracija/definicija tipova, a takođe i dijalog za upite. http://ctags.sourceforge.net/
+Comment[sv]=Ctags är ett verktyg för källkodsnavigering med stöd för många språk. När det laddats tillhandahåller det en sammanhangsberoende meny för att hitta typdeklarationer eller definitioner, och dessutom en frågedialogruta. http://ctags.sourceforge.net/
+Comment[ta]=Cதத்தல்கள் இது ஒரு மூல வழி செலுத்தும் கருவி இது நிறைய மொழிகளை ஆதரிக்கும். ஏற்றும் பொழுது எழுத்து உருவை காண உதவும் ஒரு பட்டியலும் மற்றும் கருவிப்பட்டியலில் கேள்வி உரையாடல்களும் இது அளிக்கும்.http://ctags.sourceforge.net/
+Comment[tg]=CTags-ин воситаи навигадсия дар код мебошад, ки бисёр забонҳоро дастрасӣ менамояд. Ҳангоми пурбор намудан, вай менюи қаринагинро пешниҳод менамояд, барои ёфтани тасвир ва муаян сохтани намуди нишонаҳои интихоб карда шуда ва боз гуфтугӯи дархостро мегузорад. http://ctags.sourceforge.net/
+Comment[tr]=CTags birçok dili destekleyen bir kaynak dolaşım aracıdır. Yüklendiğinde tip tanımlamalarını bulmayı sağlayan bir bağlam menüsü ve bir sorgu penceresi sunar.
+Comment[zh_CN]=CTags 是一个支持多种语言源文件浏览的工具。启动后在上下文菜单中提供查找类型的声明/定义,并在工具菜单中提供查询对话框。http://ctags.sourceforge.net/
+Comment[zh_TW]=CTags 是支援許多種語言的程式源碼導覽工具。它載入後會提供一個選單,尋找型態的宣告、定義,並提供一個查詢對話框。http://ctags.sourceforge.net/
+Name=KDevCTags2
+Name[da]=KDevelop CTags2
+Name[nds]=KDevelop-CTags2
+Name[sk]=KDev CTags2
+Name[sv]=KDevelop ctags-2
+Name[tg]=KDevCТегҳо2
+Name[zh_TW]=KDevelop CTags2
+GenericName=CTags Frontend
+GenericName[ca]=Entorn per a CTags
+GenericName[da]=CTags-grænseflade
+GenericName[de]=Unterstützung für CTags
+GenericName[el]=Πρόγραμμα CTags
+GenericName[es]=Entorno de CTags
+GenericName[et]=CTagsi kasutajaliides
+GenericName[eu]=CTags interfazea
+GenericName[fa]=پایانۀ CTags
+GenericName[fr]=Interface pour CTags
+GenericName[ga]=Comhéadan CTags
+GenericName[gl]=Frontal para CTags
+GenericName[hi]=सी-टैग्स-फ्रन्टएन्ड
+GenericName[hu]=CTags-kezelő
+GenericName[it]=Interfaccia a CTags
+GenericName[ja]=CTags フロントエンド
+GenericName[ms]=Antaradepan CTags
+GenericName[nds]=CTags-Böversiet
+GenericName[ne]=CTags फ्रेन्टइन्ड
+GenericName[nl]=Frontend voor CTags
+GenericName[pl]=Interfejs do CTags
+GenericName[pt]=Interface de CTags
+GenericName[pt_BR]=Interface do CTags
+GenericName[ru]=Интерфейс к CTags
+GenericName[sk]=CTags rozhranie
+GenericName[sl]=Vmesnik za CTags
+GenericName[sr]=Интерфејс CTags-а
+GenericName[sr@Latn]=Interfejs CTags-a
+GenericName[sv]=Ctags-gränssnitt
+GenericName[ta]=CTags முன்பகுதி
+GenericName[tg]=Интерфейс дар CTags
+GenericName[tr]=CTags Önucu
+GenericName[zh_CN]=CTags前端
+GenericName[zh_TW]=CTags 前端介面
+ServiceTypes=KDevelop/Plugin
+X-KDevelop-Scope=Project
+X-KDE-Library=libkdevctags2
+X-KDevelop-Version=5
+X-KDevelop-Properties=CodeNavigation
diff --git a/parts/ctags2/kdevpart_ctags2.rc b/parts/ctags2/kdevpart_ctags2.rc
new file mode 100644
index 00000000..e8745b3b
--- /dev/null
+++ b/parts/ctags2/kdevpart_ctags2.rc
@@ -0,0 +1,12 @@
+<!DOCTYPE kpartgui>
+<kpartplugin name="ctags" library="libkdevctags2" version="3">
+ <MenuBar>
+ </MenuBar>
+ <Menu name="hidden">
+ <Action name="ctags_lookup_shortcut"/>
+ <Action name="ctags_declaration_shortcut"/>
+ <Action name="ctags_definition_shortcut"/>
+ <Action name="ctags_jump_to_next"/>
+ <Action name="ctags_input_shortcut"/>
+ </Menu>
+</kpartplugin>
diff --git a/parts/ctags2/readtags.c b/parts/ctags2/readtags.c
new file mode 100644
index 00000000..38014d3f
--- /dev/null
+++ b/parts/ctags2/readtags.c
@@ -0,0 +1,960 @@
+/*
+*
+* Copyright (c) 1996-2003, Darren Hiebert
+*
+* This source code is released into the public domain.
+*
+* This module contains functions for reading tag files.
+*/
+
+/*
+* INCLUDE FILES
+*/
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h> /* to declare off_t */
+
+#include "readtags.h"
+
+/*
+* MACROS
+*/
+#define TAB '\t'
+
+
+/*
+* DATA DECLARATIONS
+*/
+typedef struct {
+ size_t size;
+ char *buffer;
+} vstring;
+
+/* Information about current tag file */
+struct sTagFile {
+ /* has the file been opened and this structure initialized? */
+ short initialized;
+ /* format of tag file */
+ short format;
+ /* how is the tag file sorted? */
+ sortType sortMethod;
+ /* pointer to file structure */
+ FILE* fp;
+ /* file position of first character of `line' */
+ off_t pos;
+ /* size of tag file in seekable positions */
+ off_t size;
+ /* last line read */
+ vstring line;
+ /* name of tag in last line read */
+ vstring name;
+ /* defines tag search state */
+ struct {
+ /* file position of last match for tag */
+ off_t pos;
+ /* name of tag last searched for */
+ const char *name;
+ /* length of name for partial matches */
+ size_t nameLength;
+ /* peforming partial match */
+ short partial;
+ /* ignoring case */
+ short ignorecase;
+ } search;
+ /* miscellaneous extension fields */
+ struct {
+ /* number of entries in `list' */
+ unsigned short max;
+ /* list of key value pairs */
+ tagExtensionField *list;
+ } fields;
+ /* buffers to be freed at close */
+ struct {
+ /* name of program author */
+ char *author;
+ /* name of program */
+ char *name;
+ /* URL of distribution */
+ char *url;
+ /* program version */
+ char *version;
+ } program;
+};
+
+/*
+* DATA DEFINITIONS
+*/
+const char *const EmptyString = "";
+const char *const PseudoTagPrefix = "!_";
+
+/*
+* FUNCTION DEFINITIONS
+*/
+
+/*
+ * Compare two strings, ignoring case.
+ * Return 0 for match, < 0 for smaller, > 0 for bigger
+ * Make sure case is folded to uppercase in comparison (like for 'sort -f')
+ * This makes a difference when one of the chars lies between upper and lower
+ * ie. one of the chars [ \ ] ^ _ ` for ascii. (The '_' in particular !)
+ */
+static int struppercmp (const char *s1, const char *s2)
+{
+ int result;
+ do
+ {
+ result = toupper ((int) *s1) - toupper ((int) *s2);
+ } while (result == 0 && *s1++ != '\0' && *s2++ != '\0');
+ return result;
+}
+
+static int strnuppercmp (const char *s1, const char *s2, size_t n)
+{
+ int result;
+ do
+ {
+ result = toupper ((int) *s1) - toupper ((int) *s2);
+ } while (result == 0 && --n > 0 && *s1++ != '\0' && *s2++ != '\0');
+ return result;
+}
+
+static int growString (vstring *s)
+{
+ int result = 0;
+ size_t newLength;
+ char *newLine;
+ if (s->size == 0)
+ {
+ newLength = 128;
+ newLine = (char*) malloc (newLength);
+ *newLine = '\0';
+ }
+ else
+ {
+ newLength = 2 * s->size;
+ newLine = (char*) realloc (s->buffer, newLength);
+ }
+ if (newLine == NULL)
+ perror ("string too large");
+ else
+ {
+ s->buffer = newLine;
+ s->size = newLength;
+ result = 1;
+ }
+ return result;
+}
+
+/* Copy name of tag out of tag line */
+static void copyName (tagFile *const file)
+{
+ size_t length;
+ const char *end = strchr (file->line.buffer, '\t');
+ if (end == NULL)
+ {
+ end = strchr (file->line.buffer, '\n');
+ if (end == NULL)
+ end = strchr (file->line.buffer, '\r');
+ }
+ if (end != NULL)
+ length = end - file->line.buffer;
+ else
+ length = strlen (file->line.buffer);
+ while (length >= file->name.size)
+ growString (&file->name);
+ strncpy (file->name.buffer, file->line.buffer, length);
+ file->name.buffer [length] = '\0';
+}
+
+static int readTagLineRaw (tagFile *const file)
+{
+ int result = 1;
+ int reReadLine;
+
+ /* If reading the line places any character other than a null or a
+ * newline at the last character position in the buffer (one less than
+ * the buffer size), then we must resize the buffer and reattempt to read
+ * the line.
+ */
+ do
+ {
+ char *const pLastChar = file->line.buffer + file->line.size - 2;
+ char *line;
+
+ file->pos = ftell (file->fp);
+ reReadLine = 0;
+ *pLastChar = '\0';
+ line = fgets (file->line.buffer, (int) file->line.size, file->fp);
+ if (line == NULL)
+ {
+ /* read error */
+ if (! feof (file->fp))
+ perror ("readTagLine");
+ result = 0;
+ }
+ else if (*pLastChar != '\0' &&
+ *pLastChar != '\n' && *pLastChar != '\r')
+ {
+ /* buffer overflow */
+ growString (&file->line);
+ fseek (file->fp, file->pos, SEEK_SET);
+ reReadLine = 1;
+ }
+ else
+ {
+ size_t i = strlen (file->line.buffer);
+ while (i > 0 &&
+ (file->line.buffer [i - 1] == '\n' || file->line.buffer [i - 1] == '\r'))
+ {
+ file->line.buffer [i - 1] = '\0';
+ --i;
+ }
+ }
+ } while (reReadLine && result);
+ if (result)
+ copyName (file);
+ return result;
+}
+
+static int readTagLine (tagFile *const file)
+{
+ int result;
+ do
+ {
+ result = readTagLineRaw (file);
+ } while (result && *file->name.buffer == '\0');
+ return result;
+}
+
+static tagResult growFields (tagFile *const file)
+{
+ tagResult result = TagFailure;
+ unsigned short newCount = 2 * file->fields.max;
+ tagExtensionField *newFields = (tagExtensionField*)
+ realloc (file->fields.list, newCount * sizeof (tagExtensionField));
+ if (newFields == NULL)
+ perror ("too many extension fields");
+ else
+ {
+ file->fields.list = newFields;
+ file->fields.max = newCount;
+ result = TagSuccess;
+ }
+ return result;
+}
+
+static void parseExtensionFields (tagFile *const file, tagEntry *const entry,
+ char *const string)
+{
+ char *p = string;
+ while (p != NULL && *p != '\0')
+ {
+ while (*p == TAB)
+ *p++ = '\0';
+ if (*p != '\0')
+ {
+ char *colon;
+ char *field = p;
+ p = strchr (p, TAB);
+ if (p != NULL)
+ *p++ = '\0';
+ colon = strchr (field, ':');
+ if (colon == NULL)
+ entry->kind = field;
+ else
+ {
+ const char *key = field;
+ const char *value = colon + 1;
+ *colon = '\0';
+ if (strcmp (key, "kind") == 0)
+ entry->kind = value;
+ else if (strcmp (key, "file") == 0)
+ entry->fileScope = 1;
+ else if (strcmp (key, "line") == 0)
+ entry->address.lineNumber = atol (value);
+ else
+ {
+ if (entry->fields.count == file->fields.max)
+ growFields (file);
+ file->fields.list [entry->fields.count].key = key;
+ file->fields.list [entry->fields.count].value = value;
+ ++entry->fields.count;
+ }
+ }
+ }
+ }
+}
+
+static void parseTagLine (tagFile *file, tagEntry *const entry)
+{
+ int i;
+ char *p = file->line.buffer;
+ char *tab = strchr (p, TAB);
+ int fieldsPresent = 0;
+
+ entry->fields.list = NULL;
+ entry->fields.count = 0;
+ entry->kind = NULL;
+ entry->fileScope = 0;
+
+ entry->name = p;
+ if (tab != NULL)
+ {
+ *tab = '\0';
+ p = tab + 1;
+ entry->file = p;
+ tab = strchr (p, TAB);
+ if (tab != NULL)
+ {
+ *tab = '\0';
+ p = tab + 1;
+ if (*p == '/' || *p == '?')
+ {
+ /* parse pattern */
+ int delimiter = *(unsigned char*) p;
+ entry->address.lineNumber = 0;
+ entry->address.pattern = p;
+ do
+ {
+ p = strchr (p + 1, delimiter);
+ } while (p != NULL && *(p - 1) == '\\');
+ if (p == NULL)
+ {
+ /* invalid pattern */
+ }
+ else
+ ++p;
+ }
+ else if (isdigit ((int) *(unsigned char*) p))
+ {
+ /* parse line number */
+ entry->address.pattern = p;
+ entry->address.lineNumber = atol (p);
+ while (isdigit ((int) *(unsigned char*) p))
+ ++p;
+ }
+ else
+ {
+ /* invalid pattern */
+ }
+ if ( p != NULL )
+ {
+ fieldsPresent = (strncmp (p, ";\"", 2) == 0);
+ *p = '\0';
+ if (fieldsPresent)
+ parseExtensionFields (file, entry, p + 2);
+ }
+ }
+ }
+ if (entry->fields.count > 0)
+ entry->fields.list = file->fields.list;
+ for (i = entry->fields.count ; i < file->fields.max ; ++i)
+ {
+ file->fields.list [i].key = NULL;
+ file->fields.list [i].value = NULL;
+ }
+}
+
+static char *duplicate (const char *str)
+{
+ char *result = NULL;
+ if (str != NULL)
+ {
+ result = (char*) malloc (strlen (str) + 1);
+ if (result == NULL)
+ perror (NULL);
+ else
+ strcpy (result, str);
+ }
+ return result;
+}
+
+static void readPseudoTags (tagFile *const file, tagFileInfo *const info)
+{
+ fpos_t startOfLine;
+ const size_t prefixLength = strlen (PseudoTagPrefix);
+ if (info != NULL)
+ {
+ info->file.format = 1;
+ info->file.sort = TAG_UNSORTED;
+ info->program.author = NULL;
+ info->program.name = NULL;
+ info->program.url = NULL;
+ info->program.version = NULL;
+ }
+ while (1)
+ {
+ fgetpos (file->fp, &startOfLine);
+ if (! readTagLine (file))
+ break;
+ if (strncmp (file->line.buffer, PseudoTagPrefix, prefixLength) != 0)
+ break;
+ else
+ {
+ tagEntry entry;
+ const char *key, *value;
+ parseTagLine (file, &entry);
+ key = entry.name + prefixLength;
+ value = entry.file;
+ if (strcmp (key, "TAG_FILE_SORTED") == 0)
+ file->sortMethod = (sortType) atoi (value);
+ else if (strcmp (key, "TAG_FILE_FORMAT") == 0)
+ file->format = atoi (value);
+ else if (strcmp (key, "TAG_PROGRAM_AUTHOR") == 0)
+ file->program.author = duplicate (value);
+ else if (strcmp (key, "TAG_PROGRAM_NAME") == 0)
+ file->program.name = duplicate (value);
+ else if (strcmp (key, "TAG_PROGRAM_URL") == 0)
+ file->program.url = duplicate (value);
+ else if (strcmp (key, "TAG_PROGRAM_VERSION") == 0)
+ file->program.version = duplicate (value);
+ if (info != NULL)
+ {
+ info->file.format = file->format;
+ info->file.sort = file->sortMethod;
+ info->program.author = file->program.author;
+ info->program.name = file->program.name;
+ info->program.url = file->program.url;
+ info->program.version = file->program.version;
+ }
+ }
+ }
+ fsetpos (file->fp, &startOfLine);
+}
+
+static void gotoFirstLogicalTag (tagFile *const file)
+{
+ fpos_t startOfLine;
+ const size_t prefixLength = strlen (PseudoTagPrefix);
+ rewind (file->fp);
+ while (1)
+ {
+ fgetpos (file->fp, &startOfLine);
+ if (! readTagLine (file))
+ break;
+ if (strncmp (file->line.buffer, PseudoTagPrefix, prefixLength) != 0)
+ break;
+ }
+ fsetpos (file->fp, &startOfLine);
+}
+
+static tagFile *initialize (const char *const filePath, tagFileInfo *const info)
+{
+ tagFile *result = (tagFile*) malloc (sizeof (tagFile));
+ if (result != NULL)
+ {
+ memset (result, 0, sizeof (tagFile));
+ growString (&result->line);
+ growString (&result->name);
+ result->fields.max = 20;
+ result->fields.list = (tagExtensionField*) malloc (
+ result->fields.max * sizeof (tagExtensionField));
+ result->fp = fopen (filePath, "r");
+ if (result->fp == NULL)
+ {
+ free (result);
+ result = NULL;
+ info->status.error_number = errno;
+ }
+ else
+ {
+ fseek (result->fp, 0, SEEK_END);
+ result->size = ftell (result->fp);
+ rewind (result->fp);
+ readPseudoTags (result, info);
+ info->status.opened = 1;
+ result->initialized = 1;
+ }
+ }
+ return result;
+}
+
+static void terminate (tagFile *const file)
+{
+ fclose (file->fp);
+
+ free (file->line.buffer);
+ free (file->name.buffer);
+ free (file->fields.list);
+
+ if (file->program.author != NULL)
+ free (file->program.author);
+ if (file->program.name != NULL)
+ free (file->program.name);
+ if (file->program.url != NULL)
+ free (file->program.url);
+ if (file->program.version != NULL)
+ free (file->program.version);
+
+ memset (file, 0, sizeof (tagFile));
+
+ free (file);
+}
+
+static tagResult readNext (tagFile *const file, tagEntry *const entry)
+{
+ tagResult result = TagFailure;
+ if (file == NULL || ! file->initialized)
+ result = TagFailure;
+ else if (! readTagLine (file))
+ result = TagFailure;
+ else
+ {
+ if (entry != NULL)
+ parseTagLine (file, entry);
+ result = TagSuccess;
+ }
+ return result;
+}
+
+static const char *readFieldValue (
+ const tagEntry *const entry, const char *const key)
+{
+ const char *result = NULL;
+ int i;
+ if (strcmp (key, "kind") == 0)
+ result = entry->kind;
+ else if (strcmp (key, "file") == 0)
+ result = EmptyString;
+ else for (i = 0 ; i < entry->fields.count && result == NULL ; ++i)
+ if (strcmp (entry->fields.list [i].key, key) == 0)
+ result = entry->fields.list [i].value;
+ return result;
+}
+
+static int readTagLineSeek (tagFile *const file, const off_t pos)
+{
+ int result = 0;
+ if (fseek (file->fp, pos, SEEK_SET) == 0)
+ {
+ result = readTagLine (file); /* read probable partial line */
+ if (pos > 0 && result)
+ result = readTagLine (file); /* read complete line */
+ }
+ return result;
+}
+
+static int nameComparison (tagFile *const file)
+{
+ int result;
+ if (file->search.ignorecase)
+ {
+ if (file->search.partial)
+ result = strnuppercmp (file->search.name, file->name.buffer,
+ file->search.nameLength);
+ else
+ result = struppercmp (file->search.name, file->name.buffer);
+ }
+ else
+ {
+ if (file->search.partial)
+ result = strncmp (file->search.name, file->name.buffer,
+ file->search.nameLength);
+ else
+ result = strcmp (file->search.name, file->name.buffer);
+ }
+ return result;
+}
+
+static void findFirstNonMatchBefore (tagFile *const file)
+{
+#define JUMP_BACK 512
+ int more_lines;
+ int comp;
+ off_t start = file->pos;
+ off_t pos = start;
+ do
+ {
+ if (pos < (off_t) JUMP_BACK)
+ pos = 0;
+ else
+ pos = pos - JUMP_BACK;
+ more_lines = readTagLineSeek (file, pos);
+ comp = nameComparison (file);
+ } while (more_lines && comp == 0 && pos > 0 && pos < start);
+}
+
+static tagResult findFirstMatchBefore (tagFile *const file)
+{
+ tagResult result = TagFailure;
+ int more_lines;
+ off_t start = file->pos;
+ findFirstNonMatchBefore (file);
+ do
+ {
+ more_lines = readTagLine (file);
+ if (nameComparison (file) == 0)
+ result = TagSuccess;
+ } while (more_lines && result != TagSuccess && file->pos < start);
+ return result;
+}
+
+static tagResult findBinary (tagFile *const file)
+{
+ tagResult result = TagFailure;
+ off_t lower_limit = 0;
+ off_t upper_limit = file->size;
+ off_t last_pos = 0;
+ off_t pos = upper_limit / 2;
+ while (result != TagSuccess)
+ {
+ if (! readTagLineSeek (file, pos))
+ {
+ /* in case we fell off end of file */
+ result = findFirstMatchBefore (file);
+ break;
+ }
+ else if (pos == last_pos)
+ {
+ /* prevent infinite loop if we backed up to beginning of file */
+ break;
+ }
+ else
+ {
+ const int comp = nameComparison (file);
+ last_pos = pos;
+ if (comp < 0)
+ {
+ upper_limit = pos;
+ pos = lower_limit + ((upper_limit - lower_limit) / 2);
+ }
+ else if (comp > 0)
+ {
+ lower_limit = pos;
+ pos = lower_limit + ((upper_limit - lower_limit) / 2);
+ }
+ else if (pos == 0)
+ result = TagSuccess;
+ else
+ result = findFirstMatchBefore (file);
+ }
+ }
+ return result;
+}
+
+static tagResult findSequential (tagFile *const file)
+{
+ tagResult result = TagFailure;
+ if (file->initialized)
+ {
+ while (result == TagFailure && readTagLine (file))
+ {
+ if (nameComparison (file) == 0)
+ result = TagSuccess;
+ }
+ }
+ return result;
+}
+
+static tagResult find (tagFile *const file, tagEntry *const entry,
+ const char *const name, const int options)
+{
+ tagResult result = TagFailure;
+ file->search.name = name;
+ file->search.nameLength = strlen (name);
+ file->search.partial = (options & TAG_PARTIALMATCH) != 0;
+ file->search.ignorecase = (options & TAG_IGNORECASE) != 0;
+ fseek (file->fp, 0, SEEK_END);
+ file->size = ftell (file->fp);
+ rewind (file->fp);
+ if ((file->sortMethod == TAG_SORTED && !file->search.ignorecase) ||
+ (file->sortMethod == TAG_FOLDSORTED && file->search.ignorecase))
+ {
+#ifdef DEBUG
+ printf ("<performing binary search>\n");
+#endif
+ result = findBinary (file);
+ }
+ else
+ {
+#ifdef DEBUG
+ printf ("<performing sequential search>\n");
+#endif
+ result = findSequential (file);
+ }
+
+ if (result != TagSuccess)
+ file->search.pos = file->size;
+ else
+ {
+ file->search.pos = file->pos;
+ if (entry != NULL)
+ parseTagLine (file, entry);
+ }
+ return result;
+}
+
+static tagResult findNext (tagFile *const file, tagEntry *const entry)
+{
+ tagResult result = TagFailure;
+ if ((file->sortMethod == TAG_SORTED && !file->search.ignorecase) ||
+ (file->sortMethod == TAG_FOLDSORTED && file->search.ignorecase))
+ {
+ result = tagsNext (file, entry);
+ if (result == TagSuccess && nameComparison (file) != 0)
+ result = TagFailure;
+ }
+ else
+ {
+ result = findSequential (file);
+ if (result == TagSuccess && entry != NULL)
+ parseTagLine (file, entry);
+ }
+ return result;
+}
+
+/*
+* EXTERNAL INTERFACE
+*/
+
+extern tagFile *tagsOpen (const char *const filePath, tagFileInfo *const info)
+{
+ return initialize (filePath, info);
+}
+
+extern tagResult tagsSetSortType (tagFile *const file, const sortType type)
+{
+ tagResult result = TagFailure;
+ if (file != NULL && file->initialized)
+ {
+ file->sortMethod = type;
+ result = TagSuccess;
+ }
+ return result;
+}
+
+extern tagResult tagsFirst (tagFile *const file, tagEntry *const entry)
+{
+ tagResult result = TagFailure;
+ if (file != NULL && file->initialized)
+ {
+ gotoFirstLogicalTag (file);
+ result = readNext (file, entry);
+ }
+ return result;
+}
+
+extern tagResult tagsNext (tagFile *const file, tagEntry *const entry)
+{
+ tagResult result = TagFailure;
+ if (file != NULL && file->initialized)
+ result = readNext (file, entry);
+ return result;
+}
+
+extern const char *tagsField (const tagEntry *const entry, const char *const key)
+{
+ const char *result = NULL;
+ if (entry != NULL)
+ result = readFieldValue (entry, key);
+ return result;
+}
+
+extern tagResult tagsFind (tagFile *const file, tagEntry *const entry,
+ const char *const name, const int options)
+{
+ tagResult result = TagFailure;
+ if (file != NULL && file->initialized)
+ result = find (file, entry, name, options);
+ return result;
+}
+
+extern tagResult tagsFindNext (tagFile *const file, tagEntry *const entry)
+{
+ tagResult result = TagFailure;
+ if (file != NULL && file->initialized)
+ result = findNext (file, entry);
+ return result;
+}
+
+extern tagResult tagsClose (tagFile *const file)
+{
+ tagResult result = TagFailure;
+ if (file != NULL && file->initialized)
+ {
+ terminate (file);
+ result = TagSuccess;
+ }
+ return result;
+}
+
+/*
+* TEST FRAMEWORK
+*/
+
+#ifdef READTAGS_MAIN
+
+static const char *TagFileName = "tags";
+static const char *ProgramName;
+static int extensionFields;
+static int SortOverride;
+static sortType SortMethod;
+
+static void printTag (const tagEntry *entry)
+{
+ int i;
+ int first = 1;
+ const char* separator = ";\"";
+ const char* const empty = "";
+/* "sep" returns a value only the first time it is evaluated */
+#define sep (first ? (first = 0, separator) : empty)
+ printf ("%s\t%s\t%s",
+ entry->name, entry->file, entry->address.pattern);
+ if (extensionFields)
+ {
+ if (entry->kind != NULL && entry->kind [0] != '\0')
+ printf ("%s\tkind:%s", sep, entry->kind);
+ if (entry->fileScope)
+ printf ("%s\tfile:", sep);
+#if 0
+ if (entry->address.lineNumber > 0)
+ printf ("%s\tline:%lu", sep, entry->address.lineNumber);
+#endif
+ for (i = 0 ; i < entry->fields.count ; ++i)
+ printf ("%s\t%s:%s", sep, entry->fields.list [i].key,
+ entry->fields.list [i].value);
+ }
+ putchar ('\n');
+#undef sep
+}
+
+static void findTag (const char *const name, const int options)
+{
+ tagFileInfo info;
+ tagEntry entry;
+ tagFile *const file = tagsOpen (TagFileName, &info);
+ if (file == NULL)
+ {
+ fprintf (stderr, "%s: cannot open tag file: %s: %s\n",
+ ProgramName, strerror (info.status.error_number), name);
+ exit (1);
+ }
+ else
+ {
+ if (SortOverride)
+ tagsSetSortType (file, SortMethod);
+ if (tagsFind (file, &entry, name, options) == TagSuccess)
+ {
+ do
+ {
+ printTag (&entry);
+ } while (tagsFindNext (file, &entry) == TagSuccess);
+ }
+ tagsClose (file);
+ }
+}
+
+static void listTags (void)
+{
+ tagFileInfo info;
+ tagEntry entry;
+ tagFile *const file = tagsOpen (TagFileName, &info);
+ if (file == NULL)
+ {
+ fprintf (stderr, "%s: cannot open tag file: %s: %s\n",
+ ProgramName, strerror (info.status.error_number), TagFileName);
+ exit (1);
+ }
+ else
+ {
+ while (tagsNext (file, &entry) == TagSuccess)
+ printTag (&entry);
+ tagsClose (file);
+ }
+}
+
+const char *const Usage =
+ "Find tag file entries matching specified names.\n\n"
+ "Usage: %s [-ilp] [-s[0|1]] [-t file] [name(s)]\n\n"
+ "Options:\n"
+ " -e Include extension fields in output.\n"
+ " -i Perform case-insensitive matching.\n"
+ " -l List all tags.\n"
+ " -p Perform partial matching.\n"
+ " -s[0|1|2] Override sort detection of tag file.\n"
+ " -t file Use specified tag file (default: \"tags\").\n"
+ "Note that options are acted upon as encountered, so order is significant.\n";
+
+extern int main (int argc, char **argv)
+{
+ int options = 0;
+ int actionSupplied = 0;
+ int i;
+ ProgramName = argv [0];
+ if (argc == 1)
+ {
+ fprintf (stderr, Usage, ProgramName);
+ exit (1);
+ }
+ for (i = 1 ; i < argc ; ++i)
+ {
+ const char *const arg = argv [i];
+ if (arg [0] != '-')
+ {
+ findTag (arg, options);
+ actionSupplied = 1;
+ }
+ else
+ {
+ size_t j;
+ for (j = 1 ; arg [j] != '\0' ; ++j)
+ {
+ switch (arg [j])
+ {
+ case 'e': extensionFields = 1; break;
+ case 'i': options |= TAG_IGNORECASE; break;
+ case 'p': options |= TAG_PARTIALMATCH; break;
+ case 'l': listTags (); actionSupplied = 1; break;
+
+ case 't':
+ if (arg [j+1] != '\0')
+ {
+ TagFileName = arg + j + 1;
+ j += strlen (TagFileName);
+ }
+ else if (i + 1 < argc)
+ TagFileName = argv [++i];
+ else
+ {
+ fprintf (stderr, Usage, ProgramName);
+ exit (1);
+ }
+ break;
+ case 's':
+ SortOverride = 1;
+ ++j;
+ if (arg [j] == '\0')
+ SortMethod = TAG_SORTED;
+ else if (strchr ("012", arg[j]) != NULL)
+ SortMethod = (sortType) (arg[j] - '0');
+ else
+ {
+ fprintf (stderr, Usage, ProgramName);
+ exit (1);
+ }
+ break;
+ default:
+ fprintf (stderr, "%s: unknown option: %c\n",
+ ProgramName, arg[j]);
+ exit (1);
+ break;
+ }
+ }
+ }
+ }
+ if (! actionSupplied)
+ {
+ fprintf (stderr,
+ "%s: no action specified: specify tag name(s) or -l option\n",
+ ProgramName);
+ exit (1);
+ }
+ return 0;
+}
+
+#endif
+
+/* vi:set tabstop=8 shiftwidth=4: */
diff --git a/parts/ctags2/readtags.h b/parts/ctags2/readtags.h
new file mode 100644
index 00000000..4d4228fc
--- /dev/null
+++ b/parts/ctags2/readtags.h
@@ -0,0 +1,251 @@
+/*
+*
+* Copyright (c) 1996-2003, Darren Hiebert
+*
+* This source code is released for the public domain.
+*
+* This file defines the public interface for looking up tag entries in tag
+* files.
+*
+* The functions defined in this interface are intended to provide tag file
+* support to a software tool. The tag lookups provided are sufficiently fast
+* enough to permit opening a sorted tag file, searching for a matching tag,
+* then closing the tag file each time a tag is looked up (search times are
+* on the order of hundreths of a second, even for huge tag files). This is
+* the recommended use of this library for most tool applications. Adhering
+* to this approach permits a user to regenerate a tag file at will without
+* the tool needing to detect and resynchronize with changes to the tag file.
+* Even for an unsorted 24MB tag file, tag searches take about one second.
+*/
+#ifndef READTAGS_H
+#define READTAGS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+* MACROS
+*/
+
+/* Options for tagsSetSortType() */
+typedef enum {
+ TAG_UNSORTED, TAG_SORTED, TAG_FOLDSORTED
+} sortType ;
+
+/* Options for tagsFind() */
+#define TAG_FULLMATCH 0x0
+#define TAG_PARTIALMATCH 0x1
+
+#define TAG_OBSERVECASE 0x0
+#define TAG_IGNORECASE 0x2
+
+/*
+* DATA DECLARATIONS
+*/
+
+typedef enum { TagFailure = 0, TagSuccess = 1 } tagResult;
+
+struct sTagFile;
+
+typedef struct sTagFile tagFile;
+
+/* This structure contains information about the tag file. */
+typedef struct {
+
+ struct {
+ /* was the tag file successfully opened? */
+ int opened;
+
+ /* errno value when 'opened' is false */
+ int error_number;
+ } status;
+
+ /* information about the structure of the tag file */
+ struct {
+ /* format of tag file (1 = original, 2 = extended) */
+ short format;
+
+ /* how is the tag file sorted? */
+ sortType sort;
+ } file;
+
+
+ /* information about the program which created this tag file */
+ struct {
+ /* name of author of generating program (may be null) */
+ const char *author;
+
+ /* name of program (may be null) */
+ const char *name;
+
+ /* URL of distribution (may be null) */
+ const char *url;
+
+ /* program version (may be null) */
+ const char *version;
+ } program;
+
+} tagFileInfo;
+
+/* This structure contains information about an extension field for a tag.
+ * These exist at the end of the tag in the form "key:value").
+ */
+typedef struct {
+
+ /* the key of the extension field */
+ const char *key;
+
+ /* the value of the extension field (may be an empty string) */
+ const char *value;
+
+} tagExtensionField;
+
+/* This structure contains information about a specific tag. */
+typedef struct {
+
+ /* name of tag */
+ const char *name;
+
+ /* path of source file containing definition of tag */
+ const char *file;
+
+ /* address for locating tag in source file */
+ struct {
+ /* pattern for locating source line
+ * (may be NULL if not present) */
+ const char *pattern;
+
+ /* line number in source file of tag definition
+ * (may be zero if not known) */
+ unsigned long lineNumber;
+ } address;
+
+ /* kind of tag (may by name, character, or NULL if not known) */
+ const char *kind;
+
+ /* is tag of file-limited scope? */
+ short fileScope;
+
+ /* miscellaneous extension fields */
+ struct {
+ /* number of entries in `list' */
+ unsigned short count;
+
+ /* list of key value pairs */
+ tagExtensionField *list;
+ } fields;
+
+} tagEntry;
+
+
+/*
+* FUNCTION PROTOTYPES
+*/
+
+/*
+* This function must be called before calling other functions in this
+* library. It is passed the path to the tag file to read and a (possibly
+* null) pointer to a structure which, if not null, will be populated with
+* information about the tag file. If successful, the function will return a
+* handle which must be supplied to other calls to read information from the
+* tag file, and info.status.opened will be set to true. If unsuccessful,
+* info.status.opened will be set to false and info.status.error_number will
+* be set to the errno value representing the system error preventing the tag
+* file from being successfully opened.
+*/
+extern tagFile *tagsOpen (const char *const filePath, tagFileInfo *const info);
+
+/*
+* This function allows the client to override the normal automatic detection
+* of how a tag file is sorted. Permissible values for `type' are
+* TAG_UNSORTED, TAG_SORTED, TAG_FOLDSORTED. Tag files in the new extended
+* format contain a key indicating whether or not they are sorted. However,
+* tag files in the original format do not contain such a key even when
+* sorted, preventing this library from taking advantage of fast binary
+* lookups. If the client knows that such an unmarked tag file is indeed
+* sorted (or not), it can override the automatic detection. Note that
+* incorrect lookup results will result if a tag file is marked as sorted when
+* it actually is not. The function will return TagSuccess if called on an
+* open tag file or TagFailure if not.
+*/
+extern tagResult tagsSetSortType (tagFile *const file, const sortType type);
+
+/*
+* Reads the first tag in the file, if any. It is passed the handle to an
+* opened tag file and a (possibly null) pointer to a structure which, if not
+* null, will be populated with information about the first tag file entry.
+* The function will return TagSuccess another tag entry is found, or
+* TagFailure if not (i.e. it reached end of file).
+*/
+extern tagResult tagsFirst (tagFile *const file, tagEntry *const entry);
+
+/*
+* Step to the next tag in the file, if any. It is passed the handle to an
+* opened tag file and a (possibly null) pointer to a structure which, if not
+* null, will be populated with information about the next tag file entry. The
+* function will return TagSuccess another tag entry is found, or TagFailure
+* if not (i.e. it reached end of file). It will always read the first tag in
+* the file immediately after calling tagsOpen().
+*/
+extern tagResult tagsNext (tagFile *const file, tagEntry *const entry);
+
+/*
+* Retrieve the value associated with the extension field for a specified key.
+* It is passed a pointer to a structure already populated with values by a
+* previous call to tagsNext(), tagsFind(), or tagsFindNext(), and a string
+* containing the key of the desired extension field. If no such field of the
+* specified key exists, the function will return null.
+*/
+extern const char *tagsField (const tagEntry *const entry, const char *const key);
+
+/*
+* Find the first tag matching `name'. The structure pointed to by `entry'
+* will be populated with information about the tag file entry. If a tag file
+* is sorted using the C locale, a binary search algorithm is used to search
+* the tag file, resulting in very fast tag lookups, even in huge tag files.
+* Various options controlling the matches can be combined by bit-wise or-ing
+* certain values together. The available values are:
+*
+* TAG_PARTIALMATCH
+* Tags whose leading characters match `name' will qualify.
+*
+* TAG_FULLMATCH
+* Only tags whose full lengths match `name' will qualify.
+*
+* TAG_IGNORECASE
+* Matching will be performed in a case-insenstive manner. Note that
+* this disables binary searches of the tag file.
+*
+* TAG_OBSERVECASE
+* Matching will be performed in a case-senstive manner. Note that
+* this enables binary searches of the tag file.
+*
+* The function will return TagSuccess if a tag matching the name is found, or
+* TagFailure if not.
+*/
+extern tagResult tagsFind (tagFile *const file, tagEntry *const entry, const char *const name, const int options);
+
+/*
+* Find the next tag matching the name and options supplied to the most recent
+* call to tagsFind() for the same tag file. The structure pointed to by
+* `entry' will be populated with information about the tag file entry. The
+* function will return TagSuccess if another tag matching the name is found,
+* or TagFailure if not.
+*/
+extern tagResult tagsFindNext (tagFile *const file, tagEntry *const entry);
+
+/*
+* Call tagsTerminate() at completion of reading the tag file, which will
+* close the file and free any internal memory allocated. The function will
+* return TagFailure is no file is currently open, TagSuccess otherwise.
+*/
+extern tagResult tagsClose (tagFile *const file);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/* vi:set tabstop=8 shiftwidth=4: */
diff --git a/parts/ctags2/tagitem.cpp b/parts/ctags2/tagitem.cpp
new file mode 100644
index 00000000..e2ddf158
--- /dev/null
+++ b/parts/ctags2/tagitem.cpp
@@ -0,0 +1,23 @@
+/***************************************************************************
+ * Copyright (C) 2004 by Jens Dagerbo *
+ * jens.dagerbo@swipnet.se *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "tagitem.h"
+
+TagItem::TagItem( QListView * lv, QString const & tag, QString const & type, QString const & file, QString const & pattern )
+ : QListViewItem( lv ), tag(tag), type(type), file(file), pattern(pattern)
+{}
+
+TagItem::~TagItem()
+{
+}
+
+
+
diff --git a/parts/ctags2/tagitem.h b/parts/ctags2/tagitem.h
new file mode 100644
index 00000000..fddb823d
--- /dev/null
+++ b/parts/ctags2/tagitem.h
@@ -0,0 +1,29 @@
+/***************************************************************************
+ * Copyright (C) 2004 by Jens Dagerbo *
+ * jens.dagerbo@swipnet.se *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef TAGITEM_H
+#define TAGITEM_H
+
+#include <qlistview.h>
+
+class TagItem : public QListViewItem
+{
+public:
+ TagItem(QListView * lv, QString const & tag, QString const & type, QString const & file, QString const & pattern );
+ ~TagItem();
+
+ QString tag;
+ QString type;
+ QString file;
+ QString pattern;
+};
+
+#endif
diff --git a/parts/ctags2/tags.cpp b/parts/ctags2/tags.cpp
new file mode 100644
index 00000000..3ba98159
--- /dev/null
+++ b/parts/ctags2/tags.cpp
@@ -0,0 +1,171 @@
+/***************************************************************************
+ * Copyright (C) 2004 by Jens Dagerbo *
+ * jens.dagerbo@swipnet.se *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+namespace ctags
+{
+#include "readtags.h"
+}
+
+#include "ctagskinds.h"
+
+#include "tags.h"
+
+QStringList Tags::_tagFiles;
+
+Tags::TagEntry::TagEntry() {}
+
+Tags::TagEntry::TagEntry( const QString & tag, const QString & type, const QString & file, const QString & pattern )
+ : tag(tag), type(type), file(file), pattern(pattern)
+{}
+
+
+bool Tags::hasTag(const QString & tag )
+{
+ QStringList::iterator it;
+ for (it = _tagFiles.begin(); it != _tagFiles.end() ; it++) {
+ if (hasTag((*it).ascii(), tag))
+ return true;
+ }
+
+ return false;
+}
+
+bool Tags::hasTag(const char* tagFile, const QString & tag )
+{
+ ctags::tagFileInfo info;
+ ctags::tagFile * file = ctags::tagsOpen(tagFile, &info );
+ ctags::tagEntry entry;
+
+ bool found = ( ctags::tagsFind( file, &entry, tag.ascii(), TAG_FULLMATCH | TAG_OBSERVECASE ) == ctags::TagSuccess );
+
+ ctags::tagsClose( file );
+
+ return found;
+}
+
+unsigned int Tags::numberOfMatches( const QString & tagpart, bool partial )
+{
+ unsigned int n = 0;
+ QStringList::iterator it;
+ for (it = _tagFiles.begin(); it != _tagFiles.end(); it++)
+ {
+ n += numberOfMatches( (*it).ascii(), tagpart, partial );
+ }
+
+ return n;
+}
+
+unsigned int Tags::numberOfMatches(const char* tagFile, const QString & tagpart, bool partial )
+{
+ unsigned int n = 0;
+
+ if ( tagpart.isEmpty() ) return 0;
+
+ ctags::tagFileInfo info;
+ ctags::tagFile * file = ctags::tagsOpen( tagFile, &info );
+ ctags::tagEntry entry;
+
+ if ( ctags::tagsFind( file, &entry, tagpart.ascii(), TAG_OBSERVECASE | (partial ? TAG_PARTIALMATCH : TAG_FULLMATCH) ) == ctags::TagSuccess )
+ {
+ do
+ {
+ n++;
+ }
+ while ( ctags::tagsFindNext( file, &entry ) == ctags::TagSuccess );
+ }
+
+ ctags::tagsClose( file );
+
+ return n;
+}
+
+
+Tags::TagList Tags::getMatches( const QString & tagpart, bool partial, const QStringList & types )
+{
+ Tags::TagList list;
+
+ // build a compound tag list from all the configured tag files
+ QStringList::iterator it;
+ for ( it = _tagFiles.begin(); it != _tagFiles.end(); it++ )
+ {
+ list += getMatches((*it).ascii(), tagpart, partial, types);
+ }
+
+ return list;
+}
+
+Tags::TagList Tags::getMatches(const char* tagFile, const QString & tagpart, bool partial, const QStringList & types )
+{
+ Tags::TagList list;
+
+ if ( tagpart.isEmpty() ) return list;
+
+ ctags::tagFileInfo info;
+ ctags::tagFile * file = ctags::tagsOpen(tagFile, &info );
+ ctags::tagEntry entry;
+
+ if ( ctags::tagsFind( file, &entry, tagpart.ascii(), TAG_OBSERVECASE | (partial ? TAG_PARTIALMATCH : TAG_FULLMATCH) ) == ctags::TagSuccess )
+ {
+ do
+ {
+ QString type( CTagsKinds::findKind( entry.kind, QString( entry.file ).section( '.', -1 ) ) );
+ QString file( entry.file );
+
+ if ( type.isEmpty() && file.endsWith( "Makefile" ) )
+ {
+ type = "macro";
+ }
+ if ( types.isEmpty() || types.contains( entry.kind ) )
+ {
+ list << TagEntry( QString( entry.name ), type, file, QString( entry.address.pattern ) );
+ }
+ }
+ while ( ctags::tagsFindNext( file, &entry ) == ctags::TagSuccess );
+ }
+
+ ctags::tagsClose( file );
+
+ return list;
+}
+
+void Tags::setTagFiles(const QStringList& tagFiles )
+{
+ _tagFiles = tagFiles;
+}
+
+QStringList Tags::getTagFiles( )
+{
+ return _tagFiles;
+}
+
+unsigned int Tags::numberOfPartialMatches( const QString & tagpart )
+{
+ return numberOfMatches( tagpart, true );
+}
+
+unsigned int Tags::numberOfExactMatches( const QString & tagpart )
+{
+ return numberOfMatches( tagpart, false );
+}
+
+Tags::TagList Tags::getPartialMatches( const QString & tagpart )
+{
+ return getMatches( tagpart, true );
+}
+
+Tags::TagList Tags::getExactMatches( const QString & tag )
+{
+ return getMatches( tag, false );
+}
+
+// kate: space-indent off; indent-width 4; tab-width 4; show-tabs off;
+
+
diff --git a/parts/ctags2/tags.h b/parts/ctags2/tags.h
new file mode 100644
index 00000000..1d7e3604
--- /dev/null
+++ b/parts/ctags2/tags.h
@@ -0,0 +1,74 @@
+/***************************************************************************
+ * Copyright (C) 2004 by Jens Dagerbo *
+ * jens.dagerbo@swipnet.se *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef TAGS_H
+#define TAGS_H
+
+#include <qvaluelist.h>
+#include <qcstring.h>
+#include <qstring.h>
+#include <qstringlist.h>
+
+class Tags
+{
+public:
+
+ struct TagEntry
+ {
+ TagEntry();
+ TagEntry( const QString & tag, const QString & type, const QString & file, const QString & pattern );
+
+ QString tag;
+ QString type;
+ QString file;
+ QString pattern;
+ };
+
+ typedef QValueList<TagEntry> TagList;
+
+ /**
+ * Method to set the tag database filename
+ * @param file the tag database filename
+ */
+ static void setTagFiles(const QStringList& tagFiles);
+
+ static QStringList getTagFiles();
+
+ /**
+ * Method to check if the tag database contains a specific tag
+ * @param tag Tag to look up
+ * @return returns true if tag database contains 'tag'
+ */
+ static bool hasTag( const QString & tag );
+
+ static unsigned int numberOfPartialMatches( const QString & tagpart );
+ static unsigned int numberOfExactMatches( const QString & tag );
+ static unsigned int numberOfMatches( const QString & tagpart, bool partial );
+
+ static TagList getPartialMatches( const QString & tagpart );
+ static TagList getExactMatches( const QString & tag );
+ static TagList getMatches( const QString & tagpart, bool partial, const QStringList & types = QStringList() );
+
+private:
+ static Tags::TagList getMatches(const char* tagFile,
+ const QString & tagpart,
+ bool partial,
+ const QStringList & types );
+ static unsigned int numberOfMatches(const char* tagFile,
+ const QString & tagpart,
+ bool partial );
+ static bool hasTag(const char* tagFile, const QString & tag );
+ static QStringList _tagFiles;
+};
+
+#endif
+
+// kate: space-indent off; indent-width 4; tab-width 4; show-tabs off;