kate Library API Documentation

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