Из научно-спортивного интереса осваиваю Qt и QsciScintilla в частности. Решил разработать подсветку синтаксиса для виртуального языка. И сразу возникла проблема следующего характера: если в качестве лексера для QsciScintilla указать собственный (производный от QsciLexerCustom), то подсветка синтаксиса при вводе кириллицы превращается в абсурд, если же использовать готовый, например QsciLexerCPP, то все стилизируется корректно.
#ifndef GMLSCILEXER_H
#define GMLSCILEXER_H
#include <QObject>
#include <Qsci/qsciscintilla.h>
#include <Qsci/qscilexercustom.h>
#include <QColor>
#include <QFont>
class GMLsciLexer : public QsciLexerCustom
{
Q_OBJECT
public:
explicit GMLsciLexer(QObject *parent = 0);
private:
//! Возвращает название языка
virtual const char * language() const;
//! Цвета для стилей
virtual QColor defaultColor(int style) const;
//! Шрифты для стилей
virtual QFont defaultFont(int style) const;
//! Бакгроунд для стилей
virtual QColor defaultPaper(int style) const;
//! Разбор текста на стили
virtual void styleText (int start, int end);
//! Описание
virtual QString description (int style) const;
//! Подстветить комментарии
bool comments (QString source, int start, int end);
enum
{
Default = 0,
Comment = 1,
Binary = 2,
String = 3,
Keyword1 = 4,
Keyword2 = 5,
Keyword3 = 6,
Keyword4 = 7,
Const = 8
};
signals:
public slots:
};
#endif // GMLSCILEXER_H
#include "gmlscilexer.h"
GMLsciLexer::GMLsciLexer(QObject *parent) :
QsciLexerCustom(parent)
{
}
const char * GMLsciLexer::language() const
{
return "GML";
}
QColor GMLsciLexer::defaultColor(int style) const
{
if (style == Comment)
{
return QColor(0x00,0x7f,0x00);
}
return QsciLexer::defaultColor(style);
}
QFont GMLsciLexer::defaultFont(int style) const
{
QFont f;
if (style == Comment)
{
#if defined(Q_OS_WIN)
f.setFamily("Comic Sans");
#else
f.setFamily("Sans Serif");
#endif
f.setItalic(true);
}
else
{
f = QsciLexer::defaultFont(style);
}
return f;
}
QColor GMLsciLexer::defaultPaper(int style) const
{
if (style == Comment)
{
return QColor(0xff,0xff,0xff);
}
return QsciLexer::defaultPaper(style);
}
void GMLsciLexer::styleText(int start, int end)
{
//editor() - функция из родительского класса.
//Возвращает указатель на QsciScintilla
if (!editor())
return;
QsciScintilla * editor = this->editor();
QString source = editor->text();
comments(source, start, end);
}
QString GMLsciLexer::description (int style) const
{
switch (style)
{
case Comment:
return "Comment";
case Default:
return "Default";
}
return QString(style);
}
bool GMLsciLexer::comments(QString source, int start, int end)
{
int count = source.count("//");
int style = Comment;
int idxStart = start;
int idxEnd = idxStart;
//Обрабатываем каждый символ комментария
for (int i = 0; i < count; i++)
{
idxStart = source.indexOf("//", idxStart);
if (idxStart == -1)
break;
#if defined(Q_WS_X11)
int pos = source.indexOf("\r\n", idxStart);
#elif defined(Q_WS_WIN)
int pos = source.indexOf("\n", idxStart);
#endif
if (pos != -1)
{
idxEnd = pos;
}
else
{
idxEnd = idxStart + source.mid(idxStart).size();
}
//Здесь мы сообщаем, что начинаем новый стиль
//с позиции start + idxStart
startStyling(idxStart);
int len = idxEnd - idxStart;
//А здесь мы сообщаем, что начиная от текущей позиции, определенной startStyling,
//дальше последуют len символов стиля style == Comment
setStyling(len, style);
//Заканчиваем отрисовку стиля
startStyling(idxEnd);
idxStart = idxEnd;
}
}