# kate Library API Documentation

Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# katetemplatehandler.cpp

    00001 /* This file is part of the KDE libraries
    00002   Copyright (C) 2004 Joseph Wenninger <jowenn@kde.org>
    00003
    00004   This library is free software; you can redistribute it and/or
    00005   modify it under the terms of the GNU Library General Public
    00006   License version 2 as published by the Free Software Foundation.
    00007
    00008   This library is distributed in the hope that it will be useful,
    00009   but WITHOUT ANY WARRANTY; without even the implied warranty of
    00010   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00011   Library General Public License for more details.
    00012
    00013   You should have received a copy of the GNU Library General Public License
    00014   along with this library; see the file COPYING.LIB.  If not, write to
    00015   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00016   Boston, MA 02111-1307, USA.
    00017 */
    00018 #include "katetemplatehandler.h"
    00019 #include "katetemplatehandler.moc"
    00020 #include "katedocument.h"
    00021 #include "katesupercursor.h"
    00022 #include "katearbitraryhighlight.h"
    00023 #include "kateview.h"
    00024 #include <qregexp.h>
    00025 #include <kdebug.h>
    00026 #include <qvaluelist.h>
    00027
    00028 KateTemplateHandler::KateTemplateHandler(
    00029   KateDocument *doc,
    00030   uint line, uint column,
    00031   const QString &templateString,
    00032   const QMap<QString, QString> &initialValues )
    00033     : QObject( doc )
    00034     , KateKeyInterceptorFunctor()
    00035     , m_doc( doc )
    00036     , m_currentTabStop( -1 )
    00037     , m_currentRange( 0 )
    00038     , m_initOk( false )
    00039     , m_recursion( false )
    00040 {
    00041   connect( m_doc, SIGNAL( destroyed() ), this, SLOT( slotDocumentDestroyed() ) );
    00042   m_ranges = new KateSuperRangeList( false, this ); //false/*,this*/);
    00043
    00044   if ( !m_doc->setTabInterceptor( this ) )
    00045   {
    00046     deleteLater();
    00047     return ;
    00048   }
    00049
    00050   KateArbitraryHighlight *kah = doc->arbitraryHL();
    00051   /*KateArbitraryHighlightRange *hlr=new KateArbitraryHighlightRange(doc,KateTextCursor(line,column),
    00052    KateTextCursor(line,column+3));
    00053   hlr->setUnderline(true);
    00054   hlr->setOverline(true);
    00055   l->append(hlr);*/
    00056   QValueList<KateTemplateHandlerPlaceHolderInfo> buildList;
    00057   QRegExp rx( "([$%])\\{([^}\\s]+)\\}" );
    00058   rx.setMinimal( true );
    00059   int pos = 0;
    00060   int opos = 0;
    00061   QString insertString = templateString;
    00062
    00063   while ( pos >= 0 )
    00064   {
    00065     pos = rx.search( insertString, pos );
    00066
    00067     if ( pos > -1 )
    00068     {
    00069       if ( ( pos - opos ) > 0 )
    00070       {
    00071         if ( insertString[ pos - 1 ] == '\\' )
    00072         {
    00073           insertString.remove( pos - 1, 1 );
    00074           opos = pos;
    00075           continue;
    00076         }
    00077       }
    00078
    00079       QString placeholder = rx.cap( 2 );
    00080       QString value = initialValues[ placeholder ];
    00081
    00082       // don't add %{MACRO} to the tab navigation, unless there was not value
    00083       if ( rx.cap( 1 ) != "%" || placeholder == value )
    00084         buildList.append( KateTemplateHandlerPlaceHolderInfo( pos, value.length(), placeholder ) );
    00085
    00086       insertString.replace( pos, rx.matchedLength(), value );
    00087       pos += value.length();
    00088       opos = pos;
    00089     }
    00090   }
    00091
    00092   doc->editStart();
    00093
    00094   if ( !doc->insertText( line, column, insertString ) )
    00095   {
    00096     deleteLater();
    00097     doc->editEnd();
    00098     return ;
    00099   }
    00100
    00101   if ( buildList.isEmpty() )
    00102   {
    00103     m_initOk = true;
    00104     deleteLater();
    00105     doc->editEnd();
    00106     return ;
    00107   }
    00108
    00109   doc->undoSafePoint();
    00110   doc->editEnd();
    00111   generateRangeTable( line, column, insertString, buildList );
    00112   kah->addHighlightToDocument( m_ranges );
    00113
    00114   for ( KateSuperRangeList::const_iterator it = m_ranges->begin();it != m_ranges->end();++it )
    00115   {
    00116     m_doc->tagLines( ( *it ) ->start().line(), ( *it ) ->end().line() );
    00117   }
    00118
    00119   /* connect(doc,SIGNAL(charactersInteractivelyInserted(int ,int ,const QString&)),this,
    00120    SLOT(slotCharactersInteractivlyInserted(int,int,const QString&)));
    00121    connect(doc,SIGNAL(charactersSemiInteractivelyInserted(int ,int ,const QString&)),this,
    00122    SLOT(slotCharactersInteractivlyInserted(int,int,const QString&)));*/
    00123   connect( doc, SIGNAL( textInserted( int, int ) ), this, SLOT( slotTextInserted( int, int ) ) );
    00124   connect( doc, SIGNAL( aboutToRemoveText( const KateTextRange& ) ), this, SLOT( slotAboutToRemoveText( const KateTextRange& ) ) );
    00125   connect( doc, SIGNAL( textRemoved() ), this, SLOT( slotTextRemoved() ) );
    00126
    00127   ( *this ) ( Qt::Key_Tab );
    00128 }
    00129
    00130 KateTemplateHandler::~KateTemplateHandler()
    00131 {
    00132   m_ranges->setAutoManage( true );
    00133
    00134   if ( m_doc )
    00135   {
    00136     m_doc->removeTabInterceptor( this );
    00137
    00138     for ( KateSuperRangeList::const_iterator it = m_ranges->begin();it != m_ranges->end();++it )
    00139     {
    00140       m_doc->tagLines( ( *it ) ->start().line(), ( *it ) ->end().line() );
    00141     }
    00142   }
    00143
    00144   m_ranges->clear();
    00145 }
    00146
    00147 void KateTemplateHandler::slotDocumentDestroyed() {m_doc = 0;}
    00148
    00149 void KateTemplateHandler::generateRangeTable( uint insertLine, uint insertCol, const QString& insertString, const QValueList<KateTemplateHandlerPlaceHolderInfo> &buildList )
    00150 {
    00151   uint line = insertLine;
    00152   uint col = insertCol;
    00153   uint colInText = 0;
    00154
    00155   for ( QValueList<KateTemplateHandlerPlaceHolderInfo>::const_iterator it = buildList.begin();it != buildList.end();++it )
    00156   {
    00157     KateTemplatePlaceHolder *ph = m_dict[ ( *it ).placeholder ];
    00158
    00159     if ( !ph )
    00160     {
    00161       ph = new KateTemplatePlaceHolder;
    00162       ph->isInitialValue = true;
    00163       ph->isCursor = ( ( *it ).placeholder == "cursor" );
    00164       m_dict.insert( ( *it ).placeholder, ph );
    00165
    00166       if ( !ph->isCursor ) m_tabOrder.append( ph );
    00167
    00168       ph->ranges.setAutoManage( false );
    00169     }
    00170
    00171     // FIXME handle space/tab replacement correctly make it use of the indenter
    00172     while ( colInText < ( *it ).begin )
    00173     {
    00174       ++col;
    00175
    00176       if ( insertString.at( colInText ) == '\n' )
    00177       {
    00178         col = 0;
    00179         line++;
    00180       }
    00181
    00182       ++colInText;
    00183     }
    00184
    00185     KateArbitraryHighlightRange *hlr = new KateArbitraryHighlightRange( m_doc, KateTextCursor( line, col ),
    00186                                        KateTextCursor( line, ( *it ).len + col ) );
    00187     colInText += ( *it ).len;
    00188     col += ( *it ).len;
    00189     hlr->allowZeroLength();
    00190     hlr->setUnderline( true );
    00191     hlr->setOverline( true );
    00192     //hlr->setBehaviour(KateSuperRange::ExpandRight);
    00193     ph->ranges.append( hlr );
    00194     m_ranges->append( hlr );
    00195   }
    00196
    00197   KateTemplatePlaceHolder *cursor = m_dict[ "cursor" ];
    00198
    00199   if ( cursor ) m_tabOrder.append( cursor );
    00200 }
    00201
    00202 void KateTemplateHandler::slotTextInserted( int line, int col )
    00203 {
    00204 #ifdef __GNUC__
    00205 #warning FIXME undo/redo detection
    00206 #endif
    00207
    00208   if ( m_recursion ) return ;
    00209
    00210   //if (m_editSessionNumber!=0) return; // assume that this is due an udno/redo operation right now
    00211   KateTextCursor cur( line, col );
    00212
    00213   if ( ( !m_currentRange ) ||
    00214        ( ( !m_currentRange->includes( cur ) ) && ( ! ( ( m_currentRange->start() == m_currentRange->end() ) && m_currentRange->end() == cur ) )
    00215        ) ) locateRange( cur );
    00216
    00217   if ( !m_currentRange ) return ;
    00218
    00219   KateTemplatePlaceHolder *ph = m_tabOrder.at( m_currentTabStop );
    00220
    00221   QString sourceText = m_doc->text ( m_currentRange->start().line(), m_currentRange->start().col(),
    00222                                      m_currentRange->end().line(), m_currentRange->end().col(), false );
    00223
    00224   ph->isInitialValue = false;
    00225   bool undoDontMerge = m_doc->m_undoDontMerge;
    00226   Q_ASSERT( m_doc->editSessionNumber == 0 );
    00227   m_recursion = true;
    00228
    00229   m_doc->editStart( /*false*/ );
    00230
    00231   for ( KateSuperRangeList::const_iterator it = ph->ranges.begin();it != ph->ranges.end();++it )
    00232   {
    00233     if ( ( *it ) == m_currentRange ) continue;
    00234
    00235     KateTextCursor start = ( *it ) ->start();
    00236     KateTextCursor end = ( *it ) ->end();
    00237     m_doc->removeText( start.line(), start.col(), end.line(), end.col(), false );
    00238     m_doc->insertText( start.line(), start.col(), sourceText );
    00239   }
    00240
    00241   m_doc->m_undoDontMerge = false;
    00242   m_doc->m_undoComplexMerge = true;
    00243   m_doc->undoSafePoint();
    00244   m_doc->editEnd();
    00245   m_doc->m_undoDontMerge = undoDontMerge;
    00246   m_recursion = false;
    00247
    00248   if ( ph->isCursor ) deleteLater();
    00249 }
    00250
    00251 void KateTemplateHandler::locateRange( const KateTextCursor& cursor )
    00252 {
    00253   /* if (m_currentRange) {
    00254     m_doc->tagLines(m_currentRange->start().line(),m_currentRange->end().line());
    00255
    00256    }*/
    00257
    00258   for ( uint i = 0;i < m_tabOrder.count();i++ )
    00259   {
    00260     KateTemplatePlaceHolder *ph = m_tabOrder.at( i );
    00261
    00262     for ( KateSuperRangeList::const_iterator it = ph->ranges.begin();it != ph->ranges.end();++it )
    00263     {
    00264       if ( ( *it ) ->includes( cursor ) )
    00265       {
    00266         m_currentTabStop = i;
    00267         m_currentRange = ( *it );
    00268         //m_doc->tagLines(m_currentRange->start().line(),m_currentRange->end().line());
    00269         return ;
    00270       }
    00271     }
    00272
    00273   }
    00274
    00275   m_currentRange = 0;
    00276   /*while (m_ranges->count()>0)
    00277    delete (m_ranges->take(0));
    00278   disconnect(m_ranges,0,0,0);
    00279   delete m_ranges;*/
    00280   deleteLater();
    00281 }
    00282
    00283
    00284 bool KateTemplateHandler::operator() ( KKey key )
    00285 {
    00286   if ( key==Qt::Key_Tab )
    00287   {
    00288     m_currentTabStop++;
    00289
    00290     if ( m_currentTabStop >= ( int ) m_tabOrder.count() )
    00291       m_currentTabStop = 0;
    00292   }
    00293   else
    00294   {
    00295     m_currentTabStop--;
    00296
    00297     if ( m_currentTabStop < 0 ) m_currentTabStop = m_tabOrder.count() - 1;
    00298   }
    00299
    00300   m_currentRange = m_tabOrder.at( m_currentTabStop ) ->ranges.at( 0 );
    00301
    00302   if ( m_tabOrder.at( m_currentTabStop ) ->isInitialValue )
    00303   {
    00304     m_doc->setSelection( m_currentRange->start(), m_currentRange->end() );
    00305   }
    00306   else m_doc->setSelection( m_currentRange->end(), m_currentRange->end() );
    00307
    00308   m_doc->activeView() ->setCursorPosition( m_currentRange->end().line(), m_currentRange->end().col() );
    00309   m_doc->activeView() ->tagLine( m_currentRange->end() );
    00310
    00311   return true;
    00312 }
    00313
    00314 void KateTemplateHandler::slotAboutToRemoveText( const KateTextRange &range )
    00315 {
    00316   if ( m_recursion ) return ;
    00317
    00318   if ( m_currentRange && ( !m_currentRange->includes( range.start() ) ) ) locateRange( range.start() );
    00319
    00320   if ( m_currentRange != 0 )
    00321   {
    00322     if ( m_currentRange->end() <= range.end() ) return ;
    00323   }
    00324
    00325   if ( m_doc )
    00326   {
    00327     disconnect( m_doc, SIGNAL( textInserted( int, int ) ), this, SLOT( slotTextInserted( int, int ) ) );
    00328     disconnect( m_doc, SIGNAL( aboutToRemoveText( const KateTextRange& ) ), this, SLOT( slotAboutToRemoveText( const KateTextRange& ) ) );
    00329     disconnect( m_doc, SIGNAL( textRemoved() ), this, SLOT( slotTextRemoved() ) );
    00330   }
    00331
    00332   deleteLater();
    00333 }
    00334
    00335 void KateTemplateHandler::slotTextRemoved()
    00336 {
    00337   if ( m_recursion ) return ;
    00338   if ( !m_currentRange ) return ;
    00339
    00340   slotTextInserted( m_currentRange->start().line(), m_currentRange->start().col() );
    00341 }
    00342

This file is part of the documentation for kate Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:36:38 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003