00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kateautoindent.h"
00022 #include "kateautoindent.moc"
00023
00024 #include "kateconfig.h"
00025 #include "katehighlight.h"
00026 #include "katefactory.h"
00027 #include "katejscript.h"
00028 #include "kateview.h"
00029
00030 #include <klocale.h>
00031 #include <kdebug.h>
00032 #include <kpopupmenu.h>
00033
00034 #include <cctype>
00035
00036
00037
00038 KateAutoIndent *KateAutoIndent::createIndenter (KateDocument *doc, uint mode)
00039 {
00040 if (mode == KateDocumentConfig::imNormal)
00041 return new KateNormalIndent (doc);
00042 else if (mode == KateDocumentConfig::imCStyle)
00043 return new KateCSmartIndent (doc);
00044 else if (mode == KateDocumentConfig::imPythonStyle)
00045 return new KatePythonIndent (doc);
00046 else if (mode == KateDocumentConfig::imXmlStyle)
00047 return new KateXmlIndent (doc);
00048 else if (mode == KateDocumentConfig::imCSAndS)
00049 return new KateCSAndSIndent (doc);
00050 else if ( mode == KateDocumentConfig::imVarIndent )
00051 return new KateVarIndent ( doc );
00052
00053
00054
00055 return new KateAutoIndent (doc);
00056 }
00057
00058 QStringList KateAutoIndent::listModes ()
00059 {
00060 QStringList l;
00061
00062 l << modeDescription(KateDocumentConfig::imNone);
00063 l << modeDescription(KateDocumentConfig::imNormal);
00064 l << modeDescription(KateDocumentConfig::imCStyle);
00065 l << modeDescription(KateDocumentConfig::imPythonStyle);
00066 l << modeDescription(KateDocumentConfig::imXmlStyle);
00067 l << modeDescription(KateDocumentConfig::imCSAndS);
00068 l << modeDescription(KateDocumentConfig::imVarIndent);
00069
00070
00071 return l;
00072 }
00073
00074 QString KateAutoIndent::modeName (uint mode)
00075 {
00076 if (mode == KateDocumentConfig::imNormal)
00077 return QString ("normal");
00078 else if (mode == KateDocumentConfig::imCStyle)
00079 return QString ("cstyle");
00080 else if (mode == KateDocumentConfig::imPythonStyle)
00081 return QString ("python");
00082 else if (mode == KateDocumentConfig::imXmlStyle)
00083 return QString ("xml");
00084 else if (mode == KateDocumentConfig::imCSAndS)
00085 return QString ("csands");
00086 else if ( mode == KateDocumentConfig::imVarIndent )
00087 return QString( "varindent" );
00088
00089
00090
00091 return QString ("none");
00092 }
00093
00094 QString KateAutoIndent::modeDescription (uint mode)
00095 {
00096 if (mode == KateDocumentConfig::imNormal)
00097 return i18n ("Normal");
00098 else if (mode == KateDocumentConfig::imCStyle)
00099 return i18n ("C Style");
00100 else if (mode == KateDocumentConfig::imPythonStyle)
00101 return i18n ("Python Style");
00102 else if (mode == KateDocumentConfig::imXmlStyle)
00103 return i18n ("XML Style");
00104 else if (mode == KateDocumentConfig::imCSAndS)
00105 return i18n ("S&S C Style");
00106 else if ( mode == KateDocumentConfig::imVarIndent )
00107 return i18n("Variable Based Indenter");
00108
00109
00110
00111 return i18n ("None");
00112 }
00113
00114 uint KateAutoIndent::modeNumber (const QString &name)
00115 {
00116 if (modeName(KateDocumentConfig::imNormal) == name)
00117 return KateDocumentConfig::imNormal;
00118 else if (modeName(KateDocumentConfig::imCStyle) == name)
00119 return KateDocumentConfig::imCStyle;
00120 else if (modeName(KateDocumentConfig::imPythonStyle) == name)
00121 return KateDocumentConfig::imPythonStyle;
00122 else if (modeName(KateDocumentConfig::imXmlStyle) == name)
00123 return KateDocumentConfig::imXmlStyle;
00124 else if (modeName(KateDocumentConfig::imCSAndS) == name)
00125 return KateDocumentConfig::imCSAndS;
00126 else if ( modeName( KateDocumentConfig::imVarIndent ) == name )
00127 return KateDocumentConfig::imVarIndent;
00128
00129
00130
00131 return KateDocumentConfig::imNone;
00132 }
00133
00134 bool KateAutoIndent::hasConfigPage (uint mode)
00135 {
00136
00137
00138
00139 return false;
00140 }
00141
00142 IndenterConfigPage* KateAutoIndent::configPage(QWidget *parent, uint mode)
00143 {
00144
00145
00146
00147 return 0;
00148 }
00149
00150 KateAutoIndent::KateAutoIndent (KateDocument *_doc)
00151 : QObject(), doc(_doc)
00152 {
00153 }
00154 KateAutoIndent::~KateAutoIndent ()
00155 {
00156 }
00157
00158
00159
00160
00161 KateViewIndentationAction::KateViewIndentationAction(KateDocument *_doc, const QString& text, QObject* parent, const char* name)
00162 : KActionMenu (text, parent, name), doc(_doc)
00163 {
00164 connect(popupMenu(),SIGNAL(aboutToShow()),this,SLOT(slotAboutToShow()));
00165 }
00166
00167 void KateViewIndentationAction::slotAboutToShow()
00168 {
00169 QStringList modes = KateAutoIndent::listModes ();
00170
00171 popupMenu()->clear ();
00172 for (uint z=0; z<modes.size(); ++z)
00173 popupMenu()->insertItem ( '&' + KateAutoIndent::modeDescription(z).replace('&', "&&"), this, SLOT(setMode(int)), 0, z);
00174
00175 popupMenu()->setItemChecked (doc->config()->indentationMode(), true);
00176 }
00177
00178 void KateViewIndentationAction::setMode (int mode)
00179 {
00180 doc->config()->setIndentationMode((uint)mode);
00181 }
00182
00183
00184
00185
00186 KateNormalIndent::KateNormalIndent (KateDocument *_doc)
00187 : KateAutoIndent (_doc)
00188 {
00189
00190 connect(_doc, SIGNAL(hlChanged()), this, SLOT(updateConfig()));
00191 }
00192
00193 KateNormalIndent::~KateNormalIndent ()
00194 {
00195 }
00196
00197 void KateNormalIndent::updateConfig ()
00198 {
00199 KateDocumentConfig *config = doc->config();
00200
00201 useSpaces = config->configFlags() & KateDocument::cfSpaceIndent || config->configFlags() & KateDocumentConfig::cfReplaceTabsDyn;
00202 mixedIndent = useSpaces && config->configFlags() & KateDocumentConfig::cfMixedIndent;
00203 keepProfile = config->configFlags() & KateDocument::cfKeepIndentProfile;
00204 tabWidth = config->tabWidth();
00205 indentWidth = useSpaces? config->indentationWidth() : tabWidth;
00206
00207 commentAttrib = 255;
00208 doxyCommentAttrib = 255;
00209 regionAttrib = 255;
00210 symbolAttrib = 255;
00211 alertAttrib = 255;
00212 tagAttrib = 255;
00213 wordAttrib = 255;
00214 keywordAttrib = 255;
00215 normalAttrib = 255;
00216 extensionAttrib = 255;
00217 preprocessorAttrib = 255;
00218
00219 KateHlItemDataList items;
00220 doc->highlight()->getKateHlItemDataListCopy (0, items);
00221
00222 for (uint i=0; i<items.count(); i++)
00223 {
00224 QString name = items.at(i)->name;
00225 if (name.find("Comment") != -1 && commentAttrib == 255)
00226 {
00227 commentAttrib = i;
00228 }
00229 else if (name.find("Region Marker") != -1 && regionAttrib == 255)
00230 {
00231 regionAttrib = i;
00232 }
00233 else if (name.find("Symbol") != -1 && symbolAttrib == 255)
00234 {
00235 symbolAttrib = i;
00236 }
00237 else if (name.find("Alert") != -1)
00238 {
00239 alertAttrib = i;
00240 }
00241 else if (name.find("Comment") != -1 && commentAttrib != 255 && doxyCommentAttrib == 255)
00242 {
00243 doxyCommentAttrib = i;
00244 }
00245 else if (name.find("Tags") != -1 && tagAttrib == 255)
00246 {
00247 tagAttrib = i;
00248 }
00249 else if (name.find("Word") != -1 && wordAttrib == 255)
00250 {
00251 wordAttrib = i;
00252 }
00253 else if (name.find("Keyword") != -1 && keywordAttrib == 255)
00254 {
00255 keywordAttrib = i;
00256 }
00257 else if (name.find("Normal") != -1 && normalAttrib == 255)
00258 {
00259 normalAttrib = i;
00260 }
00261 else if (name.find("Extensions") != -1 && extensionAttrib == 255)
00262 {
00263 extensionAttrib = i;
00264 }
00265 else if (name.find("Preprocessor") != -1 && preprocessorAttrib == 255)
00266 {
00267 preprocessorAttrib = i;
00268 }
00269 }
00270 }
00271
00272 bool KateNormalIndent::isBalanced (KateDocCursor &begin, const KateDocCursor &end, QChar open, QChar close, uint &pos) const
00273 {
00274 int parenOpen = 0;
00275 bool atLeastOne = false;
00276 bool getNext = false;
00277
00278 pos = doc->plainKateTextLine(begin.line())->firstChar();
00279
00280
00281
00282 while (begin < end)
00283 {
00284 QChar c = begin.currentChar();
00285 if (begin.currentAttrib() == symbolAttrib)
00286 {
00287 if (c == open)
00288 {
00289 if (!atLeastOne)
00290 {
00291 atLeastOne = true;
00292 getNext = true;
00293 pos = measureIndent(begin) + 1;
00294 }
00295 parenOpen++;
00296 }
00297 else if (c == close)
00298 {
00299 parenOpen--;
00300 }
00301 }
00302 else if (getNext && !c.isSpace())
00303 {
00304 getNext = false;
00305 pos = measureIndent(begin);
00306 }
00307
00308 if (atLeastOne && parenOpen <= 0)
00309 return true;
00310
00311 begin.moveForward(1);
00312 }
00313
00314 return (atLeastOne) ? false : true;
00315 }
00316
00317 bool KateNormalIndent::skipBlanks (KateDocCursor &cur, KateDocCursor &max, bool newline) const
00318 {
00319 int curLine = cur.line();
00320 if (newline)
00321 cur.moveForward(1);
00322
00323 if (cur >= max)
00324 return false;
00325
00326 do
00327 {
00328 uchar attrib = cur.currentAttrib();
00329 const QString hlFile = doc->highlight()->hlKeyForAttrib( attrib );
00330
00331 if (attrib != commentAttrib && attrib != regionAttrib && attrib != alertAttrib && attrib != preprocessorAttrib && !hlFile.endsWith("doxygen.xml"))
00332 {
00333 QChar c = cur.currentChar();
00334 if (!c.isNull() && !c.isSpace())
00335 break;
00336 }
00337
00338 if (!cur.moveForward(1))
00339 {
00340
00341 cur = max;
00342 break;
00343 }
00344
00345 if (curLine != cur.line())
00346 {
00347 if (!newline)
00348 break;
00349 curLine = cur.line();
00350 cur.setCol(0);
00351 }
00352 } while (cur < max);
00353
00354 if (cur > max)
00355 cur = max;
00356 return true;
00357 }
00358
00359 uint KateNormalIndent::measureIndent (KateDocCursor &cur) const
00360 {
00361
00362
00363
00364 return doc->plainKateTextLine(cur.line())->cursorX(cur.col(), tabWidth);
00365 }
00366
00367 QString KateNormalIndent::tabString(uint pos) const
00368 {
00369 QString s;
00370 pos = kMin (pos, 80U);
00371
00372 if (!useSpaces || mixedIndent)
00373 {
00374 while (pos >= tabWidth)
00375 {
00376 s += '\t';
00377 pos -= tabWidth;
00378 }
00379 }
00380 while (pos > 0)
00381 {
00382 s += ' ';
00383 pos--;
00384 }
00385 return s;
00386 }
00387
00388 void KateNormalIndent::processNewline (KateDocCursor &begin, bool )
00389 {
00390 int line = begin.line() - 1;
00391 int pos = begin.col();
00392
00393 while ((line > 0) && (pos < 0))
00394 pos = doc->plainKateTextLine(--line)->firstChar();
00395
00396 if (pos > 0)
00397 {
00398 QString filler = doc->text(line, 0, line, pos);
00399 doc->insertText(begin.line(), 0, filler);
00400 begin.setCol(filler.length());
00401 }
00402 else
00403 begin.setCol(0);
00404 }
00405
00406
00407
00408
00409
00410 KateCSmartIndent::KateCSmartIndent (KateDocument *doc)
00411 : KateNormalIndent (doc),
00412 allowSemi (false),
00413 processingBlock (false)
00414 {
00415 kdDebug(13030)<<"CREATING KATECSMART INTDETER"<<endl;
00416 }
00417
00418 KateCSmartIndent::~KateCSmartIndent ()
00419 {
00420
00421 }
00422
00423 void KateCSmartIndent::processLine (KateDocCursor &line)
00424 {
00425 kdDebug(13030)<<"PROCESSING LINE "<<line.line()<<endl;
00426 KateTextLine::Ptr textLine = doc->plainKateTextLine(line.line());
00427
00428 int firstChar = textLine->firstChar();
00429
00430 if (firstChar == -1 && processingBlock)
00431 return;
00432
00433 uint indent = 0;
00434
00435
00436 QChar first = textLine->getChar(firstChar);
00437 QChar last = textLine->getChar(textLine->lastChar());
00438
00439 if (first == '}')
00440 {
00441 indent = findOpeningBrace(line);
00442 }
00443 else if (first == ')')
00444 {
00445 indent = findOpeningParen(line);
00446 }
00447 else if (first == '{')
00448 {
00449
00450 KateDocCursor temp(line.line(), firstChar, doc);
00451 if (!firstOpeningBrace(temp))
00452 indent = calcIndent(temp, false);
00453 }
00454 else if (first == ':')
00455 {
00456
00457 int pos = findOpeningBrace(line);
00458 if (pos == 0)
00459 indent = indentWidth;
00460 else
00461 indent = pos + (indentWidth * 2);
00462 }
00463 else if (last == ':')
00464 {
00465 if (textLine->stringAtPos (firstChar, "case") ||
00466 textLine->stringAtPos (firstChar, "default") ||
00467 textLine->stringAtPos (firstChar, "public") ||
00468 textLine->stringAtPos (firstChar, "private") ||
00469 textLine->stringAtPos (firstChar, "protected") ||
00470 textLine->stringAtPos (firstChar, "signals") ||
00471 textLine->stringAtPos (firstChar, "Q_SIGNALS") ||
00472 textLine->stringAtPos (firstChar, "Q_SLOTS") ||
00473 textLine->stringAtPos (firstChar, "slots"))
00474 {
00475 indent = findOpeningBrace(line) + indentWidth;
00476 }
00477 }
00478 else if (first == '*')
00479 {
00480 if (last == '/')
00481 {
00482 int lineEnd = textLine->lastChar();
00483 if (lineEnd > 0 && textLine->getChar(lineEnd - 1) == '*')
00484 {
00485 indent = findOpeningComment(line);
00486 if (textLine->attribute(firstChar) == doxyCommentAttrib)
00487 indent++;
00488 }
00489 else
00490 return;
00491 }
00492 else
00493 {
00494 KateDocCursor temp = line;
00495 if (textLine->attribute(firstChar) == doxyCommentAttrib)
00496 indent = calcIndent(temp, false) + 1;
00497 else
00498 indent = calcIndent(temp, true);
00499 }
00500 }
00501 else if (first == '#')
00502 {
00503
00504 if (textLine->stringAtPos (firstChar, "#region") ||
00505 textLine->stringAtPos (firstChar, "#endregion"))
00506 {
00507 KateDocCursor temp = line;
00508 indent = calcIndent(temp, true);
00509 }
00510 }
00511 else
00512 {
00513
00514 if (first == '/' && last != '/')
00515 return;
00516
00517 KateDocCursor temp = line;
00518 indent = calcIndent(temp, true);
00519 if (indent == 0)
00520 {
00521 KateNormalIndent::processNewline(line, true);
00522 return;
00523 }
00524 }
00525
00526
00527 if (indent != measureIndent(line) || first == '}' || first == '{' || first == '#')
00528 {
00529 doc->removeText(line.line(), 0, line.line(), firstChar);
00530 QString filler = tabString(indent);
00531 if (indent > 0) doc->insertText(line.line(), 0, filler);
00532 if (!processingBlock) line.setCol(filler.length());
00533 }
00534 }
00535
00536 void KateCSmartIndent::processSection (const KateDocCursor &begin, const KateDocCursor &end)
00537 {
00538 kdDebug(13030)<<"PROCESS SECTION"<<endl;
00539 KateDocCursor cur = begin;
00540 QTime t;
00541 t.start();
00542
00543 processingBlock = (end.line() - cur.line() > 0) ? true : false;
00544
00545 while (cur.line() <= end.line())
00546 {
00547 processLine (cur);
00548 if (!cur.gotoNextLine())
00549 break;
00550 }
00551
00552 processingBlock = false;
00553 kdDebug(13030) << "+++ total: " << t.elapsed() << endl;
00554 }
00555
00556 bool KateCSmartIndent::handleDoxygen (KateDocCursor &begin)
00557 {
00558
00559 int line = begin.line();
00560 int first = -1;
00561 while ((line > 0) && (first < 0))
00562 first = doc->plainKateTextLine(--line)->firstChar();
00563
00564 if (first >= 0)
00565 {
00566 KateTextLine::Ptr textLine = doc->plainKateTextLine(line);
00567 bool insideDoxygen = false;
00568 bool justAfterDoxygen = false;
00569 if (textLine->attribute(first) == doxyCommentAttrib || textLine->attribute(textLine->lastChar()) == doxyCommentAttrib)
00570 {
00571 const int last = textLine->lastChar();
00572 if (last <= 0 || !(justAfterDoxygen = textLine->stringAtPos(last-1, "*/")))
00573 insideDoxygen = true;
00574 if (justAfterDoxygen)
00575 justAfterDoxygen &= textLine->string().find("/**") < 0;
00576 while (textLine->attribute(first) != doxyCommentAttrib && first <= textLine->lastChar())
00577 first++;
00578 if (textLine->stringAtPos(first, "//"))
00579 return false;
00580 }
00581
00582
00583 if (insideDoxygen)
00584 {
00585 textLine = doc->plainKateTextLine(begin.line());
00586 first = textLine->firstChar();
00587 int indent = findOpeningComment(begin);
00588 QString filler = tabString (indent);
00589
00590 bool doxygenAutoInsert = doc->config()->configFlags() & KateDocumentConfig::cfDoxygenAutoTyping;
00591
00592 if ( doxygenAutoInsert &&
00593 ((first < 0) || (!textLine->stringAtPos(first, "*/") && !textLine->stringAtPos(first, "*"))))
00594 {
00595 filler = filler + " * ";
00596 }
00597
00598 doc->removeText (begin.line(), 0, begin.line(), first);
00599 doc->insertText (begin.line(), 0, filler);
00600 begin.setCol(filler.length());
00601
00602 return true;
00603 }
00604
00605
00606 else if (justAfterDoxygen)
00607 {
00608 textLine = doc->plainKateTextLine(begin.line());
00609 first = textLine->firstChar();
00610 int indent = findOpeningComment(begin);
00611 QString filler = tabString (indent);
00612
00613 doc->removeText (begin.line(), 0, begin.line(), first);
00614 doc->insertText (begin.line(), 0, filler);
00615 begin.setCol(filler.length());
00616
00617 return true;
00618 }
00619 }
00620
00621 return false;
00622 }
00623
00624 void KateCSmartIndent::processNewline (KateDocCursor &begin, bool needContinue)
00625 {
00626 if (!handleDoxygen (begin))
00627 {
00628 KateTextLine::Ptr textLine = doc->plainKateTextLine(begin.line());
00629 bool inMiddle = textLine->firstChar() > -1;
00630
00631 int indent = calcIndent (begin, needContinue);
00632
00633 if (indent > 0 || inMiddle)
00634 {
00635 QString filler = tabString (indent);
00636 doc->insertText (begin.line(), 0, filler);
00637 begin.setCol(filler.length());
00638
00639
00640 if (inMiddle)
00641 {
00642 processLine(begin);
00643 begin.setCol(textLine->firstChar());
00644 }
00645 }
00646 else
00647 {
00648 KateNormalIndent::processNewline (begin, needContinue);
00649 }
00650
00651 if (begin.col() < 0)
00652 begin.setCol(0);
00653 }
00654 }
00655
00656 void KateCSmartIndent::processChar(QChar c)
00657 {
00658
00659
00660
00661 static const QString triggers("}{)/:#n");
00662 static const QString firstTriggers("}{)/:#");
00663 static const QString lastTriggers(":n");
00664 if (triggers.find(c) < 0)
00665 return;
00666
00667 KateView *view = doc->activeView();
00668 KateDocCursor begin(view->cursorLine(), 0, doc);
00669
00670 KateTextLine::Ptr textLine = doc->plainKateTextLine(begin.line());
00671 const int first = textLine->firstChar();
00672 const QChar firstChar = textLine->getChar(first);
00673 if (c == 'n')
00674 {
00675 if (firstChar != '#')
00676 return;
00677 }
00678
00679 if ( c == '/' )
00680 {
00681
00682 if ( textLine->attribute( begin.col() ) == doxyCommentAttrib )
00683 {
00684
00685
00686 if ( first != -1
00687 && firstChar == '*'
00688 && textLine->nextNonSpaceChar( first+1 ) == view->cursorColumnReal()-1 )
00689 doc->removeText( view->cursorLine(), first+1, view->cursorLine(), view->cursorColumnReal()-1);
00690 }
00691
00692
00693 return;
00694 }
00695
00696
00697
00698
00699
00700 const QChar lastChar = textLine->getChar(textLine->lastChar());
00701 if ((c == firstChar && firstTriggers.find(firstChar) >= 0)
00702 || (c == lastChar && lastTriggers.find(lastChar) >= 0))
00703 processLine(begin);
00704 }
00705
00706
00707 uint KateCSmartIndent::calcIndent(KateDocCursor &begin, bool needContinue)
00708 {
00709 KateTextLine::Ptr textLine;
00710 KateDocCursor cur = begin;
00711
00712 uint anchorIndent = 0;
00713 int anchorPos = 0;
00714 int parenCount = 0;
00715 bool found = false;
00716 bool isSpecial = false;
00717
00718
00719
00720
00721 while (cur.gotoPreviousLine())
00722 {
00723 isSpecial = found = false;
00724 textLine = doc->plainKateTextLine(cur.line());
00725
00726
00727 int pos = textLine->lastChar();
00728 int openCount = 0;
00729 int otherAnchor = -1;
00730 do
00731 {
00732 if (textLine->attribute(pos) == symbolAttrib)
00733 {
00734 QChar tc = textLine->getChar (pos);
00735 if ((tc == ';' || tc == ':' || tc == ',') && otherAnchor == -1 && parenCount <= 0)
00736 otherAnchor = pos;
00737 else if (tc == ')')
00738 parenCount++;
00739 else if (tc == '(')
00740 parenCount--;
00741 else if (tc == '}')
00742 openCount--;
00743 else if (tc == '{')
00744 {
00745 openCount++;
00746 if (openCount == 1)
00747 break;
00748 }
00749 }
00750 } while (--pos >= textLine->firstChar());
00751
00752 if (openCount != 0 || otherAnchor != -1)
00753 {
00754 found = true;
00755 QChar c;
00756 if (openCount > 0)
00757 c = '{';
00758 else if (openCount < 0)
00759 c = '}';
00760 else if (otherAnchor >= 0)
00761 c = textLine->getChar (otherAnchor);
00762
00763 int specialIndent = 0;
00764 if (c == ':' && needContinue)
00765 {
00766 QChar ch;
00767 specialIndent = textLine->firstChar();
00768 if (textLine->stringAtPos(specialIndent, "case"))
00769 ch = textLine->getChar(specialIndent + 4);
00770 else if (textLine->stringAtPos(specialIndent, "default"))
00771 ch = textLine->getChar(specialIndent + 7);
00772 else if (textLine->stringAtPos(specialIndent, "public"))
00773 ch = textLine->getChar(specialIndent + 6);
00774 else if (textLine->stringAtPos(specialIndent, "private"))
00775 ch = textLine->getChar(specialIndent + 7);
00776 else if (textLine->stringAtPos(specialIndent, "protected"))
00777 ch = textLine->getChar(specialIndent + 9);
00778 else if (textLine->stringAtPos(specialIndent, "signals"))
00779 ch = textLine->getChar(specialIndent + 7);
00780 else if (textLine->stringAtPos(specialIndent, "Q_SIGNALS"))
00781 ch = textLine->getChar(specialIndent + 9);
00782 else if (textLine->stringAtPos(specialIndent, "slots"))
00783 ch = textLine->getChar(specialIndent + 5);
00784 else if (textLine->stringAtPos(specialIndent, "Q_SLOTS"))
00785 ch = textLine->getChar(specialIndent + 7);
00786
00787 if (ch.isNull() || (!ch.isSpace() && ch != '(' && ch != ':'))
00788 continue;
00789
00790 KateDocCursor lineBegin = cur;
00791 lineBegin.setCol(specialIndent);
00792 specialIndent = measureIndent(lineBegin);
00793 isSpecial = true;
00794 }
00795
00796
00797 KateDocCursor skip = cur;
00798 skip.setCol(textLine->lastChar());
00799 bool result = skipBlanks(skip, begin, true);
00800
00801 anchorPos = skip.col();
00802 anchorIndent = measureIndent(skip);
00803
00804
00805
00806
00807 if (result && skip < begin)
00808 {
00809 cur = skip;
00810 break;
00811 }
00812 else if (isSpecial)
00813 {
00814 anchorIndent = specialIndent;
00815 break;
00816 }
00817
00818
00819 if ((c == '{' || c == '}') && textLine->getChar(textLine->firstChar()) == c)
00820 {
00821 cur.setCol(anchorPos = textLine->firstChar());
00822 anchorIndent = measureIndent (cur);
00823 break;
00824 }
00825 }
00826 }
00827
00828
00829 if (cur.line() == 0 && cur.col() == 0)
00830 found = true;
00831
00832 if (!found)
00833 return 0;
00834
00835 uint continueIndent = (needContinue) ? calcContinue (cur, begin) : 0;
00836
00837
00838
00839
00840 textLine = doc->plainKateTextLine(cur.line());
00841 QChar lastChar = textLine->getChar (anchorPos);
00842 int lastLine = cur.line();
00843 if (lastChar == '#' || lastChar == '[')
00844 {
00845
00846
00847 continueIndent = 0;
00848 }
00849
00850 int openCount = 0;
00851 while (cur.validPosition() && cur < begin)
00852 {
00853 if (!skipBlanks(cur, begin, true))
00854 return 0;
00855
00856 QChar tc = cur.currentChar();
00857
00858 if (cur == begin || tc.isNull())
00859 break;
00860
00861 if (!tc.isSpace() && cur < begin)
00862 {
00863 uchar attrib = cur.currentAttrib();
00864 if (tc == '{' && attrib == symbolAttrib)
00865 openCount++;
00866 else if (tc == '}' && attrib == symbolAttrib)
00867 openCount--;
00868
00869 lastChar = tc;
00870 lastLine = cur.line();
00871 }
00872 }
00873 if (openCount > 0)
00874 lastChar = '{';
00875
00876 uint indent = 0;
00877
00878
00879 if (lastChar == '{' || (lastChar == ':' && isSpecial && needContinue))
00880 {
00881 indent = anchorIndent + indentWidth;
00882 }
00883 else if (lastChar == '}')
00884 {
00885 indent = anchorIndent;
00886 }
00887 else if (lastChar == ';')
00888 {
00889 indent = anchorIndent + ((allowSemi && needContinue) ? continueIndent : 0);
00890 }
00891 else if (lastChar == ',')
00892 {
00893 textLine = doc->plainKateTextLine(lastLine);
00894 KateDocCursor start(lastLine, textLine->firstChar(), doc);
00895 KateDocCursor finish(lastLine, textLine->lastChar(), doc);
00896 uint pos = 0;
00897
00898 if (isBalanced(start, finish, QChar('('), QChar(')'), pos))
00899 indent = anchorIndent;
00900 else
00901 {
00902
00903 indent = ((pos < 48) ? pos : anchorIndent + (indentWidth * 2));
00904 }
00905 }
00906 else if (!lastChar.isNull())
00907 {
00908 if (anchorIndent != 0)
00909 indent = anchorIndent + continueIndent;
00910 else
00911 indent = continueIndent;
00912 }
00913
00914 return indent;
00915 }
00916
00917 uint KateCSmartIndent::calcContinue(KateDocCursor &start, KateDocCursor &end)
00918 {
00919 KateDocCursor cur = start;
00920
00921 bool needsBalanced = true;
00922 bool isFor = false;
00923 allowSemi = false;
00924
00925 KateTextLine::Ptr textLine = doc->plainKateTextLine(cur.line());
00926
00927
00928 if (textLine->attribute(cur.col()) == symbolAttrib)
00929 {
00930 cur.moveForward(1);
00931 skipBlanks(cur, end, false);
00932 }
00933
00934 if (textLine->getChar(cur.col()) == '}')
00935 {
00936 skipBlanks(cur, end, true);
00937 if (cur.line() != start.line())
00938 textLine = doc->plainKateTextLine(cur.line());
00939
00940 if (textLine->stringAtPos(cur.col(), "else"))
00941 cur.setCol(cur.col() + 4);
00942 else
00943 return indentWidth * 2;
00944
00945 needsBalanced = false;
00946 }
00947 else if (textLine->stringAtPos(cur.col(), "else"))
00948 {
00949 cur.setCol(cur.col() + 4);
00950 needsBalanced = false;
00951 int next = textLine->nextNonSpaceChar(cur.col());
00952 if (next >= 0 && textLine->stringAtPos(next, "if"))
00953 {
00954 cur.setCol(next + 2);
00955 needsBalanced = true;
00956 }
00957 }
00958 else if (textLine->stringAtPos(cur.col(), "if"))
00959 {
00960 cur.setCol(cur.col() + 2);
00961 }
00962 else if (textLine->stringAtPos(cur.col(), "do"))
00963 {
00964 cur.setCol(cur.col() + 2);
00965 needsBalanced = false;
00966 }
00967 else if (textLine->stringAtPos(cur.col(), "for"))
00968 {
00969 cur.setCol(cur.col() + 3);
00970 isFor = true;
00971 }
00972 else if (textLine->stringAtPos(cur.col(), "while"))
00973 {
00974 cur.setCol(cur.col() + 5);
00975 }
00976 else if (textLine->stringAtPos(cur.col(), "switch"))
00977 {
00978 cur.setCol(cur.col() + 6);
00979 }
00980 else if (textLine->stringAtPos(cur.col(), "using"))
00981 {
00982 cur.setCol(cur.col() + 5);
00983 }
00984 else
00985 {
00986 return indentWidth * 2;
00987 }
00988
00989 uint openPos = 0;
00990 if (needsBalanced && !isBalanced (cur, end, QChar('('), QChar(')'), openPos))
00991 {
00992 allowSemi = isFor;
00993 if (openPos > 0)
00994 return (openPos - textLine->firstChar());
00995 else
00996 return indentWidth * 2;
00997 }
00998
00999
01000 skipBlanks(cur, end, false);
01001 if (cur == end)
01002 return indentWidth;
01003
01004 if (skipBlanks(cur, end, true))
01005 {
01006 if (cur == end)
01007 return indentWidth;
01008 else
01009 return indentWidth + calcContinue(cur, end);
01010 }
01011
01012 return 0;
01013 }
01014
01015 uint KateCSmartIndent::findOpeningBrace(KateDocCursor &start)
01016 {
01017 KateDocCursor cur = start;
01018 int count = 1;
01019
01020
01021
01022 while (cur.moveBackward(1))
01023 {
01024 if (cur.currentAttrib() == symbolAttrib)
01025 {
01026 QChar ch = cur.currentChar();
01027 if (ch == '{')
01028 count--;
01029 else if (ch == '}')
01030 count++;
01031
01032 if (count == 0)
01033 {
01034 KateDocCursor temp(cur.line(), doc->plainKateTextLine(cur.line())->firstChar(), doc);
01035 return measureIndent(temp);
01036 }
01037 }
01038 }
01039
01040 return 0;
01041 }
01042
01043 bool KateCSmartIndent::firstOpeningBrace(KateDocCursor &start)
01044 {
01045 KateDocCursor cur = start;
01046
01047
01048 while(cur.moveBackward(1))
01049 {
01050 if (cur.currentAttrib() == symbolAttrib)
01051 {
01052 QChar ch = cur.currentChar();
01053 if (ch == '{')
01054 return false;
01055 else if (ch == '}' && cur.col() == 0)
01056 break;
01057 }
01058 }
01059
01060 return true;
01061 }
01062
01063 uint KateCSmartIndent::findOpeningParen(KateDocCursor &start)
01064 {
01065 KateDocCursor cur = start;
01066 int count = 1;
01067
01068
01069
01070 while (cur.moveBackward(1))
01071 {
01072 if (cur.currentAttrib() == symbolAttrib)
01073 {
01074 QChar ch = cur.currentChar();
01075 if (ch == '(')
01076 count--;
01077 else if (ch == ')')
01078 count++;
01079
01080 if (count == 0)
01081 return measureIndent(cur);
01082 }
01083 }
01084
01085 return 0;
01086 }
01087
01088 uint KateCSmartIndent::findOpeningComment(KateDocCursor &start)
01089 {
01090 KateDocCursor cur = start;
01091
01092
01093 do
01094 {
01095 KateTextLine::Ptr textLine = doc->plainKateTextLine(cur.line());
01096
01097 int pos = textLine->string().find("/*", false);
01098 if (pos >= 0)
01099 {
01100 KateDocCursor temp(cur.line(), pos, doc);
01101 return measureIndent(temp);
01102 }
01103
01104 } while (cur.gotoPreviousLine());
01105
01106 return 0;
01107 }
01108
01109
01110
01111
01112
01113 QRegExp KatePythonIndent::endWithColon = QRegExp( "^[^#]*:\\s*(#.*)?$" );
01114 QRegExp KatePythonIndent::stopStmt = QRegExp( "^\\s*(break|continue|raise|return|pass)\\b.*" );
01115 QRegExp KatePythonIndent::blockBegin = QRegExp( "^\\s*(class|def|if|elif|else|for|while|try)\\b.*" );
01116
01117 KatePythonIndent::KatePythonIndent (KateDocument *doc)
01118 : KateNormalIndent (doc)
01119 {
01120 }
01121 KatePythonIndent::~KatePythonIndent ()
01122 {
01123 }
01124
01125 void KatePythonIndent::processNewline (KateDocCursor &begin, bool )
01126 {
01127 int prevLine = begin.line() - 1;
01128 int prevPos = begin.col();
01129
01130 while ((prevLine > 0) && (prevPos < 0))
01131 prevPos = doc->plainKateTextLine(--prevLine)->firstChar();
01132
01133 int prevBlock = prevLine;
01134 int prevBlockPos = prevPos;
01135 int extraIndent = calcExtra (prevBlock, prevBlockPos, begin);
01136
01137 int indent = doc->plainKateTextLine(prevBlock)->cursorX(prevBlockPos, tabWidth);
01138 if (extraIndent == 0)
01139 {
01140 if (!stopStmt.exactMatch(doc->plainKateTextLine(prevLine)->string()))
01141 {
01142 if (endWithColon.exactMatch(doc->plainKateTextLine(prevLine)->string()))
01143 indent += indentWidth;
01144 else
01145 indent = doc->plainKateTextLine(prevLine)->cursorX(prevPos, tabWidth);
01146 }
01147 }
01148 else
01149 indent += extraIndent;
01150
01151 if (indent > 0)
01152 {
01153 QString filler = tabString (indent);
01154 doc->insertText (begin.line(), 0, filler);
01155 begin.setCol(filler.length());
01156 }
01157 else
01158 begin.setCol(0);
01159 }
01160
01161 int KatePythonIndent::calcExtra (int &prevBlock, int &pos, KateDocCursor &end)
01162 {
01163 int nestLevel = 0;
01164 bool levelFound = false;
01165 while ((prevBlock > 0))
01166 {
01167 if (blockBegin.exactMatch(doc->plainKateTextLine(prevBlock)->string()))
01168 {
01169 if ((!levelFound && nestLevel == 0) || (levelFound && nestLevel - 1 <= 0))
01170 {
01171 pos = doc->plainKateTextLine(prevBlock)->firstChar();
01172 break;
01173 }
01174
01175 nestLevel --;
01176 }
01177 else if (stopStmt.exactMatch(doc->plainKateTextLine(prevBlock)->string()))
01178 {
01179 nestLevel ++;
01180 levelFound = true;
01181 }
01182
01183 --prevBlock;
01184 }
01185
01186 KateDocCursor cur (prevBlock, pos, doc);
01187 QChar c;
01188 int extraIndent = 0;
01189 while (cur.line() < end.line())
01190 {
01191 c = cur.currentChar();
01192
01193 if (c == '(')
01194 extraIndent += indentWidth;
01195 else if (c == ')')
01196 extraIndent -= indentWidth;
01197 else if (c == ':')
01198 break;
01199 else if (c == '\'' || c == '"' )
01200 traverseString( c, cur, end );
01201
01202 if (c.isNull() || c == '#')
01203 cur.gotoNextLine();
01204 else
01205 cur.moveForward(1);
01206 }
01207
01208 return extraIndent;
01209 }
01210
01211 void KatePythonIndent::traverseString( const QChar &stringChar, KateDocCursor &cur, KateDocCursor &end )
01212 {
01213 QChar c;
01214 bool escape = false;
01215
01216 cur.moveForward(1);
01217 c = cur.currentChar();
01218 while ( ( c != stringChar || escape ) && cur.line() < end.line() )
01219 {
01220 if ( escape )
01221 escape = false;
01222 else if ( c == '\\' )
01223 escape = !escape;
01224
01225 cur.moveForward(1);
01226 c = cur.currentChar();
01227 }
01228 }
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256 const QRegExp KateXmlIndent::startsWithCloseTag("^[ \t]*</");
01257 const QRegExp KateXmlIndent::unclosedDoctype("<!DOCTYPE[^>]*$");
01258
01259 KateXmlIndent::KateXmlIndent (KateDocument *doc)
01260 : KateNormalIndent (doc)
01261 {
01262 }
01263
01264 KateXmlIndent::~KateXmlIndent ()
01265 {
01266 }
01267
01268 void KateXmlIndent::processNewline (KateDocCursor &begin, bool )
01269 {
01270 begin.setCol(processLine(begin.line()));
01271 }
01272
01273 void KateXmlIndent::processChar (QChar c)
01274 {
01275 if(c != '/') return;
01276
01277
01278 KateView *view = doc->activeView();
01279 QString text = doc->plainKateTextLine(view->cursorLine())->string();
01280 if(text.find(startsWithCloseTag) == -1) return;
01281
01282
01283 processLine(view->cursorLine());
01284 }
01285
01286 void KateXmlIndent::processLine (KateDocCursor &line)
01287 {
01288 processLine (line.line());
01289 }
01290
01291 void KateXmlIndent::processSection (const KateDocCursor &start, const KateDocCursor &end)
01292 {
01293 KateDocCursor cur (start);
01294 int endLine = end.line();
01295
01296 do {
01297 processLine(cur.line());
01298 if(!cur.gotoNextLine()) break;
01299 } while(cur.line() < endLine);
01300 }
01301
01302 void KateXmlIndent::getLineInfo (uint line, uint &prevIndent, int &numTags,
01303 uint &attrCol, bool &unclosedTag)
01304 {
01305 prevIndent = 0;
01306 int firstChar;
01307 KateTextLine::Ptr prevLine = 0;
01308
01309
01310 while(true) {
01311 prevLine = doc->plainKateTextLine(line);
01312 if( (firstChar = prevLine->firstChar()) < 0) {
01313 if(!line--) return;
01314 continue;
01315 }
01316 break;
01317 }
01318 prevIndent = prevLine->cursorX(prevLine->firstChar(), tabWidth);
01319 QString text = prevLine->string();
01320
01321
01322
01323
01324
01325 if(text.find(startsWithCloseTag) != -1) ++numTags;
01326
01327
01328 int lastCh = 0;
01329 uint pos, len = text.length();
01330 bool seenOpen = false;
01331 for(pos = 0; pos < len; ++pos) {
01332 int ch = text.at(pos).unicode();
01333 switch(ch) {
01334 case '<':
01335 seenOpen = true;
01336 unclosedTag = true;
01337 attrCol = pos;
01338 ++numTags;
01339 break;
01340
01341
01342 case '!':
01343 if(lastCh == '<') --numTags;
01344 break;
01345
01346
01347 case '?':
01348 if(lastCh == '<') --numTags;
01349 break;
01350
01351 case '>':
01352 if(!seenOpen) {
01353
01354
01355
01356
01357
01358
01359
01360
01361 prevIndent = 0;
01362
01363 for(uint backLine = line; backLine; ) {
01364
01365 KateTextLine::Ptr x = doc->plainKateTextLine(--backLine);
01366 if(x->string().find('<') == -1) continue;
01367
01368
01369 if(x->string().find(unclosedDoctype) != -1) --numTags;
01370 getLineInfo(backLine, prevIndent, numTags, attrCol, unclosedTag);
01371 break;
01372 }
01373 }
01374 if(lastCh == '/') --numTags;
01375 unclosedTag = false;
01376 break;
01377
01378 case '/':
01379 if(lastCh == '<') numTags -= 2;
01380 break;
01381 }
01382 lastCh = ch;
01383 }
01384
01385 if(unclosedTag) {
01386
01387 do {
01388 lastCh = text.at(++attrCol).unicode();
01389 }while(lastCh && lastCh != ' ' && lastCh != '\t');
01390
01391 while(lastCh == ' ' || lastCh == '\t') {
01392 lastCh = text.at(++attrCol).unicode();
01393 }
01394
01395 attrCol = prevLine->cursorX(attrCol, tabWidth);
01396 }
01397 }
01398
01399 uint KateXmlIndent::processLine (uint line)
01400 {
01401 KateTextLine::Ptr kateLine = doc->plainKateTextLine(line);
01402 if(!kateLine) return 0;
01403
01404
01405 uint prevIndent = 0, attrCol = 0;
01406 int numTags = 0;
01407 bool unclosedTag = false;
01408
01409 if(line) {
01410 getLineInfo(line - 1, prevIndent, numTags, attrCol, unclosedTag);
01411 }
01412
01413
01414 int indent = 0;
01415 if(unclosedTag) indent = attrCol;
01416 else indent = prevIndent + numTags * indentWidth;
01417 if(indent < 0) indent = 0;
01418
01419
01420 if(kateLine->string().find(startsWithCloseTag) != -1) {
01421 indent -= indentWidth;
01422 }
01423 if(indent < 0) indent = 0;
01424
01425
01426 doc->removeText(line, 0, line, kateLine->firstChar());
01427 QString filler = tabString(indent);
01428 doc->insertText(line, 0, filler);
01429
01430 return filler.length();
01431 }
01432
01433
01434
01435
01436
01437 KateCSAndSIndent::KateCSAndSIndent (KateDocument *doc)
01438 : KateNormalIndent (doc)
01439 {
01440 }
01441
01442 void KateCSAndSIndent::updateIndentString()
01443 {
01444 if( useSpaces )
01445 indentString.fill( ' ', indentWidth );
01446 else
01447 indentString = '\t';
01448 }
01449
01450 KateCSAndSIndent::~KateCSAndSIndent ()
01451 {
01452 }
01453
01454 void KateCSAndSIndent::processLine (KateDocCursor &line)
01455 {
01456 KateTextLine::Ptr textLine = doc->plainKateTextLine(line.line());
01457
01458 if (!textLine)
01459 return;
01460
01461 updateIndentString();
01462
01463 const int oldCol = line.col();
01464 QString whitespace = calcIndent(line);
01465
01466 int oldIndent = textLine->firstChar();
01467 if ( oldIndent < 0 )
01468 oldIndent = doc->lineLength( line.line() );
01469 if( oldIndent > 0 )
01470 doc->removeText(line.line(), 0, line.line(), oldIndent);
01471
01472 doc->insertText(line.line(), 0, whitespace);
01473
01474
01475 if ( int(oldCol + whitespace.length()) >= oldIndent )
01476 line.setCol( oldCol + whitespace.length() - oldIndent );
01477 else
01478 line.setCol( 0 );
01479 }
01480
01481 void KateCSAndSIndent::processSection (const KateDocCursor &begin, const KateDocCursor &end)
01482 {
01483 QTime t; t.start();
01484 for( KateDocCursor cur = begin; cur.line() <= end.line(); )
01485 {
01486 processLine (cur);
01487 if (!cur.gotoNextLine())
01488 break;
01489 }
01490 kdDebug(13030) << "+++ total: " << t.elapsed() << endl;
01491 }
01492
01498 static QString initialWhitespace(const KateTextLine::Ptr &line, int chars, bool convert = true)
01499 {
01500 QString text = line->string(0, chars);
01501 if( (int)text.length() < chars )
01502 {
01503 QString filler; filler.fill(' ',chars - text.length());
01504 text += filler;
01505 }
01506 for( uint n = 0; n < text.length(); ++n )
01507 {
01508 if( text[n] != '\t' && text[n] != ' ' )
01509 {
01510 if( !convert )
01511 return text.left( n );
01512 text[n] = ' ';
01513 }
01514 }
01515 return text;
01516 }
01517
01518 QString KateCSAndSIndent::findOpeningCommentIndentation(const KateDocCursor &start)
01519 {
01520 KateDocCursor cur = start;
01521
01522
01523 do
01524 {
01525 KateTextLine::Ptr textLine = doc->plainKateTextLine(cur.line());
01526
01527 int pos = textLine->string().findRev("/*");
01528
01529 if (pos >= 0)
01530 return initialWhitespace(textLine, pos);
01531 } while (cur.gotoPreviousLine());
01532
01533
01534 kdWarning( 13030 ) << " in a comment, but can't find the start of it" << endl;
01535 return QString::null;
01536 }
01537
01538 bool KateCSAndSIndent::handleDoxygen (KateDocCursor &begin)
01539 {
01540
01541 int line = begin.line();
01542 int first = -1;
01543 while ((line > 0) && (first < 0))
01544 first = doc->plainKateTextLine(--line)->firstChar();
01545
01546
01547 if (first < 0)
01548 return false;
01549
01550 KateTextLine::Ptr textLine = doc->plainKateTextLine(line);
01551
01552
01553
01554
01555
01556 if ( !(textLine->attribute(textLine->lastChar()) == doxyCommentAttrib && !textLine->endingWith("*/")) &&
01557 !(textLine->attribute(textLine->firstChar()) == doxyCommentAttrib && !textLine->string().contains("*/")) )
01558 return false;
01559
01560
01561 textLine = doc->plainKateTextLine(begin.line());
01562 first = textLine->firstChar();
01563 QString indent = findOpeningCommentIndentation(begin);
01564
01565 bool doxygenAutoInsert = doc->config()->configFlags() & KateDocumentConfig::cfDoxygenAutoTyping;
01566
01567
01568 if ( first >= 0 && textLine->stringAtPos(first, "*") )
01569 indent = indent + " ";
01570
01571 else if ( doxygenAutoInsert )
01572 indent = indent + " * ";
01573
01574
01575
01576
01577 doc->removeText (begin.line(), 0, begin.line(), first);
01578 doc->insertText (begin.line(), 0, indent);
01579 begin.setCol(indent.length());
01580
01581 return true;
01582 }
01583
01590 void KateCSAndSIndent::processNewline (KateDocCursor &begin, bool )
01591 {
01592
01593 if( handleDoxygen(begin) )
01594 return;
01595
01596
01597
01598
01599
01600 int cursorPos = doc->plainKateTextLine( begin.line() )->firstChar();
01601 if ( cursorPos < 0 )
01602 cursorPos = doc->lineLength( begin.line() );
01603 begin.setCol( cursorPos );
01604
01605 processLine( begin );
01606 }
01607
01612 bool KateCSAndSIndent::startsWithLabel( int line )
01613 {
01614
01615 KateTextLine::Ptr indentLine = doc->plainKateTextLine(line);
01616 const int indentFirst = indentLine->firstChar();
01617
01618
01619 int attrib = indentLine->attribute(indentFirst);
01620 if (attrib != 0 && attrib != keywordAttrib && attrib != normalAttrib && attrib != extensionAttrib)
01621 return false;
01622
01623
01624 const QString lineContents = indentLine->string();
01625 const int indentLast = indentLine->lastChar();
01626 bool whitespaceFound = false;
01627 for ( int n = indentFirst; n <= indentLast; ++n )
01628 {
01629
01630
01631 char c = lineContents[n].latin1();
01632 if ( c == ':' )
01633 {
01634
01635 if ( n < lineContents.length() - 1 )
01636 {
01637 if ( lineContents[n+1].latin1() == ':' )
01638 {
01639 n += 2;
01640 continue;
01641 }
01642 }
01643
01644 if ( n == indentFirst)
01645 {
01646
01647 return false;
01648 }
01649
01650 return true;
01651 }
01652 if (isspace(c))
01653 {
01654 if (!whitespaceFound)
01655 {
01656 if (lineContents.mid(indentFirst, n - indentFirst) == "case")
01657 return true;
01658 else if (lineContents.mid(indentFirst, n - indentFirst) == "class")
01659 return false;
01660 whitespaceFound = true;
01661 }
01662 }
01663
01664 else if ( !isalnum(c) && c != '_' )
01665 {
01666 return false;
01667 }
01668 }
01669 return false;
01670 }
01671
01672 template<class T> T min(T a, T b) { return (a < b) ? a : b; }
01673
01674 int KateCSAndSIndent::lastNonCommentChar( const KateDocCursor &line )
01675 {
01676 KateTextLine::Ptr textLine = doc->plainKateTextLine( line.line() );
01677 QString str = textLine->string();
01678
01679
01680 int p = -2;
01681 do p = str.find( "//", p + 2 );
01682 while ( p >= 0 && textLine->attribute(p) != commentAttrib && textLine->attribute(p) != doxyCommentAttrib );
01683
01684
01685 if ( p < 0 )
01686 p = str.length();
01687
01688
01689 while( p > 0 && str[p-1].isSpace() ) --p;
01690 return p - 1;
01691 }
01692
01693 bool KateCSAndSIndent::inForStatement( int line )
01694 {
01695
01696
01697 int parens = 0, semicolons = 0;
01698 for ( ; line >= 0; --line )
01699 {
01700 KateTextLine::Ptr textLine = doc->plainKateTextLine(line);
01701 const int first = textLine->firstChar();
01702 const int last = textLine->lastChar();
01703
01704
01705
01706
01707
01708 for ( int curr = last; curr >= first; --curr )
01709 {
01710 if ( textLine->attribute(curr) != symbolAttrib )
01711 continue;
01712
01713 switch( textLine->getChar(curr) )
01714 {
01715 case ';':
01716 if( ++semicolons > 2 )
01717 return false;
01718 break;
01719 case '{': case '}':
01720 return false;
01721 case ')':
01722 ++parens;
01723 break;
01724 case '(':
01725 if( --parens < 0 )
01726 return true;
01727 break;
01728 }
01729 }
01730 }
01731
01732
01733 return false;
01734 }
01735
01736
01737
01738 bool KateCSAndSIndent::inStatement( const KateDocCursor &begin )
01739 {
01740
01741
01742 KateTextLine::Ptr textLine = doc->plainKateTextLine(begin.line());
01743 const int first = textLine->firstChar();
01744
01745
01746
01747 const int attrib = textLine->attribute(first);
01748 if( first >= 0 && (attrib == 0 || attrib == symbolAttrib) && textLine->getChar(first) == '{' )
01749 return false;
01750
01751 int line;
01752 for ( line = begin.line() - 1; line >= 0; --line )
01753 {
01754 textLine = doc->plainKateTextLine(line);
01755 const int first = textLine->firstChar();
01756 if ( first == -1 )
01757 continue;
01758
01759
01760
01761 if ( textLine->getChar( first ) == '#' )
01762 continue;
01763 KateDocCursor currLine = begin;
01764 currLine.setLine( line );
01765 const int last = lastNonCommentChar( currLine );
01766 if ( last < first )
01767 continue;
01768
01769
01770
01771
01772
01773
01774 const int attrib = textLine->attribute(last);
01775 if ( attrib == commentAttrib || attrib == doxyCommentAttrib )
01776 return false;
01777
01778 char c = textLine->getChar(last);
01779
01780
01781 if ( attrib == symbolAttrib && c == '{' || c == '}' )
01782 return false;
01783
01784
01785 if ( attrib == symbolAttrib && c == ';' )
01786 return inForStatement( line );
01787
01788
01789 if ( attrib == symbolAttrib && c == ':' )
01790 {
01791
01792
01793
01794
01795 if( startsWithLabel( line ) )
01796 {
01797
01798
01799
01800
01801 continue;
01802 }
01803 }
01804
01805
01806 return true;
01807 }
01808
01809 return false;
01810 }
01811
01812 QString KateCSAndSIndent::continuationIndent( const KateDocCursor &begin )
01813 {
01814 if( !inStatement( begin ) )
01815 return QString::null;
01816 return indentString;
01817 }
01818
01822 QString KateCSAndSIndent::calcIndent (const KateDocCursor &begin)
01823 {
01824 KateTextLine::Ptr currLine = doc->plainKateTextLine(begin.line());
01825 int currLineFirst = currLine->firstChar();
01826
01827
01828
01829
01830 if ( currLineFirst >= 0 &&
01831 (currLine->attribute(currLineFirst) == commentAttrib ||
01832 currLine->attribute(currLineFirst) == doxyCommentAttrib) )
01833 return currLine->string( 0, currLineFirst );
01834
01835
01836 if( currLineFirst >= 0 && currLine->getChar(currLineFirst) == '#' )
01837 {
01838 if( !currLine->stringAtPos( currLineFirst+1, QString::fromLatin1("region") ) &&
01839 !currLine->stringAtPos( currLineFirst+1, QString::fromLatin1("endregion") ) )
01840 return QString::null;
01841 }
01842
01843
01844
01845
01846
01847
01848
01849
01850 KateDocCursor cur = begin;
01851 int pos, openBraceCount = 0, openParenCount = 0;
01852 bool lookingForScopeKeywords = true;
01853 const char * const scopeKeywords[] = { "for", "do", "while", "if", "else" };
01854 const char * const blockScopeKeywords[] = { "try", "catch", "switch" };
01855
01856 while (cur.gotoPreviousLine())
01857 {
01858 KateTextLine::Ptr textLine = doc->plainKateTextLine(cur.line());
01859 const int lastChar = textLine->lastChar();
01860 const int firstChar = textLine->firstChar();
01861
01862
01863 for( pos = lastChar; pos >= firstChar; --pos )
01864 {
01865 if (textLine->attribute(pos) == symbolAttrib)
01866 {
01867 char tc = textLine->getChar (pos);
01868 switch( tc )
01869 {
01870 case '(': case '[':
01871 if( ++openParenCount > 0 )
01872 return calcIndentInBracket( begin, cur, pos );
01873 break;
01874 case ')': case ']': openParenCount--; break;
01875 case '{':
01876 if( ++openBraceCount > 0 )
01877 return calcIndentInBrace( begin, cur, pos );
01878 break;
01879 case '}': openBraceCount--; lookingForScopeKeywords = false; break;
01880 case ';':
01881 if( openParenCount == 0 )
01882 lookingForScopeKeywords = false;
01883 break;
01884 }
01885 }
01886
01887
01888
01889 if ( lookingForScopeKeywords && openParenCount == 0 &&
01890 textLine->attribute(pos) == keywordAttrib &&
01891 (pos == 0 || textLine->attribute(pos-1) != keywordAttrib ) )
01892 {
01893 #define ARRLEN( array ) ( sizeof(array)/sizeof(array[0]) )
01894 for( uint n = 0; n < ARRLEN(scopeKeywords); ++n )
01895 if( textLine->stringAtPos(pos, QString::fromLatin1(scopeKeywords[n]) ) )
01896 return calcIndentAfterKeyword( begin, cur, pos, false );
01897 for( uint n = 0; n < ARRLEN(blockScopeKeywords); ++n )
01898 if( textLine->stringAtPos(pos, QString::fromLatin1(blockScopeKeywords[n]) ) )
01899 return calcIndentAfterKeyword( begin, cur, pos, true );
01900 #undef ARRLEN
01901 }
01902 }
01903 }
01904
01905
01906 return QString::null;
01907 }
01908
01909 QString KateCSAndSIndent::calcIndentInBracket(const KateDocCursor &indentCursor, const KateDocCursor &bracketCursor, int bracketPos)
01910 {
01911 KateTextLine::Ptr indentLine = doc->plainKateTextLine(indentCursor.line());
01912 KateTextLine::Ptr bracketLine = doc->plainKateTextLine(bracketCursor.line());
01913
01914
01915
01916 if ( bracketPos > 48 )
01917 {
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928 return indentString + initialWhitespace( bracketLine, bracketLine->firstChar() );
01929 }
01930
01931 const int indentLineFirst = indentLine->firstChar();
01932
01933 int indentTo;
01934 const int attrib = indentLine->attribute(indentLineFirst);
01935 if( indentLineFirst >= 0 && (attrib == 0 || attrib == symbolAttrib) &&
01936 ( indentLine->getChar(indentLineFirst) == ')' || indentLine->getChar(indentLineFirst) == ']' ) )
01937 {
01938
01939 indentTo = bracketPos;
01940 }
01941 else
01942 {
01943
01944 indentTo = bracketLine->nextNonSpaceChar( bracketPos + 1 );
01945 if( indentTo == -1 )
01946 indentTo = bracketPos + 2;
01947 }
01948 return initialWhitespace( bracketLine, indentTo );
01949 }
01950
01951 QString KateCSAndSIndent::calcIndentAfterKeyword(const KateDocCursor &indentCursor, const KateDocCursor &keywordCursor, int keywordPos, bool blockKeyword)
01952 {
01953 KateTextLine::Ptr keywordLine = doc->plainKateTextLine(keywordCursor.line());
01954 KateTextLine::Ptr indentLine = doc->plainKateTextLine(indentCursor.line());
01955
01956 QString whitespaceToKeyword = initialWhitespace( keywordLine, keywordPos, false );
01957 if( blockKeyword ) {
01958
01959 }
01960
01961
01962 int first = indentLine->firstChar();
01963
01964 const int attrib = indentLine->attribute(first);
01965 if( first >= 0 && (attrib == 0 || attrib == symbolAttrib) && indentLine->getChar(first) == '{' )
01966 return whitespaceToKeyword;
01967
01968
01969
01970
01971
01972
01973
01974
01975 return indentString + whitespaceToKeyword;
01976 }
01977
01978 QString KateCSAndSIndent::calcIndentInBrace(const KateDocCursor &indentCursor, const KateDocCursor &braceCursor, int bracePos)
01979 {
01980 KateTextLine::Ptr braceLine = doc->plainKateTextLine(braceCursor.line());
01981 const int braceFirst = braceLine->firstChar();
01982
01983 QString whitespaceToOpenBrace = initialWhitespace( braceLine, bracePos, false );
01984
01985
01986
01987
01988
01989 {
01990 if( braceFirst >= 0 && braceLine->attribute(braceFirst) == keywordAttrib &&
01991 braceLine->stringAtPos( braceFirst, QString::fromLatin1( "namespace" ) ) )
01992 return continuationIndent(indentCursor) + whitespaceToOpenBrace;
01993
01994 if( braceCursor.line() > 0 )
01995 {
01996 KateTextLine::Ptr prevLine = doc->plainKateTextLine(braceCursor.line() - 1);
01997 int firstPrev = prevLine->firstChar();
01998 if( firstPrev >= 0 && prevLine->attribute(firstPrev) == keywordAttrib &&
01999 prevLine->stringAtPos( firstPrev, QString::fromLatin1( "namespace" ) ) )
02000 return continuationIndent(indentCursor) + whitespaceToOpenBrace;
02001 }
02002 }
02003
02004 KateTextLine::Ptr indentLine = doc->plainKateTextLine(indentCursor.line());
02005 const int indentFirst = indentLine->firstChar();
02006
02007
02008 if( indentFirst >= 0 && indentLine->getChar(indentFirst) == '}' )
02009 return whitespaceToOpenBrace;
02010
02011
02012
02013 if ( indentFirst >= 0 && indentLine->attribute(indentFirst) == symbolAttrib &&
02014 indentLine->getChar(indentFirst) == ':' && indentLine->getChar(indentFirst+1) != ':' )
02015 {
02016 return indentString + indentString + whitespaceToOpenBrace;
02017 }
02018
02019 const bool continuation = inStatement(indentCursor);
02020
02021 if( !continuation && startsWithLabel( indentCursor.line() ) )
02022 return whitespaceToOpenBrace;
02023
02024
02025 QString continuationIndent = continuation ? indentString : QString::null;
02026 return indentString + continuationIndent + whitespaceToOpenBrace;
02027 }
02028
02029 void KateCSAndSIndent::processChar(QChar c)
02030 {
02031
02032 static const QString triggers("}{)]/:;#n");
02033 if (triggers.find(c) == -1)
02034 return;
02035
02036
02037
02038 KateView *view = doc->activeView();
02039 KateDocCursor begin(view->cursorLine(), 0, doc);
02040
02041 KateTextLine::Ptr textLine = doc->plainKateTextLine(begin.line());
02042 if ( c == 'n' )
02043 {
02044 int first = textLine->firstChar();
02045 if( first < 0 || textLine->getChar(first) != '#' )
02046 return;
02047 }
02048
02049 if ( textLine->attribute( begin.col() ) == doxyCommentAttrib )
02050 {
02051
02052 if ( c == '/' )
02053 {
02054 int first = textLine->firstChar();
02055
02056
02057 if ( first != -1
02058 && textLine->getChar( first ) == '*'
02059 && textLine->nextNonSpaceChar( first+1 ) == view->cursorColumnReal()-1 )
02060 doc->removeText( view->cursorLine(), first+1, view->cursorLine(), view->cursorColumnReal()-1);
02061 }
02062
02063
02064 return;
02065 }
02066
02067 processLine(begin);
02068 }
02069
02070
02071
02072
02073 class KateVarIndentPrivate {
02074 public:
02075 QRegExp reIndentAfter, reIndent, reUnindent;
02076 QString triggers;
02077 uint couples;
02078 uchar coupleAttrib;
02079 };
02080
02081 KateVarIndent::KateVarIndent( KateDocument *doc )
02082 : KateNormalIndent( doc )
02083 {
02084 d = new KateVarIndentPrivate;
02085 d->reIndentAfter = QRegExp( doc->variable( "var-indent-indent-after" ) );
02086 d->reIndent = QRegExp( doc->variable( "var-indent-indent" ) );
02087 d->reUnindent = QRegExp( doc->variable( "var-indent-unindent" ) );
02088 d->triggers = doc->variable( "var-indent-triggerchars" );
02089 d->coupleAttrib = 0;
02090
02091 slotVariableChanged( "var-indent-couple-attribute", doc->variable( "var-indent-couple-attribute" ) );
02092 slotVariableChanged( "var-indent-handle-couples", doc->variable( "var-indent-handle-couples" ) );
02093
02094
02095 connect( doc, SIGNAL(variableChanged( const QString&, const QString&) ),
02096 this, SLOT(slotVariableChanged( const QString&, const QString& )) );
02097 }
02098
02099 KateVarIndent::~KateVarIndent()
02100 {
02101 delete d;
02102 }
02103
02104 void KateVarIndent::processNewline ( KateDocCursor &begin, bool )
02105 {
02106
02107 KateDocCursor left( begin.line()-1, 0, doc );
02108 processLine( left );
02109 processLine( begin );
02110 }
02111
02112 void KateVarIndent::processChar ( QChar c )
02113 {
02114
02115 if ( d->triggers.contains( c ) )
02116 {
02117 KateTextLine::Ptr ln = doc->plainKateTextLine( doc->activeView()->cursorLine() );
02118 if ( ln->attribute( doc->activeView()->cursorColumn()-1 ) == commentAttrib )
02119 return;
02120
02121 KateView *view = doc->activeView();
02122 KateDocCursor begin( view->cursorLine(), 0, doc );
02123 kdDebug(13030)<<"variable indenter: process char '"<<c<<", line "<<begin.line()<<endl;
02124 processLine( begin );
02125 }
02126 }
02127
02128 void KateVarIndent::processLine ( KateDocCursor &line )
02129 {
02130 QString indent;
02131
02132
02133
02134 int ln = line.line();
02135 int pos = -1;
02136 KateTextLine::Ptr ktl = doc->plainKateTextLine( ln );
02137 if ( ! ktl ) return;
02138
02139
02140 KateView *v = doc->activeView();
02141 if ( (ktl->firstChar() < 0) && (!v || (int)v->cursorLine() != ln ) )
02142 return;
02143
02144 int fc;
02145 if ( ln > 0 )
02146 do
02147 {
02148
02149 ktl = doc->plainKateTextLine( --ln );
02150 fc = ktl->firstChar();
02151 if ( ktl->attribute( fc ) != commentAttrib )
02152 pos = fc;
02153 }
02154 while ( (ln > 0) && (pos < 0) );
02155
02156 if ( pos < 0 )
02157 pos = 0;
02158 else
02159 pos = ktl->cursorX( pos, tabWidth );
02160
02161 int adjustment = 0;
02162
02163
02164
02165 if ( d->couples & Parens && coupleBalance( ln, '(', ')' ) > 0 )
02166 adjustment++;
02167 else if ( d->couples & Braces && coupleBalance( ln, '{', '}' ) > 0 )
02168 adjustment++;
02169 else if ( d->couples & Brackets && coupleBalance( ln, '[', ']' ) > 0 )
02170 adjustment++;
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182 {
02183 KateTextLine::Ptr tl = doc->plainKateTextLine( line.line() );
02184 int i = tl->firstChar();
02185 if ( i > -1 )
02186 {
02187 QChar ch = tl->getChar( i );
02188 uchar at = tl->attribute( i );
02189 kdDebug(13030)<<"attrib is "<<at<<endl;
02190 if ( d->couples & Parens && ch == ')'
02191 && ( at == d->coupleAttrib
02192 || (! at && hasRelevantOpening( KateDocCursor( line.line(), i, doc ) ))
02193 )
02194 )
02195 adjustment--;
02196 else if ( d->couples & Braces && ch == '}'
02197 && ( at == d->coupleAttrib
02198 || (! at && hasRelevantOpening( KateDocCursor( line.line(), i, doc ) ))
02199 )
02200 )
02201 adjustment--;
02202 else if ( d->couples & Brackets && ch == ']'
02203 && ( at == d->coupleAttrib
02204 || (! at && hasRelevantOpening( KateDocCursor( line.line(), i, doc ) ))
02205 )
02206 )
02207 adjustment--;
02208 }
02209 }
02210 #define ISCOMMENTATTR(attr) (attr==commentAttrib||attr==doxyCommentAttrib)
02211 #define ISCOMMENT (ISCOMMENTATTR(ktl->attribute(ktl->firstChar()))||ISCOMMENTATTR(ktl->attribute(matchpos)))
02212
02213
02214 kdDebug(13030)<<"variable indenter: starting indent: "<<pos<<endl;
02215
02216 int matchpos = 0;
02217 if ( ktl && ! d->reIndentAfter.isEmpty()
02218 && (matchpos = d->reIndentAfter.search( doc->textLine( ln ) )) > -1
02219 && ! ISCOMMENT )
02220 adjustment++;
02221
02222
02223 ktl = doc->plainKateTextLine( line.line() );
02224 if ( ! d->reIndent.isEmpty()
02225 && (matchpos = d->reIndent.search( doc->textLine( line.line() ) )) > -1
02226 && ! ISCOMMENT )
02227 adjustment++;
02228
02229
02230 if ( ! d->reUnindent.isEmpty()
02231 && (matchpos = d->reUnindent.search( doc->textLine( line.line() ) )) > -1
02232 && ! ISCOMMENT )
02233 adjustment--;
02234
02235 kdDebug(13030)<<"variable indenter: adjusting by "<<adjustment<<" units"<<endl;
02236
02237 if ( adjustment > 0 )
02238 pos += indentWidth;
02239 else if ( adjustment < 0 )
02240 pos -= indentWidth;
02241
02242 ln = line.line();
02243 fc = doc->plainKateTextLine( ln )->firstChar();
02244
02245
02246
02247
02248
02249 if ( fc == pos )
02250 return;
02251
02252 if ( fc > 0 )
02253 doc->removeText (ln, 0, ln, fc );
02254
02255 if ( pos > 0 )
02256 indent = tabString( pos );
02257
02258 if ( pos > 0 )
02259 doc->insertText (ln, 0, indent);
02260
02261
02262 line.setCol( pos );
02263 }
02264
02265 void KateVarIndent::processSection (const KateDocCursor &begin, const KateDocCursor &end)
02266 {
02267 KateDocCursor cur = begin;
02268 while (cur.line() <= end.line())
02269 {
02270 processLine (cur);
02271 if (!cur.gotoNextLine())
02272 break;
02273 }
02274 }
02275
02276 void KateVarIndent::slotVariableChanged( const QString &var, const QString &val )
02277 {
02278 if ( ! var.startsWith("var-indent") )
02279 return;
02280
02281 if ( var == "var-indent-indent-after" )
02282 d->reIndentAfter.setPattern( val );
02283 else if ( var == "var-indent-indent" )
02284 d->reIndent.setPattern( val );
02285 else if ( var == "var-indent-unindent" )
02286 d->reUnindent.setPattern( val );
02287 else if ( var == "var-indent-triggerchars" )
02288 d->triggers = val;
02289 else if ( var == "var-indent-handle-couples" )
02290 {
02291 d->couples = 0;
02292 QStringList l = QStringList::split( " ", val );
02293 if ( l.contains("parens") ) d->couples |= Parens;
02294 if ( l.contains("braces") ) d->couples |= Braces;
02295 if ( l.contains("brackets") ) d->couples |= Brackets;
02296 }
02297 else if ( var == "var-indent-couple-attribute" )
02298 {
02299
02300 KateHlItemDataList items;
02301 doc->highlight()->getKateHlItemDataListCopy (0, items);
02302
02303 for (uint i=0; i<items.count(); i++)
02304 {
02305 if ( items.at(i)->name.section( ':', 1 ) == val )
02306 {
02307 d->coupleAttrib = i;
02308 break;
02309 }
02310 }
02311 }
02312 }
02313
02314 int KateVarIndent::coupleBalance ( int line, const QChar &open, const QChar &close ) const
02315 {
02316 int r = 0;
02317
02318 KateTextLine::Ptr ln = doc->plainKateTextLine( line );
02319 if ( ! ln || ! ln->length() ) return 0;
02320
02321 for ( uint z=0; z < ln->length(); z++ )
02322 {
02323 QChar c = ln->getChar( z );
02324 if ( ln->attribute(z) == d->coupleAttrib )
02325 {
02326 kdDebug(13030)<<z<<", "<<c<<endl;
02327 if (c == open)
02328 r++;
02329 else if (c == close)
02330 r--;
02331 }
02332 }
02333 return r;
02334 }
02335
02336 bool KateVarIndent::hasRelevantOpening( const KateDocCursor &end ) const
02337 {
02338 KateDocCursor cur = end;
02339 int count = 1;
02340
02341 QChar close = cur.currentChar();
02342 QChar opener;
02343 if ( close == '}' ) opener = '{';
02344 else if ( close = ')' ) opener = '(';
02345 else if (close = ']' ) opener = '[';
02346 else return false;
02347
02348
02349 while (cur.moveBackward(1))
02350 {
02351 if (cur.currentAttrib() == d->coupleAttrib)
02352 {
02353 QChar ch = cur.currentChar();
02354 if (ch == opener)
02355 count--;
02356 else if (ch == close)
02357 count++;
02358
02359 if (count == 0)
02360 return true;
02361 }
02362 }
02363
02364 return false;
02365 }
02366
02367
02368
02369
02370
02371 KateScriptIndent::KateScriptIndent( KateDocument *doc )
02372 : KateNormalIndent( doc )
02373 {
02374 m_script=KateFactory::self()->indentScript ("script-indent-c1-test");
02375 }
02376
02377 KateScriptIndent::~KateScriptIndent()
02378 {
02379 }
02380
02381 void KateScriptIndent::processNewline( KateDocCursor &begin, bool needContinue )
02382 {
02383 kdDebug(13030) << "processNewline" << endl;
02384 KateView *view = doc->activeView();
02385
02386 if (view)
02387 {
02388 QString errorMsg;
02389
02390 QTime t;
02391 t.start();
02392 kdDebug(13030)<<"calling m_script.processChar"<<endl;
02393 if( !m_script.processNewline( view, begin, needContinue , errorMsg ) )
02394 {
02395 kdDebug(13030) << "Error in script-indent: " << errorMsg << endl;
02396 }
02397 kdDebug(13030) << "ScriptIndent::TIME in ms: " << t.elapsed() << endl;
02398 }
02399 }
02400
02401 void KateScriptIndent::processChar( QChar c )
02402 {
02403 kdDebug(13030) << "processChar" << endl;
02404 KateView *view = doc->activeView();
02405
02406 if (view)
02407 {
02408 QString errorMsg;
02409
02410 QTime t;
02411 t.start();
02412 kdDebug(13030)<<"calling m_script.processChar"<<endl;
02413 if( !m_script.processChar( view, c , errorMsg ) )
02414 {
02415 kdDebug(13030) << "Error in script-indent: " << errorMsg << endl;
02416 }
02417 kdDebug(13030) << "ScriptIndent::TIME in ms: " << t.elapsed() << endl;
02418 }
02419 }
02420
02421 void KateScriptIndent::processLine (KateDocCursor &line)
02422 {
02423 kdDebug(13030) << "processLine" << endl;
02424 KateView *view = doc->activeView();
02425
02426 if (view)
02427 {
02428 QString errorMsg;
02429
02430 QTime t;
02431 t.start();
02432 kdDebug(13030)<<"calling m_script.processLine"<<endl;
02433 if( !m_script.processLine( view, line , errorMsg ) )
02434 {
02435 kdDebug(13030) << "Error in script-indent: " << errorMsg << endl;
02436 }
02437 kdDebug(13030) << "ScriptIndent::TIME in ms: " << t.elapsed() << endl;
02438 }
02439 }
02440
02441
02442
02443 #include <qlabel.h>
02444 ScriptIndentConfigPage::ScriptIndentConfigPage ( QWidget *parent, const char *name )
02445 : IndenterConfigPage(parent, name)
02446 {
02447 QLabel* hello = new QLabel("Hello world! Dummy for testing purpose.", this);
02448 hello->show();
02449 }
02450
02451 ScriptIndentConfigPage::~ScriptIndentConfigPage ()
02452 {
02453 }
02454
02455 void ScriptIndentConfigPage::apply ()
02456 {
02457 kdDebug(13030) << "ScriptIndentConfigPagE::apply() was called, save config options now!" << endl;
02458 }
02459
02460
02461