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 bool potentialAnchorSeen = false;
00718
00719
00720
00721
00722 while (cur.gotoPreviousLine())
00723 {
00724 isSpecial = found = false;
00725 textLine = doc->plainKateTextLine(cur.line());
00726
00727
00728 int pos = textLine->lastChar();
00729 int openCount = 0;
00730 int otherAnchor = -1;
00731 do
00732 {
00733 if (textLine->attribute(pos) == symbolAttrib)
00734 {
00735 QChar tc = textLine->getChar (pos);
00736 if ((tc == ';' || tc == ':' || tc == ',') && otherAnchor == -1 && parenCount <= 0)
00737 otherAnchor = pos, potentialAnchorSeen = true;
00738 else if (tc == ')')
00739 parenCount++;
00740 else if (tc == '(')
00741 parenCount--;
00742 else if (tc == '}')
00743 openCount--;
00744 else if (tc == '{')
00745 {
00746 openCount++, potentialAnchorSeen = true;
00747 if (openCount == 1)
00748 break;
00749 }
00750 }
00751 } while (--pos >= textLine->firstChar());
00752
00753 if (openCount != 0 || otherAnchor != -1)
00754 {
00755 found = true;
00756 QChar c;
00757 if (openCount > 0)
00758 c = '{';
00759 else if (openCount < 0)
00760 c = '}';
00761 else if (otherAnchor >= 0)
00762 c = textLine->getChar (otherAnchor);
00763
00764 int specialIndent = 0;
00765 if (c == ':' && needContinue)
00766 {
00767 QChar ch;
00768 specialIndent = textLine->firstChar();
00769 if (textLine->stringAtPos(specialIndent, "case"))
00770 ch = textLine->getChar(specialIndent + 4);
00771 else if (textLine->stringAtPos(specialIndent, "default"))
00772 ch = textLine->getChar(specialIndent + 7);
00773 else if (textLine->stringAtPos(specialIndent, "public"))
00774 ch = textLine->getChar(specialIndent + 6);
00775 else if (textLine->stringAtPos(specialIndent, "private"))
00776 ch = textLine->getChar(specialIndent + 7);
00777 else if (textLine->stringAtPos(specialIndent, "protected"))
00778 ch = textLine->getChar(specialIndent + 9);
00779 else if (textLine->stringAtPos(specialIndent, "signals"))
00780 ch = textLine->getChar(specialIndent + 7);
00781 else if (textLine->stringAtPos(specialIndent, "Q_SIGNALS"))
00782 ch = textLine->getChar(specialIndent + 9);
00783 else if (textLine->stringAtPos(specialIndent, "slots"))
00784 ch = textLine->getChar(specialIndent + 5);
00785 else if (textLine->stringAtPos(specialIndent, "Q_SLOTS"))
00786 ch = textLine->getChar(specialIndent + 7);
00787
00788 if (ch.isNull() || (!ch.isSpace() && ch != '(' && ch != ':'))
00789 continue;
00790
00791 KateDocCursor lineBegin = cur;
00792 lineBegin.setCol(specialIndent);
00793 specialIndent = measureIndent(lineBegin);
00794 isSpecial = true;
00795 }
00796
00797
00798 KateDocCursor skip = cur;
00799 skip.setCol(textLine->lastChar());
00800 bool result = skipBlanks(skip, begin, true);
00801
00802 anchorPos = skip.col();
00803 anchorIndent = measureIndent(skip);
00804
00805
00806
00807
00808 if (result && skip < begin)
00809 {
00810 cur = skip;
00811 break;
00812 }
00813 else if (isSpecial)
00814 {
00815 anchorIndent = specialIndent;
00816 break;
00817 }
00818
00819
00820 if ((c == '{' || c == '}') && textLine->getChar(textLine->firstChar()) == c)
00821 {
00822 cur.setCol(anchorPos = textLine->firstChar());
00823 anchorIndent = measureIndent (cur);
00824 break;
00825 }
00826 }
00827 }
00828
00829
00830 if (cur.line() == 0 && cur.col() == 0 && potentialAnchorSeen)
00831 found = true;
00832
00833 if (!found)
00834 return 0;
00835
00836 uint continueIndent = (needContinue) ? calcContinue (cur, begin) : 0;
00837
00838
00839
00840
00841 textLine = doc->plainKateTextLine(cur.line());
00842 QChar lastChar = textLine->getChar (anchorPos);
00843 int lastLine = cur.line();
00844 if (lastChar == '#' || lastChar == '[')
00845 {
00846
00847
00848 continueIndent = 0;
00849 }
00850
00851 int openCount = 0;
00852 while (cur.validPosition() && cur < begin)
00853 {
00854 if (!skipBlanks(cur, begin, true))
00855 return 0;
00856
00857 QChar tc = cur.currentChar();
00858
00859 if (cur == begin || tc.isNull())
00860 break;
00861
00862 if (!tc.isSpace() && cur < begin)
00863 {
00864 uchar attrib = cur.currentAttrib();
00865 if (tc == '{' && attrib == symbolAttrib)
00866 openCount++;
00867 else if (tc == '}' && attrib == symbolAttrib)
00868 openCount--;
00869
00870 lastChar = tc;
00871 lastLine = cur.line();
00872 }
00873 }
00874 if (openCount > 0)
00875 lastChar = '{';
00876
00877 uint indent = 0;
00878
00879
00880 if (lastChar == '{' || (lastChar == ':' && isSpecial && needContinue))
00881 {
00882 indent = anchorIndent + indentWidth;
00883 }
00884 else if (lastChar == '}')
00885 {
00886 indent = anchorIndent;
00887 }
00888 else if (lastChar == ';')
00889 {
00890 indent = anchorIndent + ((allowSemi && needContinue) ? continueIndent : 0);
00891 }
00892 else if (lastChar == ',')
00893 {
00894 textLine = doc->plainKateTextLine(lastLine);
00895 KateDocCursor start(lastLine, textLine->firstChar(), doc);
00896 KateDocCursor finish(lastLine, textLine->lastChar(), doc);
00897 uint pos = 0;
00898
00899 if (isBalanced(start, finish, QChar('('), QChar(')'), pos))
00900 indent = anchorIndent;
00901 else
00902 {
00903
00904 indent = ((pos < 48) ? pos : anchorIndent + (indentWidth * 2));
00905 }
00906 }
00907 else if (!lastChar.isNull())
00908 {
00909 if (anchorIndent != 0)
00910 indent = anchorIndent + continueIndent;
00911 else
00912 indent = continueIndent;
00913 }
00914
00915 return indent;
00916 }
00917
00918 uint KateCSmartIndent::calcContinue(KateDocCursor &start, KateDocCursor &end)
00919 {
00920 KateDocCursor cur = start;
00921
00922 bool needsBalanced = true;
00923 bool isFor = false;
00924 allowSemi = false;
00925
00926 KateTextLine::Ptr textLine = doc->plainKateTextLine(cur.line());
00927
00928
00929 if (textLine->attribute(cur.col()) == symbolAttrib)
00930 {
00931 cur.moveForward(1);
00932 skipBlanks(cur, end, false);
00933 }
00934
00935 if (textLine->getChar(cur.col()) == '}')
00936 {
00937 skipBlanks(cur, end, true);
00938 if (cur.line() != start.line())
00939 textLine = doc->plainKateTextLine(cur.line());
00940
00941 if (textLine->stringAtPos(cur.col(), "else"))
00942 cur.setCol(cur.col() + 4);
00943 else
00944 return indentWidth * 2;
00945
00946 needsBalanced = false;
00947 }
00948 else if (textLine->stringAtPos(cur.col(), "else"))
00949 {
00950 cur.setCol(cur.col() + 4);
00951 needsBalanced = false;
00952 int next = textLine->nextNonSpaceChar(cur.col());
00953 if (next >= 0 && textLine->stringAtPos(next, "if"))
00954 {
00955 cur.setCol(next + 2);
00956 needsBalanced = true;
00957 }
00958 }
00959 else if (textLine->stringAtPos(cur.col(), "if"))
00960 {
00961 cur.setCol(cur.col() + 2);
00962 }
00963 else if (textLine->stringAtPos(cur.col(), "do"))
00964 {
00965 cur.setCol(cur.col() + 2);
00966 needsBalanced = false;
00967 }
00968 else if (textLine->stringAtPos(cur.col(), "for"))
00969 {
00970 cur.setCol(cur.col() + 3);
00971 isFor = true;
00972 }
00973 else if (textLine->stringAtPos(cur.col(), "while"))
00974 {
00975 cur.setCol(cur.col() + 5);
00976 }
00977 else if (textLine->stringAtPos(cur.col(), "switch"))
00978 {
00979 cur.setCol(cur.col() + 6);
00980 }
00981 else if (textLine->stringAtPos(cur.col(), "using"))
00982 {
00983 cur.setCol(cur.col() + 5);
00984 }
00985 else
00986 {
00987 return indentWidth * 2;
00988 }
00989
00990 uint openPos = 0;
00991 if (needsBalanced && !isBalanced (cur, end, QChar('('), QChar(')'), openPos))
00992 {
00993 allowSemi = isFor;
00994 if (openPos > 0)
00995 return (openPos - textLine->firstChar());
00996 else
00997 return indentWidth * 2;
00998 }
00999
01000
01001 skipBlanks(cur, end, false);
01002 if (cur == end)
01003 return indentWidth;
01004
01005 if (skipBlanks(cur, end, true))
01006 {
01007 if (cur == end)
01008 return indentWidth;
01009 else
01010 return indentWidth + calcContinue(cur, end);
01011 }
01012
01013 return 0;
01014 }
01015
01016 uint KateCSmartIndent::findOpeningBrace(KateDocCursor &start)
01017 {
01018 KateDocCursor cur = start;
01019 int count = 1;
01020
01021
01022
01023 while (cur.moveBackward(1))
01024 {
01025 if (cur.currentAttrib() == symbolAttrib)
01026 {
01027 QChar ch = cur.currentChar();
01028 if (ch == '{')
01029 count--;
01030 else if (ch == '}')
01031 count++;
01032
01033 if (count == 0)
01034 {
01035 KateDocCursor temp(cur.line(), doc->plainKateTextLine(cur.line())->firstChar(), doc);
01036 return measureIndent(temp);
01037 }
01038 }
01039 }
01040
01041 return 0;
01042 }
01043
01044 bool KateCSmartIndent::firstOpeningBrace(KateDocCursor &start)
01045 {
01046 KateDocCursor cur = start;
01047
01048
01049 while(cur.moveBackward(1))
01050 {
01051 if (cur.currentAttrib() == symbolAttrib)
01052 {
01053 QChar ch = cur.currentChar();
01054 if (ch == '{')
01055 return false;
01056 else if (ch == '}' && cur.col() == 0)
01057 break;
01058 }
01059 }
01060
01061 return true;
01062 }
01063
01064 uint KateCSmartIndent::findOpeningParen(KateDocCursor &start)
01065 {
01066 KateDocCursor cur = start;
01067 int count = 1;
01068
01069
01070
01071 while (cur.moveBackward(1))
01072 {
01073 if (cur.currentAttrib() == symbolAttrib)
01074 {
01075 QChar ch = cur.currentChar();
01076 if (ch == '(')
01077 count--;
01078 else if (ch == ')')
01079 count++;
01080
01081 if (count == 0)
01082 return measureIndent(cur);
01083 }
01084 }
01085
01086 return 0;
01087 }
01088
01089 uint KateCSmartIndent::findOpeningComment(KateDocCursor &start)
01090 {
01091 KateDocCursor cur = start;
01092
01093
01094 do
01095 {
01096 KateTextLine::Ptr textLine = doc->plainKateTextLine(cur.line());
01097
01098 int pos = textLine->string().find("/*", false);
01099 if (pos >= 0)
01100 {
01101 KateDocCursor temp(cur.line(), pos, doc);
01102 return measureIndent(temp);
01103 }
01104
01105 } while (cur.gotoPreviousLine());
01106
01107 return 0;
01108 }
01109
01110
01111
01112
01113
01114 QRegExp KatePythonIndent::endWithColon = QRegExp( "^[^#]*:\\s*(#.*)?$" );
01115 QRegExp KatePythonIndent::stopStmt = QRegExp( "^\\s*(break|continue|raise|return|pass)\\b.*" );
01116 QRegExp KatePythonIndent::blockBegin = QRegExp( "^\\s*(class|def|if|elif|else|for|while|try)\\b.*" );
01117
01118 KatePythonIndent::KatePythonIndent (KateDocument *doc)
01119 : KateNormalIndent (doc)
01120 {
01121 }
01122 KatePythonIndent::~KatePythonIndent ()
01123 {
01124 }
01125
01126 void KatePythonIndent::processNewline (KateDocCursor &begin, bool )
01127 {
01128 int prevLine = begin.line() - 1;
01129 int prevPos = begin.col();
01130
01131 while ((prevLine > 0) && (prevPos < 0))
01132 prevPos = doc->plainKateTextLine(--prevLine)->firstChar();
01133
01134 int prevBlock = prevLine;
01135 int prevBlockPos = prevPos;
01136 int extraIndent = calcExtra (prevBlock, prevBlockPos, begin);
01137
01138 int indent = doc->plainKateTextLine(prevBlock)->cursorX(prevBlockPos, tabWidth);
01139 if (extraIndent == 0)
01140 {
01141 if (!stopStmt.exactMatch(doc->plainKateTextLine(prevLine)->string()))
01142 {
01143 if (endWithColon.exactMatch(doc->plainKateTextLine(prevLine)->string()))
01144 indent += indentWidth;
01145 else
01146 indent = doc->plainKateTextLine(prevLine)->cursorX(prevPos, tabWidth);
01147 }
01148 }
01149 else
01150 indent += extraIndent;
01151
01152 if (indent > 0)
01153 {
01154 QString filler = tabString (indent);
01155 doc->insertText (begin.line(), 0, filler);
01156 begin.setCol(filler.length());
01157 }
01158 else
01159 begin.setCol(0);
01160 }
01161
01162 int KatePythonIndent::calcExtra (int &prevBlock, int &pos, KateDocCursor &end)
01163 {
01164 int nestLevel = 0;
01165 bool levelFound = false;
01166 while ((prevBlock > 0))
01167 {
01168 if (blockBegin.exactMatch(doc->plainKateTextLine(prevBlock)->string()))
01169 {
01170 if ((!levelFound && nestLevel == 0) || (levelFound && nestLevel - 1 <= 0))
01171 {
01172 pos = doc->plainKateTextLine(prevBlock)->firstChar();
01173 break;
01174 }
01175
01176 nestLevel --;
01177 }
01178 else if (stopStmt.exactMatch(doc->plainKateTextLine(prevBlock)->string()))
01179 {
01180 nestLevel ++;
01181 levelFound = true;
01182 }
01183
01184 --prevBlock;
01185 }
01186
01187 KateDocCursor cur (prevBlock, pos, doc);
01188 QChar c;
01189 int extraIndent = 0;
01190 while (cur.line() < end.line())
01191 {
01192 c = cur.currentChar();
01193
01194 if (c == '(')
01195 extraIndent += indentWidth;
01196 else if (c == ')')
01197 extraIndent -= indentWidth;
01198 else if (c == ':')
01199 break;
01200 else if (c == '\'' || c == '"' )
01201 traverseString( c, cur, end );
01202
01203 if (c.isNull() || c == '#')
01204 cur.gotoNextLine();
01205 else
01206 cur.moveForward(1);
01207 }
01208
01209 return extraIndent;
01210 }
01211
01212 void KatePythonIndent::traverseString( const QChar &stringChar, KateDocCursor &cur, KateDocCursor &end )
01213 {
01214 QChar c;
01215 bool escape = false;
01216
01217 cur.moveForward(1);
01218 c = cur.currentChar();
01219 while ( ( c != stringChar || escape ) && cur.line() < end.line() )
01220 {
01221 if ( escape )
01222 escape = false;
01223 else if ( c == '\\' )
01224 escape = !escape;
01225
01226 cur.moveForward(1);
01227 c = cur.currentChar();
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
01257 const QRegExp KateXmlIndent::startsWithCloseTag("^[ \t]*</");
01258 const QRegExp KateXmlIndent::unclosedDoctype("<!DOCTYPE[^>]*$");
01259
01260 KateXmlIndent::KateXmlIndent (KateDocument *doc)
01261 : KateNormalIndent (doc)
01262 {
01263 }
01264
01265 KateXmlIndent::~KateXmlIndent ()
01266 {
01267 }
01268
01269 void KateXmlIndent::processNewline (KateDocCursor &begin, bool )
01270 {
01271 begin.setCol(processLine(begin.line()));
01272 }
01273
01274 void KateXmlIndent::processChar (QChar c)
01275 {
01276 if(c != '/') return;
01277
01278
01279 KateView *view = doc->activeView();
01280 QString text = doc->plainKateTextLine(view->cursorLine())->string();
01281 if(text.find(startsWithCloseTag) == -1) return;
01282
01283
01284 processLine(view->cursorLine());
01285 }
01286
01287 void KateXmlIndent::processLine (KateDocCursor &line)
01288 {
01289 processLine (line.line());
01290 }
01291
01292 void KateXmlIndent::processSection (const KateDocCursor &start, const KateDocCursor &end)
01293 {
01294 KateDocCursor cur (start);
01295 int endLine = end.line();
01296
01297 do {
01298 processLine(cur.line());
01299 if(!cur.gotoNextLine()) break;
01300 } while(cur.line() < endLine);
01301 }
01302
01303 void KateXmlIndent::getLineInfo (uint line, uint &prevIndent, int &numTags,
01304 uint &attrCol, bool &unclosedTag)
01305 {
01306 prevIndent = 0;
01307 int firstChar;
01308 KateTextLine::Ptr prevLine = 0;
01309
01310
01311 while(true) {
01312 prevLine = doc->plainKateTextLine(line);
01313 if( (firstChar = prevLine->firstChar()) < 0) {
01314 if(!line--) return;
01315 continue;
01316 }
01317 break;
01318 }
01319 prevIndent = prevLine->cursorX(prevLine->firstChar(), tabWidth);
01320 QString text = prevLine->string();
01321
01322
01323
01324
01325
01326 if(text.find(startsWithCloseTag) != -1) ++numTags;
01327
01328
01329 int lastCh = 0;
01330 uint pos, len = text.length();
01331 bool seenOpen = false;
01332 for(pos = 0; pos < len; ++pos) {
01333 int ch = text.at(pos).unicode();
01334 switch(ch) {
01335 case '<':
01336 seenOpen = true;
01337 unclosedTag = true;
01338 attrCol = pos;
01339 ++numTags;
01340 break;
01341
01342
01343 case '!':
01344 if(lastCh == '<') --numTags;
01345 break;
01346
01347
01348 case '?':
01349 if(lastCh == '<') --numTags;
01350 break;
01351
01352 case '>':
01353 if(!seenOpen) {
01354
01355
01356
01357
01358
01359
01360
01361
01362 prevIndent = 0;
01363
01364 for(uint backLine = line; backLine; ) {
01365
01366 KateTextLine::Ptr x = doc->plainKateTextLine(--backLine);
01367 if(x->string().find('<') == -1) continue;
01368
01369
01370 if(x->string().find(unclosedDoctype) != -1) --numTags;
01371 getLineInfo(backLine, prevIndent, numTags, attrCol, unclosedTag);
01372 break;
01373 }
01374 }
01375 if(lastCh == '/') --numTags;
01376 unclosedTag = false;
01377 break;
01378
01379 case '/':
01380 if(lastCh == '<') numTags -= 2;
01381 break;
01382 }
01383 lastCh = ch;
01384 }
01385
01386 if(unclosedTag) {
01387
01388 do {
01389 lastCh = text.at(++attrCol).unicode();
01390 }while(lastCh && lastCh != ' ' && lastCh != '\t');
01391
01392 while(lastCh == ' ' || lastCh == '\t') {
01393 lastCh = text.at(++attrCol).unicode();
01394 }
01395
01396 attrCol = prevLine->cursorX(attrCol, tabWidth);
01397 }
01398 }
01399
01400 uint KateXmlIndent::processLine (uint line)
01401 {
01402 KateTextLine::Ptr kateLine = doc->plainKateTextLine(line);
01403 if(!kateLine) return 0;
01404
01405
01406 uint prevIndent = 0, attrCol = 0;
01407 int numTags = 0;
01408 bool unclosedTag = false;
01409
01410 if(line) {
01411 getLineInfo(line - 1, prevIndent, numTags, attrCol, unclosedTag);
01412 }
01413
01414
01415 int indent = 0;
01416 if(unclosedTag) indent = attrCol;
01417 else indent = prevIndent + numTags * indentWidth;
01418 if(indent < 0) indent = 0;
01419
01420
01421 if(kateLine->string().find(startsWithCloseTag) != -1) {
01422 indent -= indentWidth;
01423 }
01424 if(indent < 0) indent = 0;
01425
01426
01427 doc->removeText(line, 0, line, kateLine->firstChar());
01428 QString filler = tabString(indent);
01429 doc->insertText(line, 0, filler);
01430
01431 return filler.length();
01432 }
01433
01434
01435
01436
01437
01438 KateCSAndSIndent::KateCSAndSIndent (KateDocument *doc)
01439 : KateNormalIndent (doc)
01440 {
01441 }
01442
01443 void KateCSAndSIndent::updateIndentString()
01444 {
01445 if( useSpaces )
01446 indentString.fill( ' ', indentWidth );
01447 else
01448 indentString = '\t';
01449 }
01450
01451 KateCSAndSIndent::~KateCSAndSIndent ()
01452 {
01453 }
01454
01455 void KateCSAndSIndent::processLine (KateDocCursor &line)
01456 {
01457 KateTextLine::Ptr textLine = doc->plainKateTextLine(line.line());
01458
01459 if (!textLine)
01460 return;
01461
01462 updateIndentString();
01463
01464 const int oldCol = line.col();
01465 QString whitespace = calcIndent(line);
01466
01467 int oldIndent = textLine->firstChar();
01468 if ( oldIndent < 0 )
01469 oldIndent = doc->lineLength( line.line() );
01470 if( oldIndent > 0 )
01471 doc->removeText(line.line(), 0, line.line(), oldIndent);
01472
01473 doc->insertText(line.line(), 0, whitespace);
01474
01475
01476 if ( int(oldCol + whitespace.length()) >= oldIndent )
01477 line.setCol( oldCol + whitespace.length() - oldIndent );
01478 else
01479 line.setCol( 0 );
01480 }
01481
01482 void KateCSAndSIndent::processSection (const KateDocCursor &begin, const KateDocCursor &end)
01483 {
01484 QTime t; t.start();
01485 for( KateDocCursor cur = begin; cur.line() <= end.line(); )
01486 {
01487 processLine (cur);
01488 if (!cur.gotoNextLine())
01489 break;
01490 }
01491 kdDebug(13030) << "+++ total: " << t.elapsed() << endl;
01492 }
01493
01499 static QString initialWhitespace(const KateTextLine::Ptr &line, int chars, bool convert = true)
01500 {
01501 QString text = line->string(0, chars);
01502 if( (int)text.length() < chars )
01503 {
01504 QString filler; filler.fill(' ',chars - text.length());
01505 text += filler;
01506 }
01507 for( uint n = 0; n < text.length(); ++n )
01508 {
01509 if( text[n] != '\t' && text[n] != ' ' )
01510 {
01511 if( !convert )
01512 return text.left( n );
01513 text[n] = ' ';
01514 }
01515 }
01516 return text;
01517 }
01518
01519 QString KateCSAndSIndent::findOpeningCommentIndentation(const KateDocCursor &start)
01520 {
01521 KateDocCursor cur = start;
01522
01523
01524 do
01525 {
01526 KateTextLine::Ptr textLine = doc->plainKateTextLine(cur.line());
01527
01528 int pos = textLine->string().findRev("/*");
01529
01530 if (pos >= 0)
01531 return initialWhitespace(textLine, pos);
01532 } while (cur.gotoPreviousLine());
01533
01534
01535 kdWarning( 13030 ) << " in a comment, but can't find the start of it" << endl;
01536 return QString::null;
01537 }
01538
01539 bool KateCSAndSIndent::handleDoxygen (KateDocCursor &begin)
01540 {
01541
01542 int line = begin.line();
01543 int first = -1;
01544 while ((line > 0) && (first < 0))
01545 first = doc->plainKateTextLine(--line)->firstChar();
01546
01547
01548 if (first < 0)
01549 return false;
01550
01551 KateTextLine::Ptr textLine = doc->plainKateTextLine(line);
01552
01553
01554
01555
01556
01557 if ( !(textLine->attribute(textLine->lastChar()) == doxyCommentAttrib && !textLine->endingWith("*/")) &&
01558 !(textLine->attribute(textLine->firstChar()) == doxyCommentAttrib && !textLine->string().contains("*/")) )
01559 return false;
01560
01561
01562 textLine = doc->plainKateTextLine(begin.line());
01563 first = textLine->firstChar();
01564 QString indent = findOpeningCommentIndentation(begin);
01565
01566 bool doxygenAutoInsert = doc->config()->configFlags() & KateDocumentConfig::cfDoxygenAutoTyping;
01567
01568
01569 if ( first >= 0 && textLine->stringAtPos(first, "*") )
01570 indent = indent + " ";
01571
01572 else if ( doxygenAutoInsert )
01573 indent = indent + " * ";
01574
01575
01576
01577
01578 doc->removeText (begin.line(), 0, begin.line(), first);
01579 doc->insertText (begin.line(), 0, indent);
01580 begin.setCol(indent.length());
01581
01582 return true;
01583 }
01584
01591 void KateCSAndSIndent::processNewline (KateDocCursor &begin, bool )
01592 {
01593
01594 if( handleDoxygen(begin) )
01595 return;
01596
01597
01598
01599
01600
01601 int cursorPos = doc->plainKateTextLine( begin.line() )->firstChar();
01602 if ( cursorPos < 0 )
01603 cursorPos = doc->lineLength( begin.line() );
01604 begin.setCol( cursorPos );
01605
01606 processLine( begin );
01607 }
01608
01613 bool KateCSAndSIndent::startsWithLabel( int line )
01614 {
01615
01616 KateTextLine::Ptr indentLine = doc->plainKateTextLine(line);
01617 const int indentFirst = indentLine->firstChar();
01618
01619
01620 int attrib = indentLine->attribute(indentFirst);
01621 if (attrib != 0 && attrib != keywordAttrib && attrib != normalAttrib && attrib != extensionAttrib)
01622 return false;
01623
01624
01625 const QString lineContents = indentLine->string();
01626 const int indentLast = indentLine->lastChar();
01627 bool whitespaceFound = false;
01628 for ( int n = indentFirst; n <= indentLast; ++n )
01629 {
01630
01631
01632 char c = lineContents[n].latin1();
01633 if ( c == ':' )
01634 {
01635
01636 if ( n < lineContents.length() - 1 )
01637 {
01638 if ( lineContents[n+1].latin1() == ':' )
01639 {
01640 n += 2;
01641 continue;
01642 }
01643 }
01644
01645 if ( n == indentFirst)
01646 {
01647
01648 return false;
01649 }
01650
01651 return true;
01652 }
01653 if (isspace(c))
01654 {
01655 if (!whitespaceFound)
01656 {
01657 if (lineContents.mid(indentFirst, n - indentFirst) == "case")
01658 return true;
01659 else if (lineContents.mid(indentFirst, n - indentFirst) == "class")
01660 return false;
01661 whitespaceFound = true;
01662 }
01663 }
01664
01665 else if ( !isalnum(c) && c != '_' )
01666 {
01667 return false;
01668 }
01669 }
01670 return false;
01671 }
01672
01673 template<class T> T min(T a, T b) { return (a < b) ? a : b; }
01674
01675 int KateCSAndSIndent::lastNonCommentChar( const KateDocCursor &line )
01676 {
01677 KateTextLine::Ptr textLine = doc->plainKateTextLine( line.line() );
01678 QString str = textLine->string();
01679
01680
01681 int p = -2;
01682 do p = str.find( "//", p + 2 );
01683 while ( p >= 0 && textLine->attribute(p) != commentAttrib && textLine->attribute(p) != doxyCommentAttrib );
01684
01685
01686 if ( p < 0 )
01687 p = str.length();
01688
01689
01690 while( p > 0 && str[p-1].isSpace() ) --p;
01691 return p - 1;
01692 }
01693
01694 bool KateCSAndSIndent::inForStatement( int line )
01695 {
01696
01697
01698 int parens = 0, semicolons = 0;
01699 for ( ; line >= 0; --line )
01700 {
01701 KateTextLine::Ptr textLine = doc->plainKateTextLine(line);
01702 const int first = textLine->firstChar();
01703 const int last = textLine->lastChar();
01704
01705
01706
01707
01708
01709 for ( int curr = last; curr >= first; --curr )
01710 {
01711 if ( textLine->attribute(curr) != symbolAttrib )
01712 continue;
01713
01714 switch( textLine->getChar(curr) )
01715 {
01716 case ';':
01717 if( ++semicolons > 2 )
01718 return false;
01719 break;
01720 case '{': case '}':
01721 return false;
01722 case ')':
01723 ++parens;
01724 break;
01725 case '(':
01726 if( --parens < 0 )
01727 return true;
01728 break;
01729 }
01730 }
01731 }
01732
01733
01734 return false;
01735 }
01736
01737
01738
01739 bool KateCSAndSIndent::inStatement( const KateDocCursor &begin )
01740 {
01741
01742
01743 KateTextLine::Ptr textLine = doc->plainKateTextLine(begin.line());
01744 const int first = textLine->firstChar();
01745
01746
01747
01748 const int attrib = textLine->attribute(first);
01749 if( first >= 0 && (attrib == 0 || attrib == symbolAttrib) && textLine->getChar(first) == '{' )
01750 return false;
01751
01752 int line;
01753 for ( line = begin.line() - 1; line >= 0; --line )
01754 {
01755 textLine = doc->plainKateTextLine(line);
01756 const int first = textLine->firstChar();
01757 if ( first == -1 )
01758 continue;
01759
01760
01761
01762 if ( textLine->getChar( first ) == '#' )
01763 continue;
01764 KateDocCursor currLine = begin;
01765 currLine.setLine( line );
01766 const int last = lastNonCommentChar( currLine );
01767 if ( last < first )
01768 continue;
01769
01770
01771
01772
01773
01774
01775 const int attrib = textLine->attribute(last);
01776 if ( attrib == commentAttrib || attrib == doxyCommentAttrib )
01777 return false;
01778
01779 char c = textLine->getChar(last);
01780
01781
01782 if ( attrib == symbolAttrib && c == '{' || c == '}' )
01783 return false;
01784
01785
01786 if ( attrib == symbolAttrib && c == ';' )
01787 return inForStatement( line );
01788
01789
01790 if ( attrib == symbolAttrib && c == ':' )
01791 {
01792
01793
01794
01795
01796 if( startsWithLabel( line ) )
01797 {
01798
01799
01800
01801
01802 continue;
01803 }
01804 }
01805
01806
01807 return true;
01808 }
01809
01810 return false;
01811 }
01812
01813 QString KateCSAndSIndent::continuationIndent( const KateDocCursor &begin )
01814 {
01815 if( !inStatement( begin ) )
01816 return QString::null;
01817 return indentString;
01818 }
01819
01823 QString KateCSAndSIndent::calcIndent (const KateDocCursor &begin)
01824 {
01825 KateTextLine::Ptr currLine = doc->plainKateTextLine(begin.line());
01826 int currLineFirst = currLine->firstChar();
01827
01828
01829
01830
01831 if ( currLineFirst >= 0 &&
01832 (currLine->attribute(currLineFirst) == commentAttrib ||
01833 currLine->attribute(currLineFirst) == doxyCommentAttrib) )
01834 return currLine->string( 0, currLineFirst );
01835
01836
01837 if( currLineFirst >= 0 && currLine->getChar(currLineFirst) == '#' )
01838 {
01839 if( !currLine->stringAtPos( currLineFirst+1, QString::fromLatin1("region") ) &&
01840 !currLine->stringAtPos( currLineFirst+1, QString::fromLatin1("endregion") ) )
01841 return QString::null;
01842 }
01843
01844
01845
01846
01847
01848
01849
01850
01851 KateDocCursor cur = begin;
01852 int pos, openBraceCount = 0, openParenCount = 0;
01853 bool lookingForScopeKeywords = true;
01854 const char * const scopeKeywords[] = { "for", "do", "while", "if", "else" };
01855 const char * const blockScopeKeywords[] = { "try", "catch", "switch" };
01856
01857 while (cur.gotoPreviousLine())
01858 {
01859 KateTextLine::Ptr textLine = doc->plainKateTextLine(cur.line());
01860 const int lastChar = textLine->lastChar();
01861 const int firstChar = textLine->firstChar();
01862
01863
01864 for( pos = lastChar; pos >= firstChar; --pos )
01865 {
01866 if (textLine->attribute(pos) == symbolAttrib)
01867 {
01868 char tc = textLine->getChar (pos);
01869 switch( tc )
01870 {
01871 case '(': case '[':
01872 if( ++openParenCount > 0 )
01873 return calcIndentInBracket( begin, cur, pos );
01874 break;
01875 case ')': case ']': openParenCount--; break;
01876 case '{':
01877 if( ++openBraceCount > 0 )
01878 return calcIndentInBrace( begin, cur, pos );
01879 break;
01880 case '}': openBraceCount--; lookingForScopeKeywords = false; break;
01881 case ';':
01882 if( openParenCount == 0 )
01883 lookingForScopeKeywords = false;
01884 break;
01885 }
01886 }
01887
01888
01889
01890 if ( lookingForScopeKeywords && openParenCount == 0 &&
01891 textLine->attribute(pos) == keywordAttrib &&
01892 (pos == 0 || textLine->attribute(pos-1) != keywordAttrib ) )
01893 {
01894 #define ARRLEN( array ) ( sizeof(array)/sizeof(array[0]) )
01895 for( uint n = 0; n < ARRLEN(scopeKeywords); ++n )
01896 if( textLine->stringAtPos(pos, QString::fromLatin1(scopeKeywords[n]) ) )
01897 return calcIndentAfterKeyword( begin, cur, pos, false );
01898 for( uint n = 0; n < ARRLEN(blockScopeKeywords); ++n )
01899 if( textLine->stringAtPos(pos, QString::fromLatin1(blockScopeKeywords[n]) ) )
01900 return calcIndentAfterKeyword( begin, cur, pos, true );
01901 #undef ARRLEN
01902 }
01903 }
01904 }
01905
01906
01907 return QString::null;
01908 }
01909
01910 QString KateCSAndSIndent::calcIndentInBracket(const KateDocCursor &indentCursor, const KateDocCursor &bracketCursor, int bracketPos)
01911 {
01912 KateTextLine::Ptr indentLine = doc->plainKateTextLine(indentCursor.line());
01913 KateTextLine::Ptr bracketLine = doc->plainKateTextLine(bracketCursor.line());
01914
01915
01916
01917 if ( bracketPos > 48 )
01918 {
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929 return indentString + initialWhitespace( bracketLine, bracketLine->firstChar() );
01930 }
01931
01932 const int indentLineFirst = indentLine->firstChar();
01933
01934 int indentTo;
01935 const int attrib = indentLine->attribute(indentLineFirst);
01936 if( indentLineFirst >= 0 && (attrib == 0 || attrib == symbolAttrib) &&
01937 ( indentLine->getChar(indentLineFirst) == ')' || indentLine->getChar(indentLineFirst) == ']' ) )
01938 {
01939
01940 indentTo = bracketPos;
01941 }
01942 else
01943 {
01944
01945 indentTo = bracketLine->nextNonSpaceChar( bracketPos + 1 );
01946 if( indentTo == -1 )
01947 indentTo = bracketPos + 2;
01948 }
01949 return initialWhitespace( bracketLine, indentTo );
01950 }
01951
01952 QString KateCSAndSIndent::calcIndentAfterKeyword(const KateDocCursor &indentCursor, const KateDocCursor &keywordCursor, int keywordPos, bool blockKeyword)
01953 {
01954 KateTextLine::Ptr keywordLine = doc->plainKateTextLine(keywordCursor.line());
01955 KateTextLine::Ptr indentLine = doc->plainKateTextLine(indentCursor.line());
01956
01957 QString whitespaceToKeyword = initialWhitespace( keywordLine, keywordPos, false );
01958 if( blockKeyword ) {
01959
01960 }
01961
01962
01963 int first = indentLine->firstChar();
01964
01965 const int attrib = indentLine->attribute(first);
01966 if( first >= 0 && (attrib == 0 || attrib == symbolAttrib) && indentLine->getChar(first) == '{' )
01967 return whitespaceToKeyword;
01968
01969
01970
01971
01972
01973
01974
01975
01976 return indentString + whitespaceToKeyword;
01977 }
01978
01979 QString KateCSAndSIndent::calcIndentInBrace(const KateDocCursor &indentCursor, const KateDocCursor &braceCursor, int bracePos)
01980 {
01981 KateTextLine::Ptr braceLine = doc->plainKateTextLine(braceCursor.line());
01982 const int braceFirst = braceLine->firstChar();
01983
01984 QString whitespaceToOpenBrace = initialWhitespace( braceLine, bracePos, false );
01985
01986
01987
01988
01989
01990 {
01991 if( braceFirst >= 0 && braceLine->attribute(braceFirst) == keywordAttrib &&
01992 braceLine->stringAtPos( braceFirst, QString::fromLatin1( "namespace" ) ) )
01993 return continuationIndent(indentCursor) + whitespaceToOpenBrace;
01994
01995 if( braceCursor.line() > 0 )
01996 {
01997 KateTextLine::Ptr prevLine = doc->plainKateTextLine(braceCursor.line() - 1);
01998 int firstPrev = prevLine->firstChar();
01999 if( firstPrev >= 0 && prevLine->attribute(firstPrev) == keywordAttrib &&
02000 prevLine->stringAtPos( firstPrev, QString::fromLatin1( "namespace" ) ) )
02001 return continuationIndent(indentCursor) + whitespaceToOpenBrace;
02002 }
02003 }
02004
02005 KateTextLine::Ptr indentLine = doc->plainKateTextLine(indentCursor.line());
02006 const int indentFirst = indentLine->firstChar();
02007
02008
02009 if( indentFirst >= 0 && indentLine->getChar(indentFirst) == '}' )
02010 return whitespaceToOpenBrace;
02011
02012
02013
02014 if ( indentFirst >= 0 && indentLine->attribute(indentFirst) == symbolAttrib &&
02015 indentLine->getChar(indentFirst) == ':' && indentLine->getChar(indentFirst+1) != ':' )
02016 {
02017 return indentString + indentString + whitespaceToOpenBrace;
02018 }
02019
02020 const bool continuation = inStatement(indentCursor);
02021
02022 if( !continuation && startsWithLabel( indentCursor.line() ) )
02023 return whitespaceToOpenBrace;
02024
02025
02026 QString continuationIndent = continuation ? indentString : QString::null;
02027 return indentString + continuationIndent + whitespaceToOpenBrace;
02028 }
02029
02030 void KateCSAndSIndent::processChar(QChar c)
02031 {
02032
02033 static const QString triggers("}{)]/:;#n");
02034 if (triggers.find(c) == -1)
02035 return;
02036
02037
02038
02039 KateView *view = doc->activeView();
02040 KateDocCursor begin(view->cursorLine(), 0, doc);
02041
02042 KateTextLine::Ptr textLine = doc->plainKateTextLine(begin.line());
02043 if ( c == 'n' )
02044 {
02045 int first = textLine->firstChar();
02046 if( first < 0 || textLine->getChar(first) != '#' )
02047 return;
02048 }
02049
02050 if ( textLine->attribute( begin.col() ) == doxyCommentAttrib )
02051 {
02052
02053 if ( c == '/' )
02054 {
02055 int first = textLine->firstChar();
02056
02057
02058 if ( first != -1
02059 && textLine->getChar( first ) == '*'
02060 && textLine->nextNonSpaceChar( first+1 ) == view->cursorColumnReal()-1 )
02061 doc->removeText( view->cursorLine(), first+1, view->cursorLine(), view->cursorColumnReal()-1);
02062 }
02063
02064
02065 return;
02066 }
02067
02068 processLine(begin);
02069 }
02070
02071
02072
02073
02074 class KateVarIndentPrivate {
02075 public:
02076 QRegExp reIndentAfter, reIndent, reUnindent;
02077 QString triggers;
02078 uint couples;
02079 uchar coupleAttrib;
02080 };
02081
02082 KateVarIndent::KateVarIndent( KateDocument *doc )
02083 : KateNormalIndent( doc )
02084 {
02085 d = new KateVarIndentPrivate;
02086 d->reIndentAfter = QRegExp( doc->variable( "var-indent-indent-after" ) );
02087 d->reIndent = QRegExp( doc->variable( "var-indent-indent" ) );
02088 d->reUnindent = QRegExp( doc->variable( "var-indent-unindent" ) );
02089 d->triggers = doc->variable( "var-indent-triggerchars" );
02090 d->coupleAttrib = 0;
02091
02092 slotVariableChanged( "var-indent-couple-attribute", doc->variable( "var-indent-couple-attribute" ) );
02093 slotVariableChanged( "var-indent-handle-couples", doc->variable( "var-indent-handle-couples" ) );
02094
02095
02096 connect( doc, SIGNAL(variableChanged( const QString&, const QString&) ),
02097 this, SLOT(slotVariableChanged( const QString&, const QString& )) );
02098 }
02099
02100 KateVarIndent::~KateVarIndent()
02101 {
02102 delete d;
02103 }
02104
02105 void KateVarIndent::processNewline ( KateDocCursor &begin, bool )
02106 {
02107
02108 KateDocCursor left( begin.line()-1, 0, doc );
02109 processLine( left );
02110 processLine( begin );
02111 }
02112
02113 void KateVarIndent::processChar ( QChar c )
02114 {
02115
02116 if ( d->triggers.contains( c ) )
02117 {
02118 KateTextLine::Ptr ln = doc->plainKateTextLine( doc->activeView()->cursorLine() );
02119 if ( ln->attribute( doc->activeView()->cursorColumn()-1 ) == commentAttrib )
02120 return;
02121
02122 KateView *view = doc->activeView();
02123 KateDocCursor begin( view->cursorLine(), 0, doc );
02124 kdDebug(13030)<<"variable indenter: process char '"<<c<<", line "<<begin.line()<<endl;
02125 processLine( begin );
02126 }
02127 }
02128
02129 void KateVarIndent::processLine ( KateDocCursor &line )
02130 {
02131 QString indent;
02132
02133
02134
02135 int ln = line.line();
02136 int pos = -1;
02137 KateTextLine::Ptr ktl = doc->plainKateTextLine( ln );
02138 if ( ! ktl ) return;
02139
02140
02141 KateView *v = doc->activeView();
02142 if ( (ktl->firstChar() < 0) && (!v || (int)v->cursorLine() != ln ) )
02143 return;
02144
02145 int fc;
02146 if ( ln > 0 )
02147 do
02148 {
02149
02150 ktl = doc->plainKateTextLine( --ln );
02151 fc = ktl->firstChar();
02152 if ( ktl->attribute( fc ) != commentAttrib )
02153 pos = fc;
02154 }
02155 while ( (ln > 0) && (pos < 0) );
02156
02157 if ( pos < 0 )
02158 pos = 0;
02159 else
02160 pos = ktl->cursorX( pos, tabWidth );
02161
02162 int adjustment = 0;
02163
02164
02165
02166 if ( d->couples & Parens && coupleBalance( ln, '(', ')' ) > 0 )
02167 adjustment++;
02168 else if ( d->couples & Braces && coupleBalance( ln, '{', '}' ) > 0 )
02169 adjustment++;
02170 else if ( d->couples & Brackets && coupleBalance( ln, '[', ']' ) > 0 )
02171 adjustment++;
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183 {
02184 KateTextLine::Ptr tl = doc->plainKateTextLine( line.line() );
02185 int i = tl->firstChar();
02186 if ( i > -1 )
02187 {
02188 QChar ch = tl->getChar( i );
02189 uchar at = tl->attribute( i );
02190 kdDebug(13030)<<"attrib is "<<at<<endl;
02191 if ( d->couples & Parens && ch == ')'
02192 && ( at == d->coupleAttrib
02193 || (! at && hasRelevantOpening( KateDocCursor( line.line(), i, doc ) ))
02194 )
02195 )
02196 adjustment--;
02197 else if ( d->couples & Braces && ch == '}'
02198 && ( at == d->coupleAttrib
02199 || (! at && hasRelevantOpening( KateDocCursor( line.line(), i, doc ) ))
02200 )
02201 )
02202 adjustment--;
02203 else if ( d->couples & Brackets && ch == ']'
02204 && ( at == d->coupleAttrib
02205 || (! at && hasRelevantOpening( KateDocCursor( line.line(), i, doc ) ))
02206 )
02207 )
02208 adjustment--;
02209 }
02210 }
02211 #define ISCOMMENTATTR(attr) (attr==commentAttrib||attr==doxyCommentAttrib)
02212 #define ISCOMMENT (ISCOMMENTATTR(ktl->attribute(ktl->firstChar()))||ISCOMMENTATTR(ktl->attribute(matchpos)))
02213
02214
02215 kdDebug(13030)<<"variable indenter: starting indent: "<<pos<<endl;
02216
02217 int matchpos = 0;
02218 if ( ktl && ! d->reIndentAfter.isEmpty()
02219 && (matchpos = d->reIndentAfter.search( doc->textLine( ln ) )) > -1
02220 && ! ISCOMMENT )
02221 adjustment++;
02222
02223
02224 ktl = doc->plainKateTextLine( line.line() );
02225 if ( ! d->reIndent.isEmpty()
02226 && (matchpos = d->reIndent.search( doc->textLine( line.line() ) )) > -1
02227 && ! ISCOMMENT )
02228 adjustment++;
02229
02230
02231 if ( ! d->reUnindent.isEmpty()
02232 && (matchpos = d->reUnindent.search( doc->textLine( line.line() ) )) > -1
02233 && ! ISCOMMENT )
02234 adjustment--;
02235
02236 kdDebug(13030)<<"variable indenter: adjusting by "<<adjustment<<" units"<<endl;
02237
02238 if ( adjustment > 0 )
02239 pos += indentWidth;
02240 else if ( adjustment < 0 )
02241 pos -= indentWidth;
02242
02243 ln = line.line();
02244 fc = doc->plainKateTextLine( ln )->firstChar();
02245
02246
02247
02248
02249
02250 if ( fc == pos )
02251 return;
02252
02253 if ( fc > 0 )
02254 doc->removeText (ln, 0, ln, fc );
02255
02256 if ( pos > 0 )
02257 indent = tabString( pos );
02258
02259 if ( pos > 0 )
02260 doc->insertText (ln, 0, indent);
02261
02262
02263 line.setCol( pos );
02264 }
02265
02266 void KateVarIndent::processSection (const KateDocCursor &begin, const KateDocCursor &end)
02267 {
02268 KateDocCursor cur = begin;
02269 while (cur.line() <= end.line())
02270 {
02271 processLine (cur);
02272 if (!cur.gotoNextLine())
02273 break;
02274 }
02275 }
02276
02277 void KateVarIndent::slotVariableChanged( const QString &var, const QString &val )
02278 {
02279 if ( ! var.startsWith("var-indent") )
02280 return;
02281
02282 if ( var == "var-indent-indent-after" )
02283 d->reIndentAfter.setPattern( val );
02284 else if ( var == "var-indent-indent" )
02285 d->reIndent.setPattern( val );
02286 else if ( var == "var-indent-unindent" )
02287 d->reUnindent.setPattern( val );
02288 else if ( var == "var-indent-triggerchars" )
02289 d->triggers = val;
02290 else if ( var == "var-indent-handle-couples" )
02291 {
02292 d->couples = 0;
02293 QStringList l = QStringList::split( " ", val );
02294 if ( l.contains("parens") ) d->couples |= Parens;
02295 if ( l.contains("braces") ) d->couples |= Braces;
02296 if ( l.contains("brackets") ) d->couples |= Brackets;
02297 }
02298 else if ( var == "var-indent-couple-attribute" )
02299 {
02300
02301 KateHlItemDataList items;
02302 doc->highlight()->getKateHlItemDataListCopy (0, items);
02303
02304 for (uint i=0; i<items.count(); i++)
02305 {
02306 if ( items.at(i)->name.section( ':', 1 ) == val )
02307 {
02308 d->coupleAttrib = i;
02309 break;
02310 }
02311 }
02312 }
02313 }
02314
02315 int KateVarIndent::coupleBalance ( int line, const QChar &open, const QChar &close ) const
02316 {
02317 int r = 0;
02318
02319 KateTextLine::Ptr ln = doc->plainKateTextLine( line );
02320 if ( ! ln || ! ln->length() ) return 0;
02321
02322 for ( uint z=0; z < ln->length(); z++ )
02323 {
02324 QChar c = ln->getChar( z );
02325 if ( ln->attribute(z) == d->coupleAttrib )
02326 {
02327 kdDebug(13030)<<z<<", "<<c<<endl;
02328 if (c == open)
02329 r++;
02330 else if (c == close)
02331 r--;
02332 }
02333 }
02334 return r;
02335 }
02336
02337 bool KateVarIndent::hasRelevantOpening( const KateDocCursor &end ) const
02338 {
02339 KateDocCursor cur = end;
02340 int count = 1;
02341
02342 QChar close = cur.currentChar();
02343 QChar opener;
02344 if ( close == '}' ) opener = '{';
02345 else if ( close = ')' ) opener = '(';
02346 else if (close = ']' ) opener = '[';
02347 else return false;
02348
02349
02350 while (cur.moveBackward(1))
02351 {
02352 if (cur.currentAttrib() == d->coupleAttrib)
02353 {
02354 QChar ch = cur.currentChar();
02355 if (ch == opener)
02356 count--;
02357 else if (ch == close)
02358 count++;
02359
02360 if (count == 0)
02361 return true;
02362 }
02363 }
02364
02365 return false;
02366 }
02367
02368
02369
02370
02371
02372 KateScriptIndent::KateScriptIndent( KateDocument *doc )
02373 : KateNormalIndent( doc )
02374 {
02375 m_script=KateFactory::self()->indentScript ("script-indent-c1-test");
02376 }
02377
02378 KateScriptIndent::~KateScriptIndent()
02379 {
02380 }
02381
02382 void KateScriptIndent::processNewline( KateDocCursor &begin, bool needContinue )
02383 {
02384 kdDebug(13030) << "processNewline" << endl;
02385 KateView *view = doc->activeView();
02386
02387 if (view)
02388 {
02389 QString errorMsg;
02390
02391 QTime t;
02392 t.start();
02393 kdDebug(13030)<<"calling m_script.processChar"<<endl;
02394 if( !m_script.processNewline( view, begin, needContinue , errorMsg ) )
02395 {
02396 kdDebug(13030) << "Error in script-indent: " << errorMsg << endl;
02397 }
02398 kdDebug(13030) << "ScriptIndent::TIME in ms: " << t.elapsed() << endl;
02399 }
02400 }
02401
02402 void KateScriptIndent::processChar( QChar c )
02403 {
02404 kdDebug(13030) << "processChar" << endl;
02405 KateView *view = doc->activeView();
02406
02407 if (view)
02408 {
02409 QString errorMsg;
02410
02411 QTime t;
02412 t.start();
02413 kdDebug(13030)<<"calling m_script.processChar"<<endl;
02414 if( !m_script.processChar( view, c , errorMsg ) )
02415 {
02416 kdDebug(13030) << "Error in script-indent: " << errorMsg << endl;
02417 }
02418 kdDebug(13030) << "ScriptIndent::TIME in ms: " << t.elapsed() << endl;
02419 }
02420 }
02421
02422 void KateScriptIndent::processLine (KateDocCursor &line)
02423 {
02424 kdDebug(13030) << "processLine" << endl;
02425 KateView *view = doc->activeView();
02426
02427 if (view)
02428 {
02429 QString errorMsg;
02430
02431 QTime t;
02432 t.start();
02433 kdDebug(13030)<<"calling m_script.processLine"<<endl;
02434 if( !m_script.processLine( view, line , errorMsg ) )
02435 {
02436 kdDebug(13030) << "Error in script-indent: " << errorMsg << endl;
02437 }
02438 kdDebug(13030) << "ScriptIndent::TIME in ms: " << t.elapsed() << endl;
02439 }
02440 }
02441
02442
02443
02444 #include <qlabel.h>
02445 ScriptIndentConfigPage::ScriptIndentConfigPage ( QWidget *parent, const char *name )
02446 : IndenterConfigPage(parent, name)
02447 {
02448 QLabel* hello = new QLabel("Hello world! Dummy for testing purpose.", this);
02449 hello->show();
02450 }
02451
02452 ScriptIndentConfigPage::~ScriptIndentConfigPage ()
02453 {
02454 }
02455
02456 void ScriptIndentConfigPage::apply ()
02457 {
02458 kdDebug(13030) << "ScriptIndentConfigPagE::apply() was called, save config options now!" << endl;
02459 }
02460
02461
02462