# khtml Library API Documentation

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

# kjs_debugwin.cpp

    00001 /*
    00002  *  This file is part of the KDE libraries
    00003  *  Copyright (C) 2000-2001 Harri Porten (porten@kde.org)
    00004  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
    00005  *
    00006  *  This library is free software; you can redistribute it and/or
    00007  *  modify it under the terms of the GNU Library General Public
    00008  *  License as published by the Free Software Foundation; either
    00009  *  version 2 of the License, or (at your option) any later version.
    00010  *
    00011  *  This library is distributed in the hope that it will be useful,
    00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00014  *  Library General Public License for more details.
    00015  *
    00016  *  You should have received a copy of the GNU Library General Public
    00017  *  License along with this library; if not, write to the Free Software
    00018  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    00019  */
    00020
    00021 #include "kjs_debugwin.h"
    00022
    00023 #ifdef KJS_DEBUGGER
    00024
    00025 #include <assert.h>
    00026 #include <qlayout.h>
    00027 #include <qpushbutton.h>
    00028 #include <qtextedit.h>
    00029 #include <qlistbox.h>
    00030 #include <qlineedit.h>
    00031 #include <qapplication.h>
    00032 #include <qsplitter.h>
    00033 #include <qcombobox.h>
    00034 #include <qbitmap.h>
    00035 #include <qwidgetlist.h>
    00036
    00037 #include <klocale.h>
    00038 #include <kdebug.h>
    00039 #include <kiconloader.h>
    00040 #include <kmessagebox.h>
    00041
    00042 #include "kjs_dom.h"
    00043 #include <kjs/ustring.h>
    00044 #include <kjs/object.h>
    00045 #include <kjs/function.h>
    00046 #include <kjs/interpreter.h>
    00047
    00048 using namespace KJS;
    00049
    00050 KJSDebugWin * KJSDebugWin::kjs_html_debugger = 0;
    00051
    00052 bool FakeModal::eventFilter( QObject *o, QEvent *e )
    00053 {
    00054     switch (e->type()) {
    00055         case QEvent::MouseButtonPress:
    00056         case QEvent::MouseButtonRelease:
    00057         case QEvent::MouseButtonDblClick:
    00058         case QEvent::MouseMove:
    00059         case QEvent::KeyPress:
    00060         case QEvent::KeyRelease:
    00061         case QEvent::Destroy:
    00062         case QEvent::Close:
    00063         case QEvent::Quit:
    00064             while (o->parent())
    00065                 o = o->parent();
    00066             if (o == modalWidget)
    00067                 return QWidget::eventFilter( o, e );
    00068             else
    00069                 return TRUE;
    00070             break;
    00071         default:
    00072             return QWidget::eventFilter( o, e );
    00073     }
    00074 }
    00075
    00076
    00077 void FakeModal::enable(QWidget *modal)
    00078 {
    00079     QWidgetList *widgets = QApplication::allWidgets();
    00080     QWidgetListIt it(*widgets);
    00081     for (; it.current(); ++it)
    00082         it.current()->installEventFilter(this);
    00083     modalWidget = modal;
    00084 }
    00085
    00086 void FakeModal::disable()
    00087 {
    00088     QWidgetList *widgets = QApplication::allWidgets();
    00089     QWidgetListIt it(*widgets);
    00090     for (; it.current(); ++it)
    00091         it.current()->removeEventFilter(this);
    00092     modalWidget = 0;
    00093 }
    00094
    00095 //-------------------------------------------------------------------------
    00096
    00097 QString StackFrame::toString()
    00098 {
    00099   QString str = "";
    00100   if (!name.isNull())
    00101     str.sprintf("%s() at sourceId %d, line %d",name.ascii(),sourceId,lineno);
    00102   else
    00103     str.sprintf("??? at sourceId %d, line %d",sourceId,lineno);
    00104   return str;
    00105 }
    00106
    00107 SourceFragment::SourceFragment(int sid, int bl, SourceFile *sf)
    00108 {
    00109   sourceId = sid;
    00110   baseLine = bl;
    00111   sourceFile = sf;
    00112   sourceFile->ref();
    00113 }
    00114
    00115 SourceFragment::~SourceFragment()
    00116 {
    00117   sourceFile->deref();
    00118 }
    00119
    00120 //-------------------------------------------------------------------------
    00121
    00122 KJSDebugWin::KJSDebugWin(QWidget *parent, const char *name)
    00123   : QWidget(parent, name),
    00124     m_inSession(false),
    00125     m_curSourceFile(0)
    00126 {
    00127   setCaption(i18n("JavaScript Debugger"));
    00128   QVBoxLayout *vl = new QVBoxLayout(this, 5);
    00129
    00130   // frame list & code
    00131   QSplitter *splitter = new QSplitter(this);
    00132   QFont font("courier",10);
    00133
    00134   m_frameList = new QListBox(splitter);
    00135   m_frameList->setFont(font);
    00136   m_frameList->setMinimumSize(100,200);
    00137   connect(m_frameList,SIGNAL(highlighted(int)),this,SLOT(showFrame(int)));
    00138
    00139   // source selection & display
    00140   QWidget *sourceSelDisplay = new QWidget(splitter);
    00141   QVBoxLayout *ssdvl = new QVBoxLayout(sourceSelDisplay);
    00142
    00143
    00144   m_sourceSel = new QComboBox(sourceSelDisplay);
    00145   connect(m_sourceSel,SIGNAL(activated(int)),this,SLOT(sourceSelected(int)));
    00146   ssdvl->addWidget(m_sourceSel);
    00147
    00148   m_sourceDisplay = new QListBox(sourceSelDisplay);
    00149   m_sourceDisplay->setFont(font);
    00150   ssdvl->addWidget(m_sourceDisplay);
    00151
    00152   vl->addWidget(splitter);
    00153
    00154   QValueList<int> splitSizes;
    00155   splitSizes.insert(splitSizes.end(),200);
    00156   splitSizes.insert(splitSizes.end(),400);
    00157   splitter->setSizes(splitSizes);
    00158
    00159
    00160   // evaluate
    00161   QHBoxLayout *hl1 = new QHBoxLayout(vl);
    00162   m_evalEdit = new QLineEdit(this);
    00163   m_evalButton = new QPushButton(i18n("&Evaluate"),this);
    00164   m_evalButton->setEnabled(false);
    00165   hl1->addWidget(m_evalEdit);
    00166   hl1->addWidget(m_evalButton);
    00167   connect(m_evalButton, SIGNAL(clicked()), SLOT(eval()));
    00168   connect(m_evalEdit, SIGNAL(returnPressed()), SLOT(eval()));
    00169
    00170   // control buttons
    00171   QHBoxLayout *hl2 = new QHBoxLayout(vl);
    00172   m_nextButton = new QPushButton(i18n("&Next"), this);
    00173   m_stepButton = new QPushButton(i18n("&Step"), this);
    00174   m_continueButton = new QPushButton(i18n("&Continue"), this);
    00175   m_stopButton = new QPushButton(i18n("St&op"), this);
    00176   m_breakButton = new QPushButton(i18n("&Break at next Statement"), this);
    00177   m_breakpointButton = new QPushButton(i18n("&Toggle Breakpoint"), this);
    00178   hl2->addWidget(m_nextButton);
    00179   hl2->addWidget(m_stepButton);
    00180   hl2->addWidget(m_continueButton);
    00181   hl2->addWidget(m_stopButton);
    00182   hl2->addWidget(m_breakButton);
    00183   hl2->addWidget(m_breakpointButton);
    00184   hl2->addStretch();
    00185
    00186   connect(m_nextButton, SIGNAL(clicked()), SLOT(next()));
    00187   connect(m_stepButton, SIGNAL(clicked()), SLOT(step()));
    00188   connect(m_continueButton, SIGNAL(clicked()), SLOT(cont()));
    00189   connect(m_stopButton, SIGNAL(clicked()), SLOT(stop()));
    00190   connect(m_breakButton, SIGNAL(clicked()), SLOT(breakNext()));
    00191   connect(m_breakpointButton, SIGNAL(clicked()), SLOT(toggleBreakpoint()));
    00192
    00193   m_nextButton->setEnabled(false);
    00194   m_stepButton->setEnabled(false);
    00195   m_continueButton->setEnabled(false);
    00196   m_stopButton->setEnabled(false);
    00197   m_breakButton->setEnabled(true);
    00198   m_breakpointButton->setEnabled(false);
    00199
    00200   // frame list
    00201   m_frames.setAutoDelete(true);
    00202   StackFrame *sf = new StackFrame(-1,-1,"Global code",false);
    00203   sf->next = true;
    00204   m_frames.append(sf);
    00205   //  m_frameList->insertItem(sf->toString());
    00206
    00207
    00208   setMinimumSize(300,200);
    00209   resize(600,450);
    00210   m_mode = Continue;
    00211   m_sourceBreakpoints = 0;
    00212
    00213   KIconLoader loader;
    00214   m_stopIcon = loader.loadIcon("stop",KIcon::Small);
    00215
    00216   m_emptyIcon = QPixmap(m_stopIcon.width(),m_stopIcon.height());
    00217   QBitmap emptyMask(m_stopIcon.width(),m_stopIcon.height(),true);
    00218   //  m_emptyIcon.fill(m_sourceDisplay,0,0);
    00219   m_emptyIcon.setMask(emptyMask);
    00220
    00221   m_nextSourceBaseLine = 0;
    00222   m_nextSourceUrl = "";
    00223
    00224   updateFrameList();
    00225   m_inSession = false;
    00226   m_curExecState = 0;
    00227 }
    00228
    00229 KJSDebugWin::~KJSDebugWin()
    00230 {
    00231 }
    00232
    00233
    00234 KJSDebugWin *KJSDebugWin::createInstance()
    00235 {
    00236   assert(!kjs_html_debugger);
    00237   kjs_html_debugger = new KJSDebugWin();
    00238   kjs_html_debugger->show();
    00239   return kjs_html_debugger;
    00240 }
    00241
    00242 void KJSDebugWin::destroyInstance()
    00243 {
    00244   assert(kjs_html_debugger);
    00245   kjs_html_debugger->hide();
    00246   delete kjs_html_debugger;
    00247 }
    00248
    00249 void KJSDebugWin::next()
    00250 {
    00251   m_mode = Next;
    00252   leaveSession();
    00253 }
    00254
    00255 void KJSDebugWin::step()
    00256 {
    00257   m_mode = Step;
    00258   leaveSession();
    00259 }
    00260
    00261 void KJSDebugWin::cont()
    00262 {
    00263   m_mode = Continue;
    00264   leaveSession();
    00265 }
    00266
    00267 void KJSDebugWin::stop()
    00268 {
    00269   m_mode = Stop;
    00270   leaveSession();
    00271 }
    00272
    00273 void KJSDebugWin::breakNext()
    00274 {
    00275   m_mode = Step;
    00276 }
    00277
    00278 void KJSDebugWin::toggleBreakpoint()
    00279 {
    00280     int line = m_sourceDisplay->currentItem();
    00281     if (line >= 0) {
    00282         QString text(m_sourceDisplay->item(line)->text());
    00283         m_sourceDisplay->removeItem(line);
    00284         QListBoxPixmap *item;
    00285         if (setBreakpoint(m_frames.last()->sourceId, line)) {
    00286             item = new QListBoxPixmap(m_stopIcon,text);
    00287         } else {
    00288             deleteBreakpoint(m_frames.last()->sourceId, line);
    00289             item = new QListBoxPixmap(m_emptyIcon,text);
    00290         }
    00291         m_sourceDisplay->insertItem(item, line);
    00292         m_sourceDisplay->setCurrentItem(line);
    00293     }
    00294 }
    00295
    00296 void KJSDebugWin::showFrame(int frameno)
    00297 {
    00298   StackFrame *frame = m_frames.at(frameno);
    00299   if (!frame)
    00300     return;
    00301   highLight(frame->sourceId,frame->lineno);
    00302 }
    00303
    00304 void KJSDebugWin::sourceSelected(int sourceSelIndex)
    00305 {
    00306   // a souce file has been selected from the drop-down list - display the file
    00307   // and hilight the line if it's in the current stack frame
    00308   if (sourceSelIndex < 0 || sourceSelIndex >= (int)m_sourceSel->count())
    00309     return;
    00310   SourceFile *sourceFile = m_sourceSelFiles[sourceSelIndex];
    00311   bool newsource = m_curSourceFile != sourceFile;
    00312   m_curSourceFile = sourceFile;
    00313
    00314   SourceFragment *lastFragment = 0;
    00315   StackFrame *curFrame = m_frames.at(m_frameList->currentItem() >= 0 ? m_frameList->currentItem() : m_frames.count()-1);
    00316   if (curFrame)
    00317     lastFragment = m_sourceFragments[curFrame->sourceId];
    00318   if (newsource)
    00319       setCode(sourceFile->code, curFrame ? curFrame->sourceId : -1);
    00320   if (lastFragment && lastFragment->sourceFile == m_curSourceFile) {
    00321     m_sourceDisplay->setCurrentItem(lastFragment->baseLine+curFrame->lineno);
    00322   } else
    00323     m_sourceDisplay->setCurrentItem(-1);
    00324 }
    00325
    00326 void KJSDebugWin::eval()
    00327 {
    00328   // evaluate the js code from m_evalEdit
    00329 /*
    00330   if (!m_inSession)
    00331     return;
    00332
    00333   // create function
    00334   KJS::Constructor constr(KJS::Global::current().get("Function").imp());
    00335   KJS::List args;
    00336   args.append(KJS::String("event"));
    00337   args.append(KJS::String("return "+m_evalEdit->text()+";"));
    00338   KJS::KJSO func = constr.construct(args);
    00339   // execute
    00340   Mode oldMode = m_mode;
    00341   m_mode = Continue; // prevents us from stopping during evaluation
    00342
    00343   KJSO ret = m_curContext->executeCall(m_curScript,func,func,0);
    00344   KMessageBox::information(this, ret.toString().value().qstring(), "JavaScript eval");
    00345   m_mode = oldMode;
    00346   */
    00347 }
    00348
    00349 void KJSDebugWin::closeEvent(QCloseEvent *e)
    00350 {
    00351   if (m_inSession)
    00352     leaveSession();
    00353   return QWidget::closeEvent(e);
    00354 }
    00355
    00356 bool KJSDebugWin::sourceParsed(KJS::ExecState * exec, int sourceId,
    00357                                const KJS::UString &source, int /*errorLine*/)
    00358 {
    00359   // the interpreter has parsed some js code - store it in a SourceFragment object
    00360   // ### report errors (errorLine >= 0)
    00361
    00362   SourceFile *sourceFile = m_sourceFiles[m_nextSourceUrl];
    00363   if (!sourceFile) {
    00364     sourceFile = new SourceFile("(unknown)",source.qstring(),m_sourceSel->count());
    00365     m_sourceSelFiles[sourceFile->index] = sourceFile;
    00366     if (m_nextSourceUrl.isNull() || m_nextSourceUrl == "")
    00367         m_sourceSel->insertItem("???");
    00368     else
    00369         m_sourceSel->insertItem(m_nextSourceUrl);
    00370   }
    00371
    00372   SourceFragment *sf = new SourceFragment(sourceId,m_nextSourceBaseLine,sourceFile);
    00373   m_sourceFragments[sourceId] = sf;
    00374
    00375
    00376   m_nextSourceBaseLine = 0;
    00377   m_nextSourceUrl = "";
    00378
    00379   return (m_mode != Stop);
    00380 }
    00381
    00382 bool KJSDebugWin::sourceUnused(KJS::ExecState * /*exec*/, int sourceId)
    00383 {
    00384   // the source fragment is no longer in use, so we can free it
    00385
    00386   SourceFragment *fragment = m_sourceFragments[sourceId];
    00387   if (fragment) {
    00388       m_sourceFragments.erase(sourceId);
    00389       SourceFile *sourceFile = fragment->sourceFile;
    00390       if (sourceFile->hasOneRef()) {
    00391           m_sourceSel->removeItem(sourceFile->index);
    00392           for (int i = sourceFile->index; i < m_sourceSel->count(); i++) {
    00393               m_sourceSelFiles[i+1]->index--;
    00394               m_sourceSelFiles[i] = m_sourceSelFiles[i+1];
    00395           }
    00396           m_sourceSelFiles.erase(m_sourceSel->count());
    00397           m_sourceSel->removeItem(m_sourceSel->count()-1);
    00398       }
    00399       delete fragment;
    00400   }
    00401   return (m_mode != Stop);
    00402 }
    00403
    00404 bool KJSDebugWin::exception(KJS::ExecState *exec, int /*sourceId*/,
    00405         int /*lineno*/, KJS::Object &exceptionObj)
    00406 {
    00407   // ### bring up source & hilight line
    00408   KMessageBox::error(this, exceptionObj.toString(exec).qstring(), "JavaScript error");
    00409   return (m_mode != Stop);
    00410 }
    00411
    00412 bool KJSDebugWin::atStatement(KJS::ExecState *exec, int sourceId,
    00413                               int firstLine, int lastLine)
    00414 {
    00415   KJS::ExecState *oldCurExecState = m_curExecState;
    00416   m_curExecState = exec;
    00417
    00418   if (haveBreakpoint(sourceId,firstLine, lastLine)) {
    00419     m_mode = Next;
    00420     m_frames.last()->next = true;
    00421   }
    00422
    00423   m_frames.last()->sourceId = sourceId;
    00424   m_frames.last()->lineno = firstLine;
    00425   //  highLight(sourceId,lineno);
    00426   if (m_mode == KJSDebugWin::Step || m_mode == KJSDebugWin::Next) {
    00427     if (m_frames.last()->next)
    00428       enterSession();
    00429   }
    00430
    00431   m_curExecState = oldCurExecState;
    00432   return (m_mode != Stop);
    00433 }
    00434
    00435 bool KJSDebugWin::callEvent(KJS::ExecState *exec, int sourceId, int lineno,
    00436         KJS::Object &function, const KJS::List & /*args*/)
    00437 {
    00438   //  highLight(sourceId,lineno);
    00439   KJS::ExecState *oldCurExecState = m_curExecState;
    00440   m_curExecState = exec;
    00441   KJS::FunctionImp *fimp = static_cast<KJS::FunctionImp*>(function.imp());
    00442   QString name = fimp->name().qstring();
    00443   StackFrame *sf = new StackFrame(sourceId,lineno,name,m_mode == Step);
    00444   m_frames.append(sf);
    00445   if (m_mode == Step)
    00446     enterSession();
    00447   m_curExecState = oldCurExecState;
    00448   return (m_mode != Stop);
    00449 }
    00450
    00451 bool KJSDebugWin::returnEvent(KJS::ExecState *exec, int sourceId, int lineno,
    00452         KJS::Object & /*function*/)
    00453 {
    00454   //  highLight(sourceId,lineno);
    00455   KJS::ExecState *oldCurExecState = m_curExecState;
    00456   m_curExecState = exec;
    00457   m_frames.last()->sourceId = sourceId;
    00458   m_frames.last()->lineno = lineno;
    00459   if (m_frames.last()->step)
    00460     enterSession();
    00461   m_frames.removeLast();
    00462   //  m_frameList->removeItem(m_frameList->count()-1);
    00463   m_curExecState = oldCurExecState;
    00464   return (m_mode != Stop);
    00465 }
    00466
    00467 void KJSDebugWin::setCode(const QString &code, int sourceId)
    00468 {
    00469   const QChar *chars = code.unicode();
    00470   uint len = code.length();
    00471   QChar newLine('\n');
    00472   QChar cr('\r');
    00473   QChar tab('\t');
    00474   QString tabstr("        ");
    00475   QString line;
    00476   m_sourceDisplay->clear();
    00477   int numlines = 0;
    00478   for (uint i = 0; i < len; i++) {
    00479       if (chars[i] == cr)
    00480           continue;
    00481       else if (chars[i] == newLine) {
    00482           m_sourceDisplay->insertItem(new QListBoxPixmap(haveBreakpoint(sourceId, numlines, numlines) ? m_stopIcon : m_emptyIcon,line));
    00483           numlines++;
    00484           line = "";
    00485       } else if (chars[i] == tab) {
    00486           line += tabstr;
    00487       } else
    00488           line += chars[i];
    00489   }
    00490   if (line.length())
    00491       m_sourceDisplay->insertItem(new QListBoxPixmap(haveBreakpoint(sourceId, numlines, numlines) ? m_stopIcon : m_emptyIcon,line));
    00492 }
    00493
    00494 void KJSDebugWin::highLight(int sourceId, int line)
    00495 {
    00496   if (!isVisible())
    00497     show();
    00498
    00499   SourceFragment *source = m_sourceFragments[sourceId];
    00500   if (!source)
    00501     return;
    00502
    00503   SourceFile *sourceFile = source->sourceFile;
    00504   if (m_curSourceFile != source->sourceFile) {
    00505       m_sourceSel->setCurrentItem(source->sourceFile->index);
    00506       setCode(sourceFile->code, sourceId);
    00507   }
    00508   m_curSourceFile = source->sourceFile;
    00509   if (line > 0)
    00510     m_sourceDisplay->setCurrentItem(line+source->baseLine-1);
    00511   else
    00512     m_sourceDisplay->setCurrentItem(-1);
    00513 }
    00514
    00515 void KJSDebugWin::setNextSourceInfo(QString url, int baseLine)
    00516 {
    00517   m_nextSourceUrl = url;
    00518   m_nextSourceBaseLine = baseLine;
    00519 }
    00520
    00521 void KJSDebugWin::setSourceFile(QString url, QString code)
    00522 {
    00523   SourceFile *existing = m_sourceFiles[url];
    00524   int newindex = m_sourceSel->count();
    00525   if (existing) {
    00526       newindex = existing->index;
    00527       m_sourceSel->removeItem(existing->index);
    00528       existing->deref();
    00529   }
    00530   SourceFile *newSF = new SourceFile(url,code,newindex);
    00531   m_sourceFiles[url] = newSF;
    00532   m_sourceSelFiles[newindex] = newSF;
    00533   m_sourceSel->insertItem(url,newindex);
    00534 }
    00535
    00536 void KJSDebugWin::appendSourceFile(QString url, QString code)
    00537 {
    00538   SourceFile *existing = m_sourceFiles[url];
    00539   if (!existing) {
    00540     setSourceFile(url,code);
    00541     return;
    00542   }
    00543   existing->code.append(code);
    00544 }
    00545
    00546 void KJSDebugWin::enterSession()
    00547 {
    00548   // This "enters" a new debugging session, i.e. enables usage of the debugging window
    00549   // It re-enters the qt event loop here, allowing execution of other parts of the
    00550   // program to continue while the script is stopped. We have to be a bit careful here,
    00551   // i.e. make sure the user can't quite the app, and not executing more js code
    00552   assert(!m_inSession);
    00553   m_fakeModal.enable(this);
    00554   m_inSession = true;
    00555   m_mode = Continue;
    00556
    00557   m_nextButton->setEnabled(true);
    00558   m_stepButton->setEnabled(true);
    00559   m_continueButton->setEnabled(true);
    00560   m_stopButton->setEnabled(true);
    00561   m_evalButton->setEnabled(true);
    00562   m_breakButton->setEnabled(false);
    00563   m_breakpointButton->setEnabled(true);
    00564   updateFrameList();
    00565
    00566   qApp->enter_loop(); // won't return until leaveSession() is called
    00567   assert(!m_inSession);
    00568 }
    00569
    00570 void KJSDebugWin::leaveSession()
    00571 {
    00572   // Disables debugging for this window and returns to execute the rest of the script
    00573   // (or aborts execution, if the user pressed stop). When this returns, the program
    00574   // will exit the qt event loop, i.e. return to whatever processing was being done
    00575   // before the debugger was stopped.
    00576   assert(m_inSession);
    00577   m_nextButton->setEnabled(false);
    00578   m_stepButton->setEnabled(false);
    00579   m_continueButton->setEnabled(false);
    00580   m_stopButton->setEnabled(false);
    00581   m_evalButton->setEnabled(false);
    00582   m_breakButton->setEnabled(true);
    00583   m_breakpointButton->setEnabled(false);
    00584   m_inSession = false;
    00585   qApp->exit_loop();
    00586   m_fakeModal.disable();
    00587 }
    00588
    00589 void KJSDebugWin::updateFrameList()
    00590 {
    00591   uint frameno;
    00592   disconnect(m_frameList,SIGNAL(highlighted(int)),this,SLOT(showFrame(int)));
    00593   m_frameList->clear();
    00594   for (frameno = 0; frameno < m_frames.count(); frameno++) {
    00595     m_frameList->insertItem(m_frames.at(frameno)->toString(),frameno);
    00596   }
    00597   m_frameList->setSelected(m_frameList->count()-1, true);
    00598   highLight(m_frames.last()->sourceId,m_frames.last()->lineno);
    00599   connect(m_frameList,SIGNAL(highlighted(int)),this,SLOT(showFrame(int)));
    00600 }
    00601
    00602 bool KJSDebugWin::setBreakpoint(int sourceId, int line)
    00603 {
    00604   if (haveBreakpoint(sourceId,line,line))
    00605     return false;
    00606
    00607   SourceBreakpoints *sbp = m_sourceBreakpoints;
    00608   while(sbp && sbp->sourceId != sourceId)
    00609     sbp = sbp->next;
    00610   if (!sbp) {
    00611     sbp = new SourceBreakpoints;
    00612     sbp->sourceId = sourceId;
    00613     sbp->breakpoints = 0;
    00614     sbp->next = m_sourceBreakpoints;
    00615     m_sourceBreakpoints = sbp;
    00616   }
    00617
    00618   Breakpoint *newbp = new Breakpoint;
    00619   newbp->lineno = line;
    00620   newbp->next = sbp->breakpoints;
    00621   sbp->breakpoints = newbp;
    00622
    00623   return true;
    00624 }
    00625
    00626 bool KJSDebugWin::deleteBreakpoint(int sourceId, int line)
    00627 {
    00628   for (SourceBreakpoints *sbp = m_sourceBreakpoints; sbp; sbp = sbp->next) {
    00629     if (sbp->sourceId == sourceId) {
    00630       // found breakpoints for this sourceId
    00631       Breakpoint *bp = sbp->breakpoints;
    00632       if (bp && bp->lineno == line) {
    00633         // was the first breakpoint
    00634         Breakpoint *next = bp->next;
    00635         delete bp;
    00636         sbp->breakpoints = next;
    00637         return true;
    00638       }
    00639
    00640       while (bp->next && bp->next->lineno != line)
    00641         bp = bp->next;
    00642       if (bp->next && bp->next->lineno == line) {
    00643         // found at subsequent breakpoint
    00644         Breakpoint *next = bp->next->next;
    00645         delete bp->next;
    00646         bp->next = next;
    00647         return true;
    00648       }
    00649       return false;
    00650     }
    00651   }
    00652   // no breakpoints at all for this sourceId
    00653   return false;
    00654 }
    00655
    00656 void KJSDebugWin::clearAllBreakpoints(int sourceId)
    00657 {
    00658   SourceBreakpoints *nextsbp = 0;
    00659   for (SourceBreakpoints *sbp = m_sourceBreakpoints; sbp; sbp = nextsbp) {
    00660     nextsbp = sbp->next;
    00661     if (sourceId == -1 || sbp->sourceId == sourceId) {
    00662       Breakpoint *nextbp;
    00663       for (Breakpoint *bp = sbp->breakpoints; bp; bp = bp->next) {
    00664         nextbp = bp->next;
    00665         delete bp;
    00666       }
    00667       delete sbp;
    00668     }
    00669   }
    00670 }
    00671
    00672 int KJSDebugWin::breakpointLine(int sourceId, int line0, int line1)
    00673 {
    00674   for (SourceBreakpoints *sbp = m_sourceBreakpoints; sbp; sbp = sbp->next) {
    00675     if (sbp->sourceId == sourceId) {
    00676       // found breakpoints for this sourceId
    00677       for (Breakpoint *bp = sbp->breakpoints; bp; bp = bp->next) {
    00678         if (bp->lineno >= 0 && bp->lineno >= line0 && bp->lineno <= line1)
    00679           return bp->lineno;
    00680       }
    00681       return -1;
    00682     }
    00683   }
    00684   // no breakpoints at all for this sourceId
    00685   return -1;
    00686 }
    00687
    00688 bool KJSDebugWin::haveBreakpoint(int sourceId, int line0, int line1)
    00689 {
    00690   return (breakpointLine(sourceId,line0,line1) != -1);
    00691 }
    00692
    00693 #include "kjs_debugwin.moc"
    00694
    00695 #endif // KJS_DEBUGGER

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:34:13 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001