00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "katesyntaxdocument.h"
00021
00022 #include <sys/types.h>
00023 #include <sys/stat.h>
00024 #include <unistd.h>
00025 #include <time.h>
00026 #include <sys/time.h>
00027
00028 #include <kdebug.h>
00029 #include <kstandarddirs.h>
00030 #include <klocale.h>
00031 #include <kmessagebox.h>
00032 #include <kconfiggroup.h>
00033
00034 #include <QtGui/QApplication>
00035 #include <QtCore/QFile>
00036
00037
00038 #undef KSD_OVER_VERBOSE
00039
00040 KateSyntaxDocument::KateSyntaxDocument(KConfig *config, bool force)
00041 : QDomDocument()
00042 , m_config (config)
00043 {
00044
00045 setupModeList(force);
00046 }
00047
00048 KateSyntaxDocument::~KateSyntaxDocument()
00049 {
00050 for (int i=0; i < myModeList.size(); i++)
00051 delete myModeList[i];
00052 }
00053
00058 bool KateSyntaxDocument::setIdentifier(const QString& identifier)
00059 {
00060
00061 if(currentFile != identifier)
00062 {
00063
00064 QFile f( identifier );
00065
00066 if ( f.open(QIODevice::ReadOnly) )
00067 {
00068
00069
00070
00071 QString errorMsg;
00072 int line, col;
00073 bool success=setContent(&f,&errorMsg,&line,&col);
00074
00075
00076 currentFile = identifier;
00077
00078
00079 f.close();
00080
00081 if (!success)
00082 {
00083 KMessageBox::error(QApplication::activeWindow(),i18n("<qt>The error <b>%4</b><br /> has been detected in the file %1 at %2/%3</qt>", identifier,
00084 line, col, i18nc("QXml",errorMsg.toUtf8())));
00085 return false;
00086 }
00087 }
00088 else
00089 {
00090
00091 KMessageBox::error(QApplication::activeWindow(), i18n("Unable to open %1", identifier) );
00092 return false;
00093 }
00094 }
00095 return true;
00096 }
00097
00101 bool KateSyntaxDocument::nextGroup( KateSyntaxContextData* data)
00102 {
00103 if(!data)
00104 return false;
00105
00106
00107 if (data->currentGroup.isNull())
00108 {
00109
00110 QDomNode node = data->parent.firstChild();
00111 while (node.isComment())
00112 node = node.nextSibling();
00113
00114 data->currentGroup = node.toElement();
00115 }
00116 else
00117 {
00118
00119 QDomNode node = data->currentGroup.nextSibling();
00120 while (node.isComment())
00121 node = node.nextSibling();
00122
00123 data->currentGroup = node.toElement();
00124 }
00125
00126 return !data->currentGroup.isNull();
00127 }
00128
00132 bool KateSyntaxDocument::nextItem( KateSyntaxContextData* data)
00133 {
00134 if(!data)
00135 return false;
00136
00137 if (data->item.isNull())
00138 {
00139 QDomNode node = data->currentGroup.firstChild();
00140 while (node.isComment())
00141 node = node.nextSibling();
00142
00143 data->item = node.toElement();
00144 }
00145 else
00146 {
00147 QDomNode node = data->item.nextSibling();
00148 while (node.isComment())
00149 node = node.nextSibling();
00150
00151 data->item = node.toElement();
00152 }
00153
00154 return !data->item.isNull();
00155 }
00156
00160 QString KateSyntaxDocument::groupItemData( const KateSyntaxContextData* data, const QString& name){
00161 if(!data)
00162 return QString();
00163
00164
00165 if ( (!data->item.isNull()) && (name.isEmpty()))
00166 {
00167 return data->item.tagName();
00168 }
00169
00170
00171 if (!data->item.isNull())
00172 {
00173 return data->item.attribute(name);
00174 }
00175
00176 return QString();
00177
00178 }
00179
00180 QString KateSyntaxDocument::groupData( const KateSyntaxContextData* data,const QString& name)
00181 {
00182 if(!data)
00183 return QString();
00184
00185 if (!data->currentGroup.isNull())
00186 {
00187 return data->currentGroup.attribute(name);
00188 }
00189 else
00190 {
00191 return QString();
00192 }
00193 }
00194
00195 void KateSyntaxDocument::freeGroupInfo( KateSyntaxContextData* data)
00196 {
00197 if (data)
00198 delete data;
00199 }
00200
00201 KateSyntaxContextData* KateSyntaxDocument::getSubItems(KateSyntaxContextData* data)
00202 {
00203 KateSyntaxContextData *retval = new KateSyntaxContextData;
00204
00205 if (data != 0)
00206 {
00207 retval->parent = data->currentGroup;
00208 retval->currentGroup = data->item;
00209 }
00210
00211 return retval;
00212 }
00213
00214 bool KateSyntaxDocument::getElement (QDomElement &element, const QString &mainGroupName, const QString &config)
00215 {
00216 #ifdef KSD_OVER_VERBOSE
00217 kDebug(13010) << "Looking for \"" << mainGroupName << "\" -> \"" << config << "\".";
00218 #endif
00219
00220 QDomNodeList nodes = documentElement().childNodes();
00221
00222
00223 for (int i=0; i<nodes.count(); i++)
00224 {
00225 QDomElement elem = nodes.item(i).toElement();
00226 if (elem.tagName() == mainGroupName)
00227 {
00228
00229 QDomNodeList subNodes = elem.childNodes();
00230
00231
00232 for (int j=0; j<subNodes.count(); j++)
00233 {
00234 QDomElement subElem = subNodes.item(j).toElement();
00235 if (subElem.tagName() == config)
00236 {
00237
00238 element = subElem;
00239 return true;
00240 }
00241 }
00242
00243 #ifdef KSD_OVER_VERBOSE
00244 kDebug(13010) << "WARNING: \""<< config <<"\" wasn't found!";
00245 #endif
00246
00247 return false;
00248 }
00249 }
00250
00251 #ifdef KSD_OVER_VERBOSE
00252 kDebug(13010) << "WARNING: \""<< mainGroupName <<"\" wasn't found!";
00253 #endif
00254
00255 return false;
00256 }
00257
00262 KateSyntaxContextData* KateSyntaxDocument::getConfig(const QString& mainGroupName, const QString &config)
00263 {
00264 QDomElement element;
00265 if (getElement(element, mainGroupName, config))
00266 {
00267 KateSyntaxContextData *data = new KateSyntaxContextData;
00268 data->item = element;
00269 return data;
00270 }
00271 return 0;
00272 }
00273
00278 KateSyntaxContextData* KateSyntaxDocument::getGroupInfo(const QString& mainGroupName, const QString &group)
00279 {
00280 QDomElement element;
00281 if (getElement(element, mainGroupName, group+'s'))
00282 {
00283 KateSyntaxContextData *data = new KateSyntaxContextData;
00284 data->parent = element;
00285 return data;
00286 }
00287 return 0;
00288 }
00289
00293 QStringList& KateSyntaxDocument::finddata(const QString& mainGroup, const QString& type, bool clearList)
00294 {
00295 #ifdef KSD_OVER_VERBOSE
00296 kDebug(13010)<<"Create a list of keywords \""<<type<<"\" from \""<<mainGroup<<"\".";
00297 #endif
00298
00299 if (clearList)
00300 m_data.clear();
00301
00302 for(QDomNode node = documentElement().firstChild(); !node.isNull(); node = node.nextSibling())
00303 {
00304 QDomElement elem = node.toElement();
00305 if (elem.tagName() == mainGroup)
00306 {
00307 #ifdef KSD_OVER_VERBOSE
00308 kDebug(13010)<<"\""<<mainGroup<<"\" found.";
00309 #endif
00310
00311 QDomNodeList nodelist1 = elem.elementsByTagName("list");
00312
00313 for (int l=0; l<nodelist1.count(); l++)
00314 {
00315 if (nodelist1.item(l).toElement().attribute("name") == type)
00316 {
00317 #ifdef KSD_OVER_VERBOSE
00318 kDebug(13010)<<"List with attribute name=\""<<type<<"\" found.";
00319 #endif
00320
00321 QDomNodeList childlist = nodelist1.item(l).toElement().childNodes();
00322
00323 for (int i=0; i<childlist.count(); i++)
00324 {
00325 QString element = childlist.item(i).toElement().text().trimmed();
00326 if (element.isEmpty())
00327 continue;
00328
00329 #ifdef KSD_OVER_VERBOSE
00330 if (i<6)
00331 {
00332 kDebug(13010)<<"\""<<element<<"\" added to the list \""<<type<<"\"";
00333 }
00334 else if(i==6)
00335 {
00336 kDebug(13010)<<"... The list continues ...";
00337 }
00338 #endif
00339
00340 m_data += element;
00341 }
00342
00343 break;
00344 }
00345 }
00346 break;
00347 }
00348 }
00349
00350 return m_data;
00351 }
00352
00353
00357 void KateSyntaxDocument::setupModeList (bool force)
00358 {
00359
00360 if (!myModeList.isEmpty())
00361 return;
00362
00363
00364 KConfigGroup generalConfig(m_config, "General");
00365
00366
00367 if (generalConfig.readEntry ("Version",0) > generalConfig.readEntry ("CachedVersion",0))
00368 {
00369 generalConfig.writeEntry ("CachedVersion", generalConfig.readEntry ("Version",0));
00370 force = true;
00371 }
00372
00373
00374 const QStringList list = KGlobal::dirs()->findAllResources("data","katepart/syntax/*.xml",
00375 KStandardDirs::NoDuplicates);
00376
00377
00378 for ( QStringList::ConstIterator it = list.begin(); it != list.end(); ++it )
00379 {
00380
00381 QString Group="Cache "+ *it;
00382
00383
00384 KConfigGroup config(m_config, Group);
00385
00386
00387 struct stat sbuf;
00388 memset (&sbuf, 0, sizeof(sbuf));
00389 stat(QFile::encodeName(*it), &sbuf);
00390
00391
00392 if (!force && config.exists() && (sbuf.st_mtime == config.readEntry("lastModified",0)))
00393 {
00394
00395 KateSyntaxModeListItem *mli=new KateSyntaxModeListItem;
00396 mli->name = config.readEntry("name");
00397 mli->nameTranslated = i18nc("Language",mli->name.toUtf8());
00398 mli->section = i18nc("Language Section",config.readEntry("section").toUtf8());
00399 mli->mimetype = config.readEntry("mimetype");
00400 mli->extension = config.readEntry("extension");
00401 mli->version = config.readEntry("version");
00402 mli->priority = config.readEntry("priority");
00403 mli->style = config.readEntry("style");
00404 mli->author = config.readEntry("author");
00405 mli->license = config.readEntry("license");
00406 mli->hidden = config.readEntry("hidden", false);
00407 mli->identifier = *it;
00408
00409
00410 myModeList.append(mli);
00411 }
00412 else
00413 {
00414 #ifdef KSD_OVER_VERBOSE
00415 kDebug (13010) << "UPDATE hl cache for: " << *it;
00416 #endif
00417
00418
00419 QFile f(*it);
00420
00421 if (f.open(QIODevice::ReadOnly))
00422 {
00423
00424
00425 QString errMsg;
00426 int line, col;
00427
00428 bool success = setContent(&f,&errMsg,&line,&col);
00429
00430 f.close();
00431
00432 if (success)
00433 {
00434 QDomElement root = documentElement();
00435
00436 if (!root.isNull())
00437 {
00438
00439 if (root.tagName()=="language")
00440 {
00441
00442 KateSyntaxModeListItem *mli = new KateSyntaxModeListItem;
00443
00444 mli->name = root.attribute("name");
00445 mli->section = root.attribute("section");
00446 mli->mimetype = root.attribute("mimetype");
00447 mli->extension = root.attribute("extensions");
00448 mli->version = root.attribute("version");
00449 mli->priority = root.attribute("priority");
00450 mli->style = root.attribute("style");
00451 mli->author = root.attribute("author");
00452 mli->license = root.attribute("license");
00453
00454 QString hidden = root.attribute("hidden");
00455 mli->hidden = (hidden == "true" || hidden == "TRUE");
00456
00457 mli->identifier = *it;
00458
00459
00460 config = KConfigGroup(m_config, Group);
00461 config.writeEntry("name",mli->name);
00462 config.writeEntry("section",mli->section);
00463 config.writeEntry("mimetype",mli->mimetype);
00464 config.writeEntry("extension",mli->extension);
00465 config.writeEntry("version",mli->version);
00466 config.writeEntry("priority",mli->priority);
00467 config.writeEntry("style",mli->style);
00468 config.writeEntry("author",mli->author);
00469 config.writeEntry("license",mli->license);
00470 config.writeEntry("hidden",mli->hidden);
00471
00472
00473 config.writeEntry("lastModified", int(sbuf.st_mtime));
00474
00475
00476 mli->section = i18nc("Language Section",mli->section.toUtf8());
00477 mli->nameTranslated = i18nc("Language",mli->name.toUtf8());
00478
00479
00480 myModeList.append(mli);
00481 }
00482 }
00483 }
00484 else
00485 {
00486 KateSyntaxModeListItem *emli=new KateSyntaxModeListItem;
00487
00488 emli->section=i18n("Errors!");
00489 emli->mimetype="invalid_file/invalid_file";
00490 emli->extension="invalid_file.invalid_file";
00491 emli->version="1.";
00492 emli->name=QString ("Error: %1").arg(*it);
00493 emli->nameTranslated=i18n("Error: %1", *it);
00494 emli->identifier=(*it);
00495
00496 myModeList.append(emli);
00497 }
00498 }
00499 }
00500 }
00501
00502
00503 generalConfig.sync();
00504 }
00505
00506