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