• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

Kate

katesyntaxdocument.cpp

Go to the documentation of this file.
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., 51 Franklin Street, Fifth Floor,
00017    Boston, MA 02110-1301, 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;

Kate

Skip menu "Kate"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal