# kate Library API Documentation

Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# katesyntaxdocument.cpp

    00001 /* This file is part of the KDE libraries
    00002    Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
    00003    Copyright (C) 2000 Scott Manson <sdmanson@alltel.net>
    00004
    00005    This library is free software; you can redistribute it and/or
    00006    modify it under the terms of the GNU Library General Public
    00007    License version 2 as published by the Free Software Foundation.
    00008
    00009    This library is distributed in the hope that it will be useful,
    00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
    00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00012    Library General Public License for more details.
    00013
    00014    You should have received a copy of the GNU Library General Public License
    00015    along with this library; see the file COPYING.LIB.  If not, write to
    00016    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00017    Boston, MA 02111-1307, USA.
    00018 */
    00019
    00020 #include "katesyntaxdocument.h"
    00021
    00022 #include <sys/types.h>
    00023 #include <sys/stat.h>
    00024 #include <unistd.h>
    00025
    00026 #include <kdebug.h>
    00027 #include <kstandarddirs.h>
    00028 #include <klocale.h>
    00029 #include <kmessagebox.h>
    00030 #include <kconfig.h>
    00031
    00032 #include <qfile.h>
    00033
    00034 KateSyntaxDocument::KateSyntaxDocument(bool force)
    00035   : QDomDocument()
    00036 {
    00037   // Let's build the Mode List (katesyntaxhighlightingrc)
    00038   setupModeList(force);
    00039 }
    00040
    00041 KateSyntaxDocument::~KateSyntaxDocument()
    00042 {
    00043   for (uint i=0; i < myModeList.size(); i++)
    00044     delete myModeList[i];
    00045 }
    00046
    00051 bool KateSyntaxDocument::setIdentifier(const QString& identifier)
    00052 {
    00053   // if the current file is the same as the new one don't do anything.
    00054   if(currentFile != identifier)
    00055   {
    00056     // let's open the new file
    00057     QFile f( identifier );
    00058
    00059     if ( f.open(IO_ReadOnly) )
    00060     {
    00061       // Let's parse the contets of the xml file
    00062       /* The result of this function should be check for robustness,
    00063          a false returned means a parse error */
    00064       QString errorMsg;
    00065       int line, col;
    00066       bool success=setContent(&f,&errorMsg,&line,&col);
    00067
    00068       // Ok, now the current file is the pretended one (identifier)
    00069       currentFile = identifier;
    00070
    00071       // Close the file, is not longer needed
    00072       f.close();
    00073
    00074       if (!success)
    00075       {
    00076         KMessageBox::error(0L,i18n("<qt>The error <b>%4</b><br> has been detected in the file %1 at %2/%3</qt>").arg(identifier)
    00077             .arg(line).arg(col).arg(i18n("QXml",errorMsg.utf8())));
    00078         return false;
    00079       }
    00080     }
    00081     else
    00082     {
    00083       // Oh o, we couldn't open the file.
    00084       KMessageBox::error( 0L, i18n("Unable to open %1").arg(identifier) );
    00085       return false;
    00086     }
    00087   }
    00088   return true;
    00089 }
    00090
    00094 bool KateSyntaxDocument::nextGroup( KateSyntaxContextData* data)
    00095 {
    00096   if(!data)
    00097     return false;
    00098
    00099   // No group yet so go to first child
    00100   if (data->currentGroup.isNull())
    00101   {
    00102     // Skip over non-elements. So far non-elements are just comments
    00103     QDomNode node = data->parent.firstChild();
    00104     while (node.isComment())
    00105       node = node.nextSibling();
    00106
    00107     data->currentGroup = node.toElement();
    00108   }
    00109   else
    00110   {
    00111     // common case, iterate over siblings, skipping comments as we go
    00112     QDomNode node = data->currentGroup.nextSibling();
    00113     while (node.isComment())
    00114       node = node.nextSibling();
    00115
    00116     data->currentGroup = node.toElement();
    00117   }
    00118
    00119   return !data->currentGroup.isNull();
    00120 }
    00121
    00125 bool KateSyntaxDocument::nextItem( KateSyntaxContextData* data)
    00126 {
    00127   if(!data)
    00128     return false;
    00129
    00130   if (data->item.isNull())
    00131   {
    00132     QDomNode node = data->currentGroup.firstChild();
    00133     while (node.isComment())
    00134       node = node.nextSibling();
    00135
    00136     data->item = node.toElement();
    00137   }
    00138   else
    00139   {
    00140     QDomNode node = data->item.nextSibling();
    00141     while (node.isComment())
    00142       node = node.nextSibling();
    00143
    00144     data->item = node.toElement();
    00145   }
    00146
    00147   return !data->item.isNull();
    00148 }
    00149
    00153 QString KateSyntaxDocument::groupItemData( const KateSyntaxContextData* data, const QString& name){
    00154   if(!data)
    00155     return QString::null;
    00156
    00157   // If there's no name just return the tag name of data->item
    00158   if ( (!data->item.isNull()) && (name.isEmpty()))
    00159   {
    00160     return data->item.tagName();
    00161   }
    00162
    00163   // if name is not empty return the value of the attribute name
    00164   if (!data->item.isNull())
    00165   {
    00166     return data->item.attribute(name);
    00167   }
    00168
    00169   return QString::null;
    00170
    00171 }
    00172
    00173 QString KateSyntaxDocument::groupData( const KateSyntaxContextData* data,const QString& name)
    00174 {
    00175   if(!data)
    00176     return QString::null;
    00177
    00178   if (!data->currentGroup.isNull())
    00179   {
    00180     return data->currentGroup.attribute(name);
    00181   }
    00182   else
    00183   {
    00184     return QString::null;
    00185   }
    00186 }
    00187
    00188 void KateSyntaxDocument::freeGroupInfo( KateSyntaxContextData* data)
    00189 {
    00190   if (data)
    00191     delete data;
    00192 }
    00193
    00194 KateSyntaxContextData* KateSyntaxDocument::getSubItems(KateSyntaxContextData* data)
    00195 {
    00196   KateSyntaxContextData *retval = new KateSyntaxContextData;
    00197
    00198   if (data != 0)
    00199   {
    00200     retval->parent = data->currentGroup;
    00201     retval->currentGroup = data->item;
    00202   }
    00203
    00204   return retval;
    00205 }
    00206
    00207 bool KateSyntaxDocument::getElement (QDomElement &element, const QString &mainGroupName, const QString &config)
    00208 {
    00209   kdDebug(13010) << "Looking for \"" << mainGroupName << "\" -> \"" << config << "\"." << endl;
    00210
    00211   QDomNodeList nodes = documentElement().childNodes();
    00212
    00213   // Loop over all these child nodes looking for mainGroupName
    00214   for (unsigned int i=0; i<nodes.count(); i++)
    00215   {
    00216     QDomElement elem = nodes.item(i).toElement();
    00217     if (elem.tagName() == mainGroupName)
    00218     {
    00219       // Found mainGroupName ...
    00220       QDomNodeList subNodes = elem.childNodes();
    00221
    00222       // ... so now loop looking for config
    00223       for (unsigned int j=0; j<subNodes.count(); j++)
    00224       {
    00225         QDomElement subElem = subNodes.item(j).toElement();
    00226         if (subElem.tagName() == config)
    00227         {
    00228           // Found it!
    00229           element = subElem;
    00230           return true;
    00231         }
    00232       }
    00233
    00234       kdDebug(13010) << "WARNING: \""<< config <<"\" wasn't found!" << endl;
    00235       return false;
    00236     }
    00237   }
    00238
    00239   kdDebug(13010) << "WARNING: \""<< mainGroupName <<"\" wasn't found!" << endl;
    00240   return false;
    00241 }
    00242
    00247 KateSyntaxContextData* KateSyntaxDocument::getConfig(const QString& mainGroupName, const QString &config)
    00248 {
    00249   QDomElement element;
    00250   if (getElement(element, mainGroupName, config))
    00251   {
    00252     KateSyntaxContextData *data = new KateSyntaxContextData;
    00253     data->item = element;
    00254     return data;
    00255   }
    00256   return 0;
    00257 }
    00258
    00263 KateSyntaxContextData* KateSyntaxDocument::getGroupInfo(const QString& mainGroupName, const QString &group)
    00264 {
    00265   QDomElement element;
    00266   if (getElement(element, mainGroupName, group+"s"))
    00267   {
    00268     KateSyntaxContextData *data = new KateSyntaxContextData;
    00269     data->parent = element;
    00270     return data;
    00271   }
    00272   return 0;
    00273 }
    00274
    00278 QStringList& KateSyntaxDocument::finddata(const QString& mainGroup, const QString& type, bool clearList)
    00279 {
    00280   kdDebug(13010)<<"Create a list of keywords \""<<type<<"\" from \""<<mainGroup<<"\"."<<endl;
    00281   if (clearList)
    00282     m_data.clear();
    00283
    00284   for(QDomNode node = documentElement().firstChild(); !node.isNull(); node = node.nextSibling())
    00285   {
    00286     QDomElement elem = node.toElement();
    00287     if (elem.tagName() == mainGroup)
    00288     {
    00289       kdDebug(13010)<<"\""<<mainGroup<<"\" found."<<endl;
    00290       QDomNodeList nodelist1 = elem.elementsByTagName("list");
    00291
    00292       for (uint l=0; l<nodelist1.count(); l++)
    00293       {
    00294         if (nodelist1.item(l).toElement().attribute("name") == type)
    00295         {
    00296           kdDebug(13010)<<"List with attribute name=\""<<type<<"\" found."<<endl;
    00297           QDomNodeList childlist = nodelist1.item(l).toElement().childNodes();
    00298
    00299           for (uint i=0; i<childlist.count(); i++)
    00300           {
    00301             QString element = childlist.item(i).toElement().text().stripWhiteSpace();
    00302             if (element.isEmpty())
    00303               continue;
    00304 #ifndef NDEBUG
    00305             if (i<6)
    00306             {
    00307               kdDebug(13010)<<"\""<<element<<"\" added to the list \""<<type<<"\""<<endl;
    00308             }
    00309             else if(i==6)
    00310             {
    00311               kdDebug(13010)<<"... The list continues ..."<<endl;
    00312             }
    00313 #endif
    00314             m_data += element;
    00315           }
    00316
    00317           break;
    00318         }
    00319       }
    00320       break;
    00321     }
    00322   }
    00323
    00324   return m_data;
    00325 }
    00326
    00327 // Private
    00331 void KateSyntaxDocument::setupModeList (bool force)
    00332 {
    00333   // If there's something in myModeList the Mode List was already built so, don't do it again
    00334   if (!myModeList.isEmpty())
    00335     return;
    00336
    00337   // We'll store the ModeList in katesyntaxhighlightingrc
    00338   KConfig config("katesyntaxhighlightingrc", false, false);
    00339
    00340   // figure our if the kate install is too new
    00341   config.setGroup ("General");
    00342   if (config.readNumEntry ("Version") > config.readNumEntry ("CachedVersion"))
    00343   {
    00344     config.writeEntry ("CachedVersion", config.readNumEntry ("Version"));
    00345     force = true;
    00346   }
    00347
    00348   // Let's get a list of all the xml files for hl
    00349   QStringList list = KGlobal::dirs()->findAllResources("data","katepart/syntax/*.xml",false,true);
    00350
    00351   // Let's iterate through the list and build the Mode List
    00352   for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it )
    00353   {
    00354     // Each file has a group called:
    00355     QString Group="Cache "+ *it;
    00356
    00357     // Let's go to this group
    00358     config.setGroup(Group);
    00359
    00360     // stat the file
    00361     struct stat sbuf;
    00362     memset (&sbuf, 0, sizeof(sbuf));
    00363     stat(QFile::encodeName(*it), &sbuf);
    00364
    00365     // If the group exist and we're not forced to read the xml file, let's build myModeList for katesyntax..rc
    00366     if (!force && config.hasGroup(Group) && (sbuf.st_mtime == config.readNumEntry("lastModified")))
    00367     {
    00368       // Let's make a new KateSyntaxModeListItem to instert in myModeList from the information in katesyntax..rc
    00369       KateSyntaxModeListItem *mli=new KateSyntaxModeListItem;
    00370       mli->name       = config.readEntry("name");
    00371       mli->nameTranslated = i18n("Language",mli->name.utf8());
    00372       mli->section    = i18n("Language Section",config.readEntry("section").utf8());
    00373       mli->mimetype   = config.readEntry("mimetype");
    00374       mli->extension  = config.readEntry("extension");
    00375       mli->version    = config.readEntry("version");
    00376       mli->priority   = config.readEntry("priority");
    00377       mli->author    = config.readEntry("author");
    00378       mli->license   = config.readEntry("license");
    00379       mli->hidden   =  config.readBoolEntry("hidden");
    00380       mli->identifier = *it;
    00381
    00382       // Apend the item to the list
    00383       myModeList.append(mli);
    00384     }
    00385     else
    00386     {
    00387       kdDebug (13010) << "UPDATE hl cache for: " << *it << endl;
    00388
    00389       // We're forced to read the xml files or the mode doesn't exist in the katesyntax...rc
    00390       QFile f(*it);
    00391
    00392       if (f.open(IO_ReadOnly))
    00393       {
    00394         // Ok we opened the file, let's read the contents and close the file
    00395         /* the return of setContent should be checked because a false return shows a parsing error */
    00396         QString errMsg;
    00397         int line, col;
    00398
    00399         bool success = setContent(&f,&errMsg,&line,&col);
    00400
    00401         f.close();
    00402
    00403         if (success)
    00404         {
    00405           QDomElement root = documentElement();
    00406
    00407           if (!root.isNull())
    00408           {
    00409             // If the 'first' tag is language, go on
    00410             if (root.tagName()=="language")
    00411             {
    00412               // let's make the mode list item.
    00413               KateSyntaxModeListItem *mli = new KateSyntaxModeListItem;
    00414
    00415               mli->name      = root.attribute("name");
    00416               mli->section   = root.attribute("section");
    00417               mli->mimetype  = root.attribute("mimetype");
    00418               mli->extension = root.attribute("extensions");
    00419               mli->version   = root.attribute("version");
    00420               mli->priority  = root.attribute("priority");
    00421               mli->author    = root.attribute("author");
    00422               mli->license   = root.attribute("license");
    00423
    00424               QString hidden = root.attribute("hidden");
    00425               mli->hidden    = (hidden == "true" || hidden == "TRUE");
    00426
    00427               mli->identifier = *it;
    00428
    00429               // Now let's write or overwrite (if force==true) the entry in katesyntax...rc
    00430               config.setGroup(Group);
    00431               config.writeEntry("name",mli->name);
    00432               config.writeEntry("section",mli->section);
    00433               config.writeEntry("mimetype",mli->mimetype);
    00434               config.writeEntry("extension",mli->extension);
    00435               config.writeEntry("version",mli->version);
    00436               config.writeEntry("priority",mli->priority);
    00437               config.writeEntry("author",mli->author);
    00438               config.writeEntry("license",mli->license);
    00439               config.writeEntry("hidden",mli->hidden);
    00440
    00441               // modified time to keep cache in sync
    00442               config.writeEntry("lastModified", sbuf.st_mtime);
    00443
    00444               // Now that the data is in the config file, translate section
    00445               mli->section    = i18n("Language Section",mli->section.utf8());
    00446               mli->nameTranslated = i18n("Language",mli->name.utf8());
    00447
    00448               // Append the new item to the list.
    00449               myModeList.append(mli);
    00450             }
    00451           }
    00452         }
    00453         else
    00454         {
    00455           KateSyntaxModeListItem *emli=new KateSyntaxModeListItem;
    00456
    00457           emli->section=i18n("Errors!");
    00458           emli->mimetype="invalid_file/invalid_file";
    00459           emli->extension="invalid_file.invalid_file";
    00460           emli->version="1.";
    00461           emli->name=QString ("Error: %1").arg(*it); // internal
    00462           emli->nameTranslated=i18n("Error: %1").arg(*it); // translated
    00463           emli->identifier=(*it);
    00464
    00465           myModeList.append(emli);
    00466         }
    00467       }
    00468     }
    00469   }
    00470
    00471   // Syncronize with the file katesyntax...rc
    00472   config.sync();
    00473 }
    00474
    00475 // kate: space-indent on; indent-width 2; replace-tabs on;

This file is part of the documentation for kate Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:36:38 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003