Logo Search packages:      
Sourcecode: qtoctave version File versions  Download package

syntax.cpp

/* Copyright (C) 2006 P.L. Lucas
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, 
 * Boston, MA 02111-1307, USA. 
 */

#include "syntax.h"
#include <iostream>
#include <QtXml/QXmlSimpleReader>
#include <QtXml/QXmlDefaultHandler>

QMap<QString, QVector<Syntax::Rule> > Syntax::instances;

/*** Xml Handler ***/
class SyntaxXmlHandler:public QXmlDefaultHandler
{
private:
  Syntax *syntax;
  QString type_name;
  bool wait_item;
public:
  // Constructor
  SyntaxXmlHandler(Syntax *s): QXmlDefaultHandler(), syntax(s) {};


  bool startElement(const QString &namespaceURI, const QString &localName,
                const QString &qname, const QXmlAttributes &atts)
  {
    if(qname == "list")
      // List block. Get the type name.
      type_name = atts.value("name").trimmed();
    else if(qname == "item")
      // Item. Next string is an item.
      wait_item = true;      
    else if(qname == "comment"){
      // Comments.
      syntax->setComment(atts.value("start"), "$", atts.value("name"));
    }

    return true;
  }


  bool characters(const QString &ch)
  {
    // We are waiting for an item
    if(wait_item)
    {
      if(ch[0] == ' ')
      syntax->setItem(QString("\\b") + ch.trimmed() + "\\b", type_name);
      else
      syntax->setItem(ch.trimmed(), type_name);
      wait_item = false;
    }

    return true;
  }
};

/*** Syntax ***/

Syntax::Syntax(QTextEdit *parent): QSyntaxHighlighter(parent)
{
  QTextCharFormat f;

  f.setFontWeight(QFont::Bold);
  format["keywords"] = f;
  format["commands"] = f;
  f.setFontWeight(QFont::Normal);
  f.setForeground(Qt::darkGreen);
  format["builtin"] = f;
  f.setForeground(Qt::blue);
  format["functions"] = f;
  // operators
  f.setForeground(Qt::darkBlue);
  format["variables"] = f;
  f.setForeground(Qt::darkMagenta);
  format["numbers"] = f;
  f.setForeground(Qt::red);
  format["strings"] = f;
  // delimiters
  f.setForeground(Qt::darkGray);
  format["singleLine"] = f;
}

void Syntax::load(const QString &path)
{
  rules = &(instances[path]);
  if(rules->empty())
  {
    // Load from file
    FILE *fl;

    fl = fopen(path.toLocal8Bit().constData(), "rt");
    if(!fl)
    {
      std::cerr << "[Syntax::load] Can not load the syntax file" << std::endl;
      return;
    }
    
    QFile file(path);
    QXmlSimpleReader parser;
    QXmlInputSource source(&file);
    SyntaxXmlHandler handler(this);

    file.open(fl, QIODevice::ReadOnly);
    
    parser.setContentHandler(&handler);
    parser.setErrorHandler(&handler);

    parser.parse(&source);
    
    file.close();
    
    fclose(fl);
    
    std::cout << "[Sytax::load] "
            << path.toLocal8Bit().constData()
            << " loaded"
            << std::endl;
  }
}

void Syntax::setItem(const QString &item, const QString &type)
{
  Rule r;
  if(!item.isEmpty())
  {
    r.pattern = QRegExp(item);
    r.type = type;
    r.format = format[type];
    rules->push_back(r);
  }
}

void Syntax::setComment(const QString &start, const QString &end, const QString &type)
{
  Rule r;
  if(!start.isEmpty())
  {
    r.pattern = QRegExp(QString("^") + start + ".*" + end);
    r.type = type;
    r.format = format[type];
    rules->push_back(r);
  }
}

void Syntax::setType(const QString &type, const QTextCharFormat &f)
{
  format[type] = f;
}

void Syntax::highlightBlock(const QString &str)
{
  int i, len;

  foreach(Rule rule, *rules)
  {
    i = str.indexOf(rule.pattern);
    while(i >= 0)
    {
      len = rule.pattern.matchedLength();
      setFormat(i, len, rule.format);
      i = str.indexOf(rule.pattern, i + len);
    }
  }
}



Generated by  Doxygen 1.6.0   Back to index