kate Library API Documentation

kateviewhelpers.cpp

00001 /* This file is part of the KDE libraries
00002    Copyright (C) 2002 John Firebaugh <jfirebaugh@kde.org>
00003    Copyright (C) 2001 Anders Lund <anders@alweb.dk>
00004    Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org>
00005 
00006    This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License version 2 as published by the Free Software Foundation.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018    Boston, MA 02111-1307, USA.
00019 */
00020 
00021 #include "kateviewhelpers.h"
00022 #include "kateviewhelpers.moc"
00023 
00024 #include "kateview.h"
00025 #include "kateviewinternal.h"
00026 #include "katedocument.h"
00027 #include "katecodefoldinghelpers.h"
00028 #include "katerenderer.h"
00029 #include "kateattribute.h"
00030 #include "kateconfig.h"
00031 
00032 #include <kglobalsettings.h>
00033 #include <klocale.h>
00034 
00035 #include <qpainter.h>
00036 #include <qpopupmenu.h>
00037 #include <qcursor.h>
00038 #include <qstyle.h>
00039 #include <qtimer.h>
00040 
00041 #include <math.h>
00042 
00043 #include "kateview.h"
00044 #include "katefactory.h"
00045 
00046 #include "../interfaces/katecmd.h"
00047 #include "../interfaces/document.h"
00048 
00049 #include <klocale.h>
00050 
00051 #include <qtimer.h>
00052 
00053 KateCmdLine::KateCmdLine (KateView *view)
00054   : KLineEdit (view)
00055   , m_view (view)
00056   , m_msgMode (false)
00057 {
00058   connect (this, SIGNAL(returnPressed(const QString &)),
00059            this, SLOT(slotReturnPressed(const QString &)));
00060 
00061   completionObject()->insertItems (KateCmd::self()->cmds());
00062 }
00063 
00064 KateCmdLine::~KateCmdLine ()
00065 {
00066 }
00067 
00068 void KateCmdLine::slotReturnPressed ( const QString& cmd )
00069 {
00070   if (cmd.length () > 0)
00071   {
00072     Kate::Command *p = KateCmd::self()->queryCommand (cmd);
00073 
00074     m_oldText = cmd;
00075     m_msgMode = true;
00076 
00077     if (p)
00078     {
00079       QString msg;
00080 
00081       if (p->exec (m_view, cmd, msg))
00082       {
00083         completionObject()->addItem (cmd);
00084         m_oldText = QString ();
00085 
00086         if (msg.length() > 0)
00087           setText (i18n ("Success: ") + msg);
00088         else
00089           setText (i18n ("Success"));
00090       }
00091       else
00092       {
00093         if (msg.length() > 0)
00094           setText (i18n ("Error: ") + msg);
00095         else
00096           setText (i18n ("Command \"%1\" failed.").arg (cmd));
00097       }
00098     }
00099     else
00100       setText (i18n ("No such command: \"%1\"").arg (cmd));
00101   }
00102 
00103   m_view->setFocus ();
00104   QTimer::singleShot( 4000, this, SLOT(hideMe()) );
00105 }
00106 
00107 void KateCmdLine::hideMe ()
00108 {
00109   m_view->showCmdLine (false);
00110 }
00111 
00112 void KateCmdLine::focusInEvent ( QFocusEvent *ev )
00113 {
00114   if (m_msgMode)
00115   {
00116     m_msgMode = false;
00117     setText (m_oldText);
00118   }
00119 
00120   KLineEdit::focusInEvent (ev);
00121 }
00122 
00123 void KateCmdLine::keyPressEvent( QKeyEvent *ev )
00124 {
00125   if (ev->key() == Key_Escape)
00126   {
00127     m_view->setFocus ();
00128     m_view->showCmdLine (false);
00129   }
00130 
00131   return KLineEdit::keyPressEvent (ev);
00132 }
00133 
00134 using namespace KTextEditor;
00135 
00136 static const char* const plus_xpm[] = {
00137 "11 11 3 1",
00138 "       c None",
00139 ".      c #000000",
00140 "+      c #FFFFFF",
00141 "...........",
00142 ".+++++++++.",
00143 ".+++++++++.",
00144 ".++++.++++.",
00145 ".++++.++++.",
00146 ".++.....++.",
00147 ".++++.++++.",
00148 ".++++.++++.",
00149 ".+++++++++.",
00150 ".+++++++++.",
00151 "..........."};
00152 
00153 static const char* const minus_xpm[] = {
00154 "11 11 3 1",
00155 "       c None",
00156 ".      c #000000",
00157 "+      c #FFFFFF",
00158 "...........",
00159 ".+++++++++.",
00160 ".+++++++++.",
00161 ".+++++++++.",
00162 ".+++++++++.",
00163 ".++.....++.",
00164 ".+++++++++.",
00165 ".+++++++++.",
00166 ".+++++++++.",
00167 ".+++++++++.",
00168 "..........."};
00169 
00170 
00171 static const char* const bookmark_xpm[]={
00172 "12 12 4 1",
00173 "b c #808080",
00174 "a c #000080",
00175 "# c #0000ff",
00176 ". c None",
00177 "........###.",
00178 ".......#...a",
00179 "......#.##.a",
00180 ".....#.#..aa",
00181 "....#.#...a.",
00182 "...#.#.a.a..",
00183 "..#.#.a.a...",
00184 ".#.#.a.a....",
00185 "#.#.a.a.....",
00186 "#.#a.a...bbb",
00187 "#...a..bbb..",
00188 ".aaa.bbb...."};
00189 
00190 const int iconPaneWidth = 16;
00191 const int halfIPW = 8;
00192 
00193 static QPixmap minus_px ((const char**)minus_xpm);
00194 static QPixmap plus_px ((const char**)plus_xpm);
00195 
00196 KateIconBorder::KateIconBorder ( KateViewInternal* internalView, QWidget *parent )
00197   : QWidget(parent, "", Qt::WStaticContents | Qt::WRepaintNoErase | Qt::WResizeNoErase )
00198   , m_view( internalView->m_view )
00199   , m_doc( internalView->m_doc )
00200   , m_viewInternal( internalView )
00201   , m_iconBorderOn( false )
00202   , m_lineNumbersOn( false )
00203   , m_foldingMarkersOn( false )
00204   , m_dynWrapIndicatorsOn( false )
00205   , m_dynWrapIndicators( 0 )
00206   , m_cachedLNWidth( 0 )
00207   , m_maxCharWidth( 0 )
00208 {
00209   setSizePolicy( QSizePolicy(  QSizePolicy::Fixed, QSizePolicy::Minimum ) );
00210 
00211   setBackgroundMode( NoBackground );
00212 
00213   m_doc->setDescription( MarkInterface::markType01, i18n("Bookmark") );
00214   m_doc->setPixmap( MarkInterface::markType01, QPixmap((const char**)bookmark_xpm) );
00215 
00216   updateFont();
00217 }
00218 
00219 void KateIconBorder::setIconBorderOn( bool enable )
00220 {
00221   if( enable == m_iconBorderOn )
00222     return;
00223 
00224   m_iconBorderOn = enable;
00225 
00226   updateGeometry();
00227 
00228   QTimer::singleShot( 0, this, SLOT(update()) );
00229 }
00230 
00231 void KateIconBorder::setLineNumbersOn( bool enable )
00232 {
00233   if( enable == m_lineNumbersOn )
00234     return;
00235 
00236   m_lineNumbersOn = enable;
00237   m_dynWrapIndicatorsOn = (m_dynWrapIndicators == 1) ? enable : m_dynWrapIndicators;
00238 
00239   updateGeometry();
00240 
00241   QTimer::singleShot( 0, this, SLOT(update()) );
00242 }
00243 
00244 void KateIconBorder::setDynWrapIndicators( int state )
00245 {
00246   if (state == m_dynWrapIndicators )
00247     return;
00248 
00249   m_dynWrapIndicators = state;
00250   m_dynWrapIndicatorsOn = (state == 1) ? m_lineNumbersOn : state;
00251 
00252   updateGeometry ();
00253 
00254   QTimer::singleShot( 0, this, SLOT(update()) );
00255 }
00256 
00257 void KateIconBorder::setFoldingMarkersOn( bool enable )
00258 {
00259   if( enable == m_foldingMarkersOn )
00260     return;
00261 
00262   m_foldingMarkersOn = enable;
00263 
00264   updateGeometry();
00265 
00266   QTimer::singleShot( 0, this, SLOT(update()) );
00267 }
00268 
00269 QSize KateIconBorder::sizeHint() const
00270 {
00271   int w = 0;
00272 
00273   if (m_iconBorderOn)
00274     w += iconPaneWidth + 1;
00275 
00276   if (m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn)) {
00277     w += lineNumberWidth();
00278   }
00279 
00280   if (m_foldingMarkersOn)
00281     w += iconPaneWidth;
00282 
00283   w += 4;
00284 
00285   return QSize( w, 0 );
00286 }
00287 
00288 // This function (re)calculates the maximum width of any of the digit characters (0 -> 9)
00289 // for graceful handling of variable-width fonts as the linenumber font.
00290 void KateIconBorder::updateFont()
00291 {
00292   const QFontMetrics *fm = m_view->renderer()->config()->fontMetrics();
00293   m_maxCharWidth = 0;
00294   // Loop to determine the widest numeric character in the current font.
00295   // 48 is ascii '0'
00296   for (int i = 48; i < 58; i++) {
00297     int charWidth = fm->width( QChar(i) );
00298     m_maxCharWidth = QMAX(m_maxCharWidth, charWidth);
00299   }
00300 }
00301 
00302 int KateIconBorder::lineNumberWidth() const
00303 {
00304   int width = m_lineNumbersOn ? ((int)log10((double)(m_view->doc()->numLines())) + 1) * m_maxCharWidth + 4 : 0;
00305 
00306   if (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) {
00307     width = QMAX(style().scrollBarExtent().width() + 4, width);
00308 
00309     if (m_cachedLNWidth != width || m_oldBackgroundColor != *m_view->renderer()->config()->iconBarColor()) {
00310       int w = style().scrollBarExtent().width();
00311       int h = m_view->renderer()->config()->fontMetrics()->height();
00312 
00313       QSize newSize(w, h);
00314       if ((m_arrow.size() != newSize || m_oldBackgroundColor != *m_view->renderer()->config()->iconBarColor()) && !newSize.isEmpty()) {
00315         m_arrow.resize(newSize);
00316 
00317         QPainter p(&m_arrow);
00318         p.fillRect( 0, 0, w, h, *m_view->renderer()->config()->iconBarColor() );
00319 
00320         h = m_view->renderer()->config()->fontMetrics()->ascent();
00321 
00322         p.setPen(m_view->renderer()->attribute(0)->textColor());
00323         p.drawLine(w/2, h/2, w/2, 0);
00324 #if 1
00325         p.lineTo(w/4, h/4);
00326         p.lineTo(0, 0);
00327         p.lineTo(0, h/2);
00328         p.lineTo(w/2, h-1);
00329         p.lineTo(w*3/4, h-1);
00330         p.lineTo(w-1, h*3/4);
00331         p.lineTo(w*3/4, h/2);
00332         p.lineTo(0, h/2);
00333 #else
00334         p.lineTo(w*3/4, h/4);
00335         p.lineTo(w-1,0);
00336         p.lineTo(w-1, h/2);
00337         p.lineTo(w/2, h-1);
00338         p.lineTo(w/4,h-1);
00339         p.lineTo(0, h*3/4);
00340         p.lineTo(w/4, h/2);
00341         p.lineTo(w-1, h/2);
00342 #endif
00343       }
00344     }
00345   }
00346 
00347   return width;
00348 }
00349 
00350 void KateIconBorder::paintEvent(QPaintEvent* e)
00351 {
00352   paintBorder(e->rect().x(), e->rect().y(), e->rect().width(), e->rect().height());
00353 }
00354 
00355 void KateIconBorder::paintBorder (int /*x*/, int y, int /*width*/, int height)
00356 {
00357   uint h = m_view->renderer()->config()->fontStruct()->fontHeight;
00358   uint startz = (y / h);
00359   uint endz = startz + 1 + (height / h);
00360   uint lineRangesSize = m_viewInternal->lineRanges.size();
00361 
00362   // center the folding boxes
00363   int m_px = (h - 11) / 2;
00364   if (m_px < 0)
00365     m_px = 0;
00366 
00367   int lnWidth( 0 );
00368   if ( m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) ) // avoid calculating unless needed ;-)
00369   {
00370     lnWidth = lineNumberWidth();
00371     if ( lnWidth != m_cachedLNWidth || m_oldBackgroundColor != *m_view->renderer()->config()->iconBarColor() )
00372     {
00373       // we went from n0 ->n9 lines or vice verca
00374       // this causes an extra updateGeometry() first time the line numbers
00375       // are displayed, but sizeHint() is supposed to be const so we can't set
00376       // the cached value there.
00377       m_cachedLNWidth = lnWidth;
00378       m_oldBackgroundColor = *m_view->renderer()->config()->iconBarColor();
00379       updateGeometry();
00380       update ();
00381       return;
00382     }
00383   }
00384 
00385   int w( this->width() );                     // sane value/calc only once
00386 
00387   QPainter p ( this );
00388   p.setFont ( *m_view->renderer()->config()->font() ); // for line numbers
00389   p.setPen ( m_view->renderer()->attribute(0)->textColor() );
00390 
00391   KateLineInfo oldInfo;
00392   if (startz < lineRangesSize)
00393   {
00394     if ((m_viewInternal->lineRanges[startz].line-1) < 0)
00395       oldInfo.topLevel = true;
00396     else
00397        m_doc->lineInfo(&oldInfo,m_viewInternal->lineRanges[startz].line-1);
00398   }
00399 
00400   for (uint z=startz; z <= endz; z++)
00401   {
00402     int y = h * z;
00403     int realLine = -1;
00404 
00405     if (z < lineRangesSize)
00406      realLine = m_viewInternal->lineRanges[z].line;
00407 
00408     int lnX ( 0 );
00409 
00410     p.fillRect( 0, y, w-4, h, *m_view->renderer()->config()->iconBarColor() );
00411     p.fillRect( w-4, y, 4, h, *m_view->renderer()->config()->backgroundColor() );
00412 
00413     // icon pane
00414     if( m_iconBorderOn )
00415     {
00416       p.drawLine(lnX+iconPaneWidth, y, lnX+iconPaneWidth, y+h);
00417 
00418       if( (realLine > -1) && (m_viewInternal->lineRanges[z].startCol == 0) )
00419       {
00420         uint mrk ( m_doc->mark( realLine ) ); // call only once
00421 
00422         if ( mrk )
00423         {
00424           for( uint bit = 0; bit < 32; bit++ )
00425           {
00426             MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes)(1<<bit);
00427             if( mrk & markType )
00428             {
00429               QPixmap *px_mark (m_doc->markPixmap( markType ));
00430 
00431               if (px_mark)
00432               {
00433                 // center the mark pixmap
00434                 int x_px = (iconPaneWidth - px_mark->width()) / 2;
00435                 if (x_px < 0)
00436                   x_px = 0;
00437 
00438                 int y_px = (h - px_mark->height()) / 2;
00439                 if (y_px < 0)
00440                   y_px = 0;
00441 
00442                 p.drawPixmap( lnX+x_px, y+y_px, *px_mark);
00443               }
00444             }
00445           }
00446         }
00447       }
00448 
00449       lnX += iconPaneWidth + 1;
00450     }
00451 
00452     // line number
00453     if( m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) )
00454     {
00455       lnX +=2;
00456 
00457       if (realLine > -1)
00458         if (m_viewInternal->lineRanges[z].startCol == 0) {
00459           if (m_lineNumbersOn)
00460             p.drawText( lnX + 1, y, lnWidth-4, h, Qt::AlignRight|Qt::AlignVCenter, QString("%1").arg( realLine + 1 ) );
00461         } else if (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) {
00462           p.drawPixmap(lnX + lnWidth - m_arrow.width() - 4, y, m_arrow);
00463         }
00464 
00465       lnX += lnWidth;
00466     }
00467 
00468     // folding markers
00469     if( m_foldingMarkersOn )
00470     {
00471       if( realLine > -1 )
00472       {
00473         KateLineInfo info;
00474         m_doc->lineInfo(&info,realLine);
00475 
00476         if (!info.topLevel)
00477         {
00478           if (info.startsVisibleBlock && (m_viewInternal->lineRanges[z].startCol == 0))
00479           {
00480             if (oldInfo.topLevel)
00481               p.drawLine(lnX+halfIPW,y+m_px,lnX+halfIPW,y+h-1);
00482             else
00483               p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1);
00484 
00485             p.drawPixmap(lnX+3,y+m_px,minus_px);
00486           }
00487           else if (info.startsInVisibleBlock)
00488           {
00489             if (m_viewInternal->lineRanges[z].startCol == 0)
00490             {
00491               if (oldInfo.topLevel)
00492                 p.drawLine(lnX+halfIPW,y+m_px,lnX+halfIPW,y+h-1);
00493               else
00494                 p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1);
00495 
00496               p.drawPixmap(lnX+3,y+m_px,plus_px);
00497             }
00498             else
00499             {
00500               p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1);
00501             }
00502 
00503             if (!m_viewInternal->lineRanges[z].wrap)
00504               p.drawLine(lnX+halfIPW,y+h-1,lnX+iconPaneWidth-2,y+h-1);
00505           }
00506           else
00507           {
00508             p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1);
00509 
00510             if (info.endsBlock && !m_viewInternal->lineRanges[z].wrap)
00511               p.drawLine(lnX+halfIPW,y+h-1,lnX+iconPaneWidth-2,y+h-1);
00512           }
00513         }
00514 
00515         oldInfo = info;
00516       }
00517 
00518       lnX += iconPaneWidth;
00519     }
00520   }
00521 }
00522 
00523 KateIconBorder::BorderArea KateIconBorder::positionToArea( const QPoint& p ) const
00524 {
00525   int x = 0;
00526 
00527   if( m_iconBorderOn ) {
00528     x += iconPaneWidth;
00529     if( p.x() <= x )
00530       return IconBorder;
00531   }
00532   if( m_lineNumbersOn || m_dynWrapIndicators ) {
00533     x += lineNumberWidth();
00534     if( p.x() <= x )
00535       return LineNumbers;
00536   }
00537   if( m_foldingMarkersOn ) {
00538     x += iconPaneWidth;
00539     if( p.x() <= x )
00540       return FoldingMarkers;
00541   }
00542   return None;
00543 }
00544 
00545 void KateIconBorder::mousePressEvent( QMouseEvent* e )
00546 {
00547   m_lastClickedLine = m_viewInternal->yToLineRange(e->y()).line;
00548 
00549   if ( positionToArea( e->pos() ) != IconBorder )
00550   {
00551     QMouseEvent forward( QEvent::MouseButtonPress,
00552       QPoint( 0, e->y() ), e->button(), e->state() );
00553     m_viewInternal->mousePressEvent( &forward );
00554   }
00555   e->accept();
00556 }
00557 
00558 void KateIconBorder::mouseMoveEvent( QMouseEvent* e )
00559 {
00560   QMouseEvent forward( QEvent::MouseMove,
00561     QPoint( 0, e->y() ), e->button(), e->state() );
00562   m_viewInternal->mouseMoveEvent( &forward );
00563 }
00564 
00565 void KateIconBorder::mouseReleaseEvent( QMouseEvent* e )
00566 {
00567   uint cursorOnLine = m_viewInternal->yToLineRange(e->y()).line;
00568 
00569   if (cursorOnLine == m_lastClickedLine &&
00570       cursorOnLine <= m_doc->lastLine() )
00571   {
00572     BorderArea area = positionToArea( e->pos() );
00573     if( area == IconBorder) {
00574       if (e->button() == LeftButton) {
00575         if( m_doc->editableMarks() & KateViewConfig::global()->defaultMarkType() ) {
00576           if( m_doc->mark( cursorOnLine ) & KateViewConfig::global()->defaultMarkType() )
00577             m_doc->removeMark( cursorOnLine, KateViewConfig::global()->defaultMarkType() );
00578           else
00579             m_doc->addMark( cursorOnLine, KateViewConfig::global()->defaultMarkType() );
00580           } else {
00581             showMarkMenu( cursorOnLine, QCursor::pos() );
00582           }
00583         }
00584         else
00585         if (e->button() == RightButton) {
00586           showMarkMenu( cursorOnLine, QCursor::pos() );
00587         }
00588     }
00589 
00590     if ( area == FoldingMarkers) {
00591       KateLineInfo info;
00592       m_doc->lineInfo(&info,cursorOnLine);
00593       if ((info.startsVisibleBlock) || (info.startsInVisibleBlock)) {
00594         emit toggleRegionVisibility(cursorOnLine);
00595       }
00596     }
00597   }
00598 
00599   QMouseEvent forward( QEvent::MouseButtonRelease,
00600     QPoint( 0, e->y() ), e->button(), e->state() );
00601   m_viewInternal->mouseReleaseEvent( &forward );
00602 }
00603 
00604 void KateIconBorder::mouseDoubleClickEvent( QMouseEvent* e )
00605 {
00606   QMouseEvent forward( QEvent::MouseButtonDblClick,
00607     QPoint( 0, e->y() ), e->button(), e->state() );
00608   m_viewInternal->mouseDoubleClickEvent( &forward );
00609 }
00610 
00611 void KateIconBorder::showMarkMenu( uint line, const QPoint& pos )
00612 {
00613   QPopupMenu markMenu;
00614   QPopupMenu selectDefaultMark;
00615 
00616   typedef QValueVector<int> MarkTypeVector;
00617   MarkTypeVector vec( 33 );
00618   int i=1;
00619 
00620   for( uint bit = 0; bit < 32; bit++ ) {
00621     MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes)(1<<bit);
00622     if( !(m_doc->editableMarks() & markType) )
00623       continue;
00624 
00625     if( !m_doc->markDescription( markType ).isEmpty() ) {
00626       markMenu.insertItem( m_doc->markDescription( markType ), i );
00627       selectDefaultMark.insertItem( m_doc->markDescription( markType ), i+100);
00628     } else {
00629       markMenu.insertItem( i18n("Mark Type %1").arg( bit + 1 ), i );
00630       selectDefaultMark.insertItem( i18n("Mark Type %1").arg( bit + 1 ), i+100);
00631     }
00632 
00633     if( m_doc->mark( line ) & markType )
00634       markMenu.setItemChecked( i, true );
00635 
00636     if( markType & KateViewConfig::global()->defaultMarkType() )
00637       selectDefaultMark.setItemChecked( i+100, true );
00638 
00639     vec[i++] = markType;
00640   }
00641 
00642   if( markMenu.count() == 0 )
00643     return;
00644 
00645   if( markMenu.count() > 1 )
00646     markMenu.insertItem( i18n("Set Default Mark Type" ), &selectDefaultMark);
00647 
00648   int result = markMenu.exec( pos );
00649   if( result <= 0 )
00650     return;
00651 
00652   if ( result > 100)
00653      KateViewConfig::global()->setDefaultMarkType (vec[result-100]);
00654   else
00655   {
00656     MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes) vec[result];
00657     if( m_doc->mark( line ) & markType ) {
00658       m_doc->removeMark( line, markType );
00659     } else {
00660         m_doc->addMark( line, markType );
00661     }
00662   }
00663 }
00664 
00665 // kate: space-indent on; indent-width 2; replace-tabs on;
KDE Logo
This file is part of the documentation for kate Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed May 5 07:18:45 2004 by doxygen 1.3.6 written by Dimitri van Heesch, © 1997-2003