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