KDevelop API Documentation

qeditor.cpp

Go to the documentation of this file.
00001 /* $Id: qeditor.cpp,v 1.44 2003/08/27 00:52:26 raggi Exp $
00002  *
00003  *  This file is part of Klint
00004  *  Copyright (C) 2002 Roberto Raggi (roberto@kdevelop.org)
00005  *
00006  *  This program is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU General Public
00008  *  License as published by the Free Software Foundation; either
00009  *  version 2 of the License, or (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  *  General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; see the file COPYING.  If not, write to
00018  *  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019  *  Boston, MA 02111-1307, USA.
00020  *
00021  */
00022 
00023 /**********************************************************************
00024 ** Copyright (C) 2000 Trolltech AS.  All rights reserved.
00025 **
00026 ** This file is part of Qt Designer.
00027 **
00028 ** This file may be distributed and/or modified under the terms of the
00029 ** GNU General Public License version 2 as published by the Free Software
00030 ** Foundation and appearing in the file COPYING included in the
00031 ** packaging of this file.
00032 **
00033 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00034 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00035 **
00036 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00037 **
00038 ** Contact info@trolltech.com if any conditions of this licensing are
00039 ** not clear to you.
00040 **
00041 **********************************************************************/
00042 
00043 #include "qeditor.h"
00044 #include "qeditor_settings.h"
00045 
00046 #include "qsourcecolorizer.h"
00047 #include "cpp_colorizer.h"
00048 #include "java_colorizer.h"
00049 #include "js_colorizer.h"
00050 #include "jsp_colorizer.h"
00051 #include "python_colorizer.h"
00052 #include "xml_colorizer.h"
00053 #include "qmake_colorizer.h"
00054 #include "cs_colorizer.h"
00055 #include "ocaml_colorizer.h"
00056 #include "pascal_colorizer.h"
00057 #include "ada_colorizer.h"
00058 #include "sql_colorizer.h"
00059 
00060 #if defined(HAVE_PERL_MODE)
00061 #  include "perl_colorizer.h"
00062 #endif
00063 
00064 #include "qeditor_indenter.h"
00065 #include "simple_indent.h"
00066 #include "python_indent.h"
00067 #include "cindent.h"
00068 #include "pascal_indent.h"
00069 #include "ada_indent.h"
00070 
00071 #include "parenmatcher.h"
00072 #include "paragdata.h"
00073 
00074 #include <private/qrichtext_p.h>
00075 #include <qregexp.h>
00076 #include <qmap.h>
00077 #include <qpopupmenu.h>
00078 
00079 #include <kdebug.h>
00080 #include <klocale.h>
00081 
00082 using namespace std;
00083 
00084 int QEditor::backspace_indentation( const QString &s )
00085 {
00086     int tabwidth = tabStop();
00087     int i = 0;
00088     int ind = 0;
00089     while ( i < (int)s.length() ) {
00090     QChar c = s.at( i );
00091     if ( c == ' ' ){
00092         ind++;
00093     } else if ( c == '\t' ){
00094         ind += tabwidth;
00095     } else {
00096         break;
00097     }
00098     ++i;
00099     }
00100     return ind;
00101 }
00102 
00103 
00104 int QEditor::backspace_indentForLine( int line )
00105 {
00106 //unused    int tabwidth = tabStop();
00107     int line_ind = backspace_indentation( text(line) );
00108     line_ind = line_ind > 0 ? line_ind-1 : 0;
00109     int ind = 0;
00110 
00111     --line;
00112     while( line>=0 ){
00113         QString raw_text = text( line );
00114     QString lineText = raw_text.stripWhiteSpace();
00115     if( !lineText.isEmpty() ){
00116         int new_ind = backspace_indentation( raw_text );
00117         if( new_ind < line_ind ){
00118         ind = new_ind;
00119         break;
00120         }
00121     }
00122     --line;
00123     }
00124     return ind;
00125 }
00126 
00127 struct QEditorKey{
00128     int key;
00129     int ascii;
00130     int state;
00131     QString text;
00132     bool autorep;
00133     ushort count;
00134 };
00135 
00136 QEditor::QEditor( QWidget* parent, const char* name )
00137     : KTextEdit( parent, name )
00138 {
00139     document()->setUseFormatCollection( FALSE );
00140 
00141     parenMatcher = new ParenMatcher();
00142 
00143     m_tabIndent = TRUE;
00144     m_backspaceIndent = TRUE;
00145     m_currentLine = -1;
00146     m_tabStop = 8;
00147     m_applicationMenu = 0;
00148     m_recording = FALSE;
00149     m_keys.setAutoDelete( TRUE );
00150 
00151     document()->addSelection( ParenMatcher::Match );
00152     document()->addSelection( ParenMatcher::Mismatch );
00153     document()->setSelectionColor( ParenMatcher::Match, QColor( 204, 232, 195 ) );
00154     document()->setSelectionColor( ParenMatcher::Mismatch, Qt::magenta );
00155     document()->setInvertSelectionText( ParenMatcher::Match, FALSE );
00156     document()->setInvertSelectionText( ParenMatcher::Mismatch, FALSE );
00157 
00158     document()->addSelection( 1000 );
00159     document()->setSelectionColor( 1000, QColor( 204, 232, 195 ) );
00160 
00161     connect( this, SIGNAL(cursorPositionChanged(QTextCursor*) ),
00162          this, SLOT(doMatch(QTextCursor*)) );
00163 //    connect( this, SIGNAL(cursorPositionChanged(int, int) ),
00164 //       this, SLOT(slotCursorPositionChanged(int, int)) );
00165 }
00166 
00167 QEditor::~QEditor()
00168 {
00169     m_keys.clear();
00170     delete( parenMatcher );
00171 }
00172 
00173 QPopupMenu* QEditor::createPopupMenu( const QPoint& pt )
00174 {
00175     QPopupMenu* menu = KTextEdit::createPopupMenu( pt );
00176     if( m_applicationMenu ){
00177     menu->insertSeparator();
00178     menu->insertItem( i18n("&Application"), m_applicationMenu );
00179     }
00180     return menu;
00181 }
00182 
00183 
00184 int QEditor::tabStop() const
00185 {
00186     return m_tabStop;
00187 }
00188 
00189 void QEditor::setTabStop( int tabStop )
00190 {
00191     m_tabStop = tabStop;
00192     if( m_tabStop == 0 )
00193         m_tabStop = 8;
00194 }
00195 
00196 void QEditor::keyPressEvent( QKeyEvent* e )
00197 {
00198     //kdDebug(9032) << "QEditor::keyPressEvent()" << endl;
00199     if( e->key() == Key_Tab ){
00200     if( tabIndentEnabled() ){
00201         int line, col;
00202         getCursorPosition( &line, &col );
00203         QString s = text( line );
00204         if( hasSelectedText() || s.stripWhiteSpace().isEmpty() || !s.mid( col ).stripWhiteSpace().isEmpty() )
00205         indent();
00206         else
00207         insert( "\t" );
00208     } else
00209         insert( "\t" );
00210     e->accept();
00211     } else if( m_electricKeys.contains( e->ascii() ) ){
00212     insert( e->text(), FALSE );
00213         indent();
00214     e->accept();
00215     } else if( e->ascii() == '{' || e->ascii() == '}' ||
00216                e->ascii() == ':' || e->ascii() == '#' ){
00217     insert( e->text(), FALSE );
00218     e->accept();
00219     } else if (e->state() == Qt::ControlButton) {
00220     bool bRemove = false;
00221         switch (e->key()) {
00222         case Qt::Key_Backspace:
00223         bRemove = true;
00224         if (!hasSelectedText()) {
00225         removeSelection();
00226         }
00227     case Qt::Key_Left: {
00228         QTextCursor* cur = textCursor();
00229         if (cur->index() < 1) {
00230         moveCursor( MoveBackward, bRemove ); break;
00231         }
00232         QChar c(cur->paragraph()->at(cur->index()-1)->c);
00233         bool firstMove = true; // make sure we do move
00234         if (c.isSpace()) {
00235         while (cur->index() > 0 && (cur->paragraph()->at(cur->index()-1)->c.isSpace() || firstMove)) {
00236             moveCursor( MoveBackward, bRemove ); firstMove = false; cur = textCursor();
00237         }
00238         }
00239         else if (isDelimiter(c)) {
00240         while (cur->index() > 0 && (isDelimiter(cur->paragraph()->at(cur->index()-1)->c) || firstMove)) {
00241             moveCursor( MoveBackward, bRemove ); firstMove = false; cur = textCursor();
00242         }
00243         }
00244         else if (!isDelimiter(c)) {
00245         while (cur->index() > 0 && (!isDelimiter(cur->paragraph()->at(cur->index()-1)->c) || firstMove)) {
00246             moveCursor( MoveBackward, bRemove ); firstMove = false; cur = textCursor();
00247         }
00248         }
00249         }
00250         break;
00251         case Qt::Key_Delete:
00252         bRemove = true;
00253         if (!hasSelectedText()) {
00254         removeSelection();
00255         }
00256     case Qt::Key_Right: {
00257         QTextCursor* cur = textCursor();
00258         if (cur->atParagEnd()) {
00259         moveCursor( MoveForward, bRemove ); break;
00260         }
00261         QChar c(cur->paragraph()->at(cur->index())->c);
00262         bool firstMove = true; // make sure we do move
00263         if (c.isSpace()) {
00264         while (!cur->atParagEnd() && (cur->paragraph()->at(cur->index())->c.isSpace() || firstMove)) {
00265             moveCursor( MoveForward, bRemove ); firstMove = false; cur = textCursor();
00266         }
00267         }
00268         else if (!isDelimiter(c)) {
00269         while (!cur->atParagEnd() && (!isDelimiter(cur->paragraph()->at(cur->index())->c) || firstMove)) {
00270             moveCursor( MoveForward, bRemove ); firstMove = false; cur = textCursor();
00271         }
00272         }
00273         else if (isDelimiter(c)) {
00274         while (!cur->atParagEnd() && (isDelimiter(cur->paragraph()->at(cur->index())->c) || firstMove)) {
00275             moveCursor( MoveForward, bRemove ); firstMove = false; cur = textCursor();
00276         }
00277         }
00278         }
00279         break;
00280         default:
00281         KTextEdit::keyPressEvent( e );
00282         break;
00283         }
00284     if (bRemove) {
00285         removeSelectedText();
00286         }
00287     }
00288     else if( e->key() == Key_Backspace ){
00289     if( backspaceIndentEnabled() ){
00290         backspaceIndent( e );
00291     } else {
00292         KTextEdit::keyPressEvent( e );
00293     }
00294     } else {
00295     KTextEdit::keyPressEvent( e );
00296     }
00297 }
00298 
00299 void QEditor::doMatch( QTextCursor* c )
00300 {
00301     if( parenMatcher->match(c) ){
00302     repaintChanged();
00303     }
00304 }
00305 
00306 void QEditor::doGotoLine( int line )
00307 {
00308     setCursorPosition( line, 0 );
00309     QTextParagraph *p = document()->paragAt( line );
00310     if ( !p )
00311     return;
00312     QTextCursor c( document() );
00313     emit ensureTextIsVisible( p );
00314     c.setParagraph( p );
00315     c.setIndex( 0 );
00316     document()->removeSelection( 1000 );
00317     document()->setSelectionStart( 1000, c );
00318     c.gotoLineEnd();
00319     document()->setSelectionEnd( 1000, c );
00320     viewport()->repaint( FALSE );
00321 }
00322 
00323 QTextCursor* QEditor::textCursor() const
00324 {
00325     return KTextEdit::textCursor();
00326 }
00327 
00328 QTextDocument* QEditor::document() const
00329 {
00330     return KTextEdit::document();
00331 }
00332 
00333 void QEditor::drawCursor( bool visible )
00334 {
00335     KTextEdit::drawCursor( visible );
00336 }
00337 
00338 void QEditor::configChanged()
00339 {
00340     updateStyles();
00341 
00342     if( QEditorSettings::self()->wordWrap() ){
00343     setWordWrap( QEditor::WidgetWidth );
00344     setHScrollBarMode( QScrollView::AlwaysOff );
00345     setVScrollBarMode( QScrollView::AlwaysOn );
00346     } else {
00347     setWordWrap( QEditor::NoWrap );
00348     setHScrollBarMode( QScrollView::AlwaysOn );
00349     setVScrollBarMode( QScrollView::AlwaysOn );
00350     }
00351 
00352     refresh();
00353 }
00354 
00355 void QEditor::zoomIn()
00356 {
00357     KTextEdit::zoomIn();
00358     updateStyles();
00359     refresh();
00360 }
00361 
00362 void QEditor::zoomOut()
00363 {
00364     KTextEdit::zoomOut();
00365     updateStyles();
00366     refresh();
00367 }
00368 
00369 void QEditor::updateStyles()
00370 {
00371     //kdDebug(9032) << "QEditor::updateStyles()" << endl;
00372     int tabwidth = tabStop();
00373     QSourceColorizer* colorizer = dynamic_cast<QSourceColorizer*>( document()->preProcessor() );
00374     if( colorizer ){
00375     setFont( colorizer->format( 0 )->font() );
00376     setTabStopWidth( colorizer->format(0)->width('x') * tabwidth );
00377     document()->setTabStops( colorizer->format(0)->width('x') * tabwidth );
00378     }
00379     KTextEdit::updateStyles();
00380 }
00381 
00382 void QEditor::backspaceIndent( QKeyEvent* e )
00383 {
00384     QTextCursor* c = textCursor();
00385     QTextParagraph* p = c->paragraph();
00386     QString raw_text = text( p->paragId() );
00387     QString line = raw_text.stripWhiteSpace();
00388 
00389     if( raw_text.left(c->index()).stripWhiteSpace().isEmpty()
00390     && c->index() > 0 && !hasSelectedText() ){
00391         drawCursor( FALSE );
00392         int oi = backspace_indentation( raw_text );
00393         int ni = backspace_indentForLine( p->paragId() );
00394 
00395         if( indenter() )
00396           indenter()->indentLine( p, oi, ni );
00397 
00398         int idx = c->index();
00399         if ( idx >= oi )
00400         idx += ni - oi;
00401         else
00402         idx = ni;
00403         c->setIndex( idx );
00404         repaintChanged();
00405         drawCursor( TRUE );
00406         e->accept();
00407     } else {
00408         // doKeyboardAction( KTextEdit::ActionBackspace );
00409         KTextEdit::keyPressEvent( e );
00410     }
00411     }
00412 
00413 bool QEditor::replace( const QString &text, const QString &replace,
00414                bool cs, bool wo, bool forward, bool startAtCursor,
00415                bool replaceAll )
00416 {
00417     // from trolltech's editor sources -- START
00418     bool ok = FALSE;
00419     if ( startAtCursor ) {
00420     ok = find( text, cs, wo, forward );
00421     } else {
00422     int dummy = 0;
00423     ok =  find( text, cs, wo, forward, &dummy, &dummy );
00424     }
00425 
00426     if ( ok ) {
00427     removeSelectedText();
00428     insert( replace, FALSE, FALSE );
00429     }
00430 
00431     if ( !replaceAll || !ok ) {
00432     if ( ok )
00433         setSelection( textCursor()->paragraph()->paragId(),
00434               textCursor()->index() - replace.length(),
00435               textCursor()->paragraph()->paragId(),
00436               textCursor()->index() );
00437     return ok;
00438     }
00439 
00440     bool ok2 = TRUE;
00441     while ( ok2 ) {
00442     ok2 = find( text, cs, wo, forward );
00443     if ( ok2 ) {
00444         removeSelectedText();
00445         insert( replace, FALSE, FALSE );
00446     }
00447     }
00448 
00449     return TRUE;
00450     // from trolltech's editor sources -- END
00451 }
00452 
00453 void QEditor::setDocument( QTextDocument* doc )
00454 {
00455     KTextEdit::setDocument( doc );
00456 }
00457 
00458 void QEditor::repaintChanged()
00459 {
00460     KTextEdit::repaintChanged();
00461 }
00462 
00463 QString QEditor::textLine( uint line ) const
00464 {
00465     return text( line );
00466 }
00467 
00468 void QEditor::setLanguage( const QString& l )
00469 {
00470     kdDebug(9032) << "QEditor::setLanguage(" << l << ")" << endl;
00471     m_language = l;
00472     if( m_language == "c++" ){
00473         setElectricKeys( "{}" );
00474     document()->setPreProcessor( new CppColorizer(this) );
00475     document()->setIndent( new CIndent(this) );
00476     } else if( m_language == "java" ){
00477         setElectricKeys( "{}" );
00478     document()->setPreProcessor( new JavaColorizer(this) );
00479     document()->setIndent( new CIndent(this) );
00480     } else if( m_language == "javascript" ){
00481         setElectricKeys( "{}" );
00482     document()->setPreProcessor( new JSColorizer(this) );
00483     document()->setIndent( new CIndent(this) );
00484     } else if( m_language == "jsp" ){
00485         setElectricKeys( QString::null );
00486     document()->setPreProcessor( new JspColorizer(this) );
00487     document()->setIndent( new SimpleIndent(this) );
00488     } else if( m_language == "csharp" ){
00489         setElectricKeys( "{}" );
00490     document()->setPreProcessor( new CSharpColorizer(this) );
00491     document()->setIndent( new CIndent(this) );
00492 #if defined(HAVE_PERL_MODE)
00493     } else if( m_language == "perl" ){
00494         setElectricKeys( "{}" );
00495     document()->setPreProcessor( new PerlColorizer(this) );
00496     document()->setIndent( new CIndent(this) );
00497 #endif
00498     } else if( m_language == "python" ){
00499         setElectricKeys( QString::null );
00500     document()->setPreProcessor( new PythonColorizer(this) );
00501     document()->setIndent( new PythonIndent(this) );
00502     } else if( m_language == "xml" ){
00503         setElectricKeys( QString::null );
00504     document()->setPreProcessor( new XMLColorizer(this) );
00505     document()->setIndent( new SimpleIndent(this) );
00506     } else if( m_language == "qmake" ){
00507         setElectricKeys( QString::null );
00508     document()->setPreProcessor( new QMakeColorizer(this) );
00509     document()->setIndent( new SimpleIndent(this) );
00510     } else if( m_language == "ocaml" ){
00511         setElectricKeys( QString::null );
00512     document()->setPreProcessor( new OCamlColorizer(this) );
00513     document()->setIndent( new SimpleIndent(this) );
00514     } else if( m_language == "pascal" ){
00515         setElectricKeys( QString::null );
00516     document()->setPreProcessor( new PascalColorizer(this) );
00517     document()->setIndent( new PascalIndent(this) );
00518     } else if( m_language == "ada" ){
00519         setElectricKeys( QString::null );
00520     document()->setPreProcessor( new AdaColorizer(this) );
00521     document()->setIndent( new AdaIndent(this) );
00522     } else if( m_language == "sql" ){
00523     setElectricKeys( QString::null );
00524     document()->setPreProcessor( new SqlColorizer(this) );
00525     document()->setIndent( new SimpleIndent(this) );
00526     } else {
00527         setElectricKeys( QString::null );
00528     document()->setPreProcessor( 0 );
00529     document()->setIndent( new SimpleIndent(this) );
00530     }
00531 
00532     configChanged();
00533     sync();
00534 }
00535 
00536 QString QEditor::language() const
00537 {
00538     return m_language;
00539 }
00540 
00541 void QEditor::setText( const QString& text )
00542 {
00543     setTextFormat( KTextEdit::PlainText );
00544     QString s = text;
00545     // tabify( s );
00546     KTextEdit::setText( s );
00547     setTextFormat( KTextEdit::AutoText );
00548 }
00549 
00550 void QEditor::slotCursorPositionChanged( int line, int column )
00551 {
00552     Q_UNUSED( line );
00553     Q_UNUSED( column );
00554 }
00555 
00556 int QEditor::level( int line) const
00557 {
00558     ParagData* data = (ParagData*) document()->paragAt( line )->extraData();
00559     if( data ){
00560     return data->level();
00561     }
00562     return 0;
00563 }
00564 
00565 
00566 void QEditor::setLevel( int line, int lev )
00567 {
00568     ParagData* data = (ParagData*) document()->paragAt( line )->extraData();
00569     if( data ){
00570         return data->setLevel( lev );
00571     }
00572 }
00573 
00574 QSourceColorizer* QEditor::colorizer() const
00575 {
00576     return dynamic_cast<QSourceColorizer*>( document()->preProcessor() );
00577 }
00578 
00579 void QEditor::refresh()
00580 {
00581     document()->invalidate();
00582     QTextParagraph* p = document()->firstParagraph();
00583     while( p ){
00584         p->format();
00585     p = p->next();
00586     }
00587     removeSelection( ParenMatcher::Match );
00588     removeSelection( ParenMatcher::Mismatch );
00589     ensureCursorVisible();
00590     repaintContents( false );
00591 }
00592 
00593 bool QEditor::event( QEvent* e )
00594 {
00595     if( isRecording() && e->type() == QEvent::KeyPress ){
00596         QKeyEvent* ke = (QKeyEvent*) e;
00597         //kdDebug(9032) << "recording" << endl;
00598         QEditorKey* k = new QEditorKey;
00599         k->key = ke->key();
00600         k->ascii = ke->ascii();
00601         k->state = ke->state();
00602         k->text = ke->text();
00603         k->autorep = ke->isAutoRepeat();
00604         k->count = ke->count();
00605 
00606         m_keys.append( k );
00607     }
00608     return QTextEdit::event( e );
00609 }
00610 
00611 void QEditor::startMacro()
00612 {
00613     m_keys.clear();
00614     setIsRecording( TRUE );
00615 }
00616 
00617 void QEditor::stopMacro()
00618 {
00619     setIsRecording( FALSE );
00620 }
00621 
00622 void QEditor::executeMacro()
00623 {
00624     QPtrListIterator<QEditorKey> it( m_keys );
00625     while( it.current() ){
00626         //kdDebug(9032) << "send key" << endl;
00627         QEditorKey* k = it.current();
00628         ++it;
00629 
00630         QKeyEvent e( QEvent::KeyPress,
00631                      k->key,
00632                      k->ascii,
00633                      k->state,
00634                      k->text,
00635                      k->autorep,
00636                      k->count );
00637         QApplication::sendEvent( this, &e );
00638     }
00639 }
00640 
00641 QEditorIndenter* QEditor::indenter() const
00642 {
00643   return dynamic_cast<QEditorIndenter*>( document()->indent() );
00644 }
00645 
00646 void QEditor::indent()
00647 {
00648     KTextEdit::indent();
00649     if( !hasSelectedText() && text( textCursor()->paragraph()->paragId() ).stripWhiteSpace().isEmpty() )
00650     moveCursor( MoveLineEnd, false );
00651 }
00652 
00653 void QEditor::contentsMouseDoubleClickEvent( QMouseEvent * e )
00654 {
00655     if ( e->button() != Qt::LeftButton ) {
00656         e->ignore();
00657         return;
00658     }
00659 
00660     // let the base class do things we maybe don't know
00661     KTextEdit::contentsMouseDoubleClickEvent(e);
00662 
00663     // now do our own method of marking text:
00664     int para = 0;
00665     int index = charAt( e->pos(), &para );
00666     setCursorPosition(para, index);
00667 
00668     QTextCursor* cur = textCursor();
00669     QTextCursor c1 = *cur;
00670     QTextCursor c2 = *cur;
00671     if (c1.paragraph()->at(c1.index())->c.isSpace()) return;
00672 
00673     // find start of text to select..
00674     while (c1.index() > 0 && !isDelimiter(c1.paragraph()->at(c1.index()-1)->c)) {
00675         c1.gotoLeft();
00676     }
00677     // find end of text to select..
00678     while ( !isDelimiter(c2.paragraph()->at(c2.index())->c) && !c2.atParagEnd() ) {
00679         c2.gotoRight();
00680         cur->gotoRight();
00681     }
00682 
00683     document()->setSelectionStart( QTextDocument::Standard, c1 );
00684     document()->setSelectionEnd( QTextDocument::Standard, c2 );
00685 
00686     repaintChanged();
00687 }
00688 
00689 bool QEditor::isDelimiter(const QChar& c)
00690 {
00691     if (c == '_') return false;
00692     return !(c.isLetterOrNumber());
00693 }
00694 
00695 #include "qeditor.moc"
KDE Logo
This file is part of the documentation for KDevelop Version 3.1.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Feb 22 09:22:24 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003