00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
#include "cpp_colorizer.h"
00025
#include "qeditor_part.h"
00026
#include "paragdata.h"
00027
00028
#include <qfont.h>
00029
#include <private/qrichtext_p.h>
00030
00031
#include <qdom.h>
00032
#include <qfile.h>
00033
00034
#include <kapplication.h>
00035
#include <kdebug.h>
00036
#include <kconfig.h>
00037
#include <kstandarddirs.h>
00038
00039
00040 static const char *
cpp_keywords[] = {
00041
"break",
"case",
"continue",
"default",
"do",
"else",
"enum",
"extern",
00042
"for",
"goto",
"if",
"return",
"sizeof",
"struct",
00043
"switch",
"typedef",
"union",
"while",
00044
"auto",
"char",
"uchar",
"const",
"double",
"float",
"int",
"uint",
"long",
"register",
00045
"short",
"signed",
"static",
"unsigned",
"void",
"volatile",
00046
"asm",
"catch",
"class",
"const_cast",
"const",
"delete",
"dynamic_cast",
00047
"explicit",
"export",
"false",
"friend",
"inline",
"namespace",
"new",
00048
"operator",
"private",
"protected",
"public",
"reinterpret_cast",
00049
"static_cast",
"template",
"this",
"throw",
"true",
"try",
"typeid",
00050
"typename",
"using",
"virtual",
00051
"and_eq",
"and",
"bitand",
"bitor",
"compl",
"not_eq",
"not",
"or_eq",
"or",
00052
"xor_eq",
"xor",
00053
"slots",
"signals",
00054
"bool",
"wchar_t",
"mutable",
00055 0
00056 };
00057
00058 class CppPreprocHLItem:
public HLItem{
00059
public:
00060 CppPreprocHLItem(
int state,
int context )
00061 :
HLItem( state, context ) {}
00062
00063 int checkHL(
const QChar* buffer,
int pos,
int length,
int*,
int* ){
00064
00065
int start_pos = pos;
00066
00067
while( (pos<
length) && buffer[pos].isSpace() )
00068 ++pos;
00069
00070
if( (pos <
length) && buffer[pos] ==
'#' )
00071
return pos + 1;
00072
00073
return start_pos;
00074 }
00075 };
00076
00077 class CppPreprocLineHLItem:
public HLItem{
00078
public:
00079 CppPreprocLineHLItem(
int state,
int context )
00080 :
HLItem( state, context ) {}
00081
00082 int checkHL(
const QChar* buffer,
int pos,
int length,
int*,
int* ){
00083
00084
int end_pos =
length - 1;
00085
00086
while( (end_pos>=0) && buffer[end_pos].isSpace() )
00087 --end_pos;
00088
00089
if( (end_pos >= 0) && buffer[end_pos] ==
'\\' )
00090
return length;
00091
00092
return pos;
00093 }
00094 };
00095
00096
using namespace std;
00097
00098 CppColorizer::CppColorizer(
QEditor* editor )
00099 :
QSourceColorizer( editor )
00100 {
00101
loadDynamicKeywords();
00102
00103
00104
HLItemCollection* context0 =
new HLItemCollection( 0 );
00105 context0->
appendChild(
new CppPreprocHLItem( PreProcessor, 4 ) );
00106 context0->
appendChild(
new WhiteSpacesHLItem( Normal, 0 ) );
00107 context0->
appendChild(
new StringHLItem(
"'", String, 1 ) );
00108 context0->
appendChild(
new StringHLItem(
"\"", String, 2 ) );
00109 context0->
appendChild(
new StringHLItem(
"/*", Comment, 3 ) );
00110 context0->
appendChild(
new StartsWithHLItem(
"//", Comment, 0 ) );
00111 context0->
appendChild(
new HexHLItem( Constant, 0 ) );
00112 context0->
appendChild(
new NumberHLItem( Constant, 0 ) );
00113 context0->
appendChild(
new KeywordsHLItem(
m_dynamicKeywords, BuiltInClass, Normal, 0,
false ) );
00114 context0->
appendChild(
new KeywordsHLItem(
cpp_keywords, Keyword, Normal, 0 ) );
00115
00116 HLItemCollection* context1 =
new HLItemCollection( String );
00117 context1->
appendChild(
new StringHLItem(
"\\\\", String, 1 ) );
00118 context1->
appendChild(
new StringHLItem(
"\\'", String, 1 ) );
00119 context1->
appendChild(
new StringHLItem(
"'", String, 0 ) );
00120
00121 HLItemCollection* context2 =
new HLItemCollection( String );
00122 context2->
appendChild(
new StringHLItem(
"\\\\", String, 2 ) );
00123 context2->
appendChild(
new StringHLItem(
"\\\"", String, 2 ) );
00124 context2->
appendChild(
new StringHLItem(
"\"", String, 0 ) );
00125
00126 HLItemCollection* context3 =
new HLItemCollection( Comment );
00127 context3->
appendChild(
new StringHLItem(
"*/", Comment, 0 ) );
00128
00129 HLItemCollection* context4 =
new HLItemCollection( PreProcessor );
00130 context4->
appendChild(
new CppPreprocLineHLItem( PreProcessor, 4 ) );
00131 context4->
appendChild(
new StartsWithHLItem(
"", PreProcessor, 0 ) );
00132
00133
00134 m_items.append( context0 );
00135 m_items.append( context1 );
00136 m_items.append( context2 );
00137 m_items.append( context3 );
00138 m_items.append( context4 );
00139 }
00140
00141 CppColorizer::~CppColorizer()
00142 {
00143 }
00144
00145 void CppColorizer::loadDynamicKeywords()
00146 {
00147
QString strFileNameTag(
"name" );
00148
QString strClassNameTag(
"name" );
00149
00150
m_dynamicKeywords.clear();
00151
00152
QString hlFileDir =
KGlobal::dirs()->
findResourceDir(
"data",
"qeditorpart/highlight/highlighting.xml" );
00153
00154 hlFileDir +=
"qeditorpart/highlight/";
00155
00156
00157
00158
if( hlFileDir.isNull() )
00159
return;
00160
00161
QDomDocument hlFile(
"hlfile" ), curDoc (
"classlist" );
00162
QFile hlRawFile( hlFileDir +
"highlighting.xml" );
00163
int keywordIndex = 0;
00164
if( !hlRawFile.open( IO_ReadOnly ) )
00165
return;
00166
if( !hlFile.setContent( &hlRawFile ) ) {
00167 hlRawFile.close();
00168
return;
00169 }
00170 hlRawFile.close();
00171
00172
QDomElement e = hlFile.documentElement();
00173
QDomNode n = e.firstChild();
00174
while( !n.isNull() ) {
00175 e = n.toElement();
00176
if( !e.isNull() ) {
00177
00178
00179
00180
QFile clsRawFile( hlFileDir + e.attribute( strFileNameTag ) );
00181
if( clsRawFile.open( IO_ReadOnly ) && curDoc.setContent( &clsRawFile ) ) {
00182
00183
QDomElement e = curDoc.documentElement();
00184
QDomNode n = e.firstChild();
00185
while( !n.isNull() ) {
00186 e = n.toElement();
00187
if( !e.isNull()) {
00188
00189
m_dynamicKeywords.insert( e.attribute( strClassNameTag ), keywordIndex++ );
00190 }
00191 n = n.nextSibling();
00192 }
00193
00194 }
00195 clsRawFile.close();
00196 }
00197 n = n.nextSibling();
00198 }
00199 }
00200
00201 int CppColorizer::computeLevel( QTextParagraph* parag,
int startLevel )
00202 {
00203
int level = startLevel;
00204
00205
ParagData* data = (
ParagData*) parag->extraData();
00206
if( !data ){
00207
return startLevel;
00208 }
00209
00210 data->
setBlockStart(
false );
00211
00212
QValueList<Symbol> symbols = data->
symbolList();
00213
QValueList<Symbol>::Iterator it = symbols.begin();
00214
while( it != symbols.end() ){
00215
Symbol sym = *it++;
00216
if( sym.
ch() ==
'{' ){
00217 ++level;
00218 }
else if( sym.
ch() ==
'}' ){
00219 --level;
00220 }
00221 }
00222
00223
if( level > startLevel ){
00224 data->
setBlockStart(
true );
00225 }
00226
00227
return level;
00228 }
00229