textdocument.cpp

00001 /***************************************************************************
00002  *   Copyright (C) 2005 by David Saxton                                    *
00003  *   david@bluehaze.org                                                    *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  ***************************************************************************/
00010 
00011 #include "asmformatter.h"
00012 #include "asminfo.h"
00013 #include "asmparser.h"
00014 #include "debugmanager.h"
00015 #include "docmanager.h"
00016 #include "documentiface.h"
00017 #include "filemetainfo.h"
00018 #include "gpsimprocessor.h"
00019 #include "ktechlab.h"
00020 #include "language.h"
00021 #include "languagemanager.h"
00022 #include "microselectwidget.h"
00023 #include "programmerdlg.h"
00024 #include "symbolviewer.h"
00025 #include "textdocument.h"
00026 #include "textview.h"
00027 
00028 // #include <kate/katedocument.h>
00029 
00030 #include <kdebug.h>
00031 #include <klibloader.h>
00032 #include <klocale.h>
00033 #include <kmessagebox.h>
00034 #include <ktempfile.h>
00035 
00036 
00037 TextDocument *TextDocument::constructTextDocument( const QString& caption, KTechlab *parent, const char *name )
00038 {
00039         TextDocument *textDocument = new TextDocument( caption, parent, name);
00040         if( textDocument->m_constructorSuccessful )
00041                 return textDocument;
00042         delete textDocument;
00043         return 0;
00044 }
00045 
00046 
00047 TextDocument::TextDocument( const QString &caption, KTechlab *ktechlab, const char *name )
00048         : Document( caption, ktechlab, name ),
00049           m_doc(0)
00050 {
00051         m_constructorSuccessful = false;
00052         
00053 #ifndef NO_GPSIM
00054         m_bOwnDebugger = false;
00055         b_lockSyncBreakpoints = false;
00056         m_lastDebugLineAt = -1;
00057         m_pDebugger = 0;
00058 #endif
00059 
00060         m_pLastTextOutputTarget = 0;
00061         m_guessedCodeType = TextDocument::ct_unknown;
00062         m_type = Document::dt_text;
00063         m_bookmarkActions.setAutoDelete(true);
00064         m_pDocumentIface = new TextDocumentIface(this);
00065         
00066         KLibFactory *factory = KLibLoader::self()->factory("libkatepart");
00067         if(!factory) {
00068                 KMessageBox::sorry( ktechlab, i18n("Libkatepart not available for constructing editor") );
00069                 return;
00070         }
00071         m_doc = (Kate::Document*)(KTextEditor::Document *)factory->create( 0, "kate", "KTextEditor::Document");
00072         
00073         guessScheme();
00074         
00075         connect( m_doc, SIGNAL(undoChanged()),          this, SIGNAL(undoRedoStateChanged()) );
00076         connect( m_doc, SIGNAL(undoChanged()),          this, SLOT(slotSyncModifiedStates()) );
00077         connect( m_doc, SIGNAL(textChanged()),          this, SLOT(slotSyncModifiedStates()) );
00078         connect( m_doc, SIGNAL(marksChanged()),         this, SLOT(slotUpdateMarksInfo()) );
00079         connect( m_doc, SIGNAL(selectionChanged()),     this, SLOT(slotSelectionmChanged()) );
00080         
00081         m_doc->setDescription((KTextEditor::MarkInterface::MarkTypes)Breakpoint, i18n("Breakpoint"));
00082         m_doc->setPixmap((KTextEditor::MarkInterface::MarkTypes)Breakpoint, *inactiveBreakpointPixmap());
00083         m_doc->setPixmap((KTextEditor::MarkInterface::MarkTypes)ActiveBreakpoint, *activeBreakpointPixmap());
00084         m_doc->setPixmap((KTextEditor::MarkInterface::MarkTypes)ReachedBreakpoint, *reachedBreakpointPixmap());
00085         m_doc->setPixmap((KTextEditor::MarkInterface::MarkTypes)DisabledBreakpoint, *disabledBreakpointPixmap());
00086         m_doc->setPixmap((KTextEditor::MarkInterface::MarkTypes)ExecutionPoint, *executionPointPixmap());
00087         m_doc->setMarksUserChangable( Bookmark | Breakpoint );
00088 
00089         m_constructorSuccessful = true;
00090 }
00091 
00092 
00093 TextDocument::~TextDocument()
00094 {
00095         if(!m_constructorSuccessful) return;
00096 
00097         debugStop();
00098 
00099         ViewList::iterator end = m_viewList.end();
00100         for(ViewList::iterator it = m_viewList.begin(); it != end; ++it) {
00101                 if(TextView * tv = dynamic_cast<TextView*>( (View*)*it)) {
00102                         Kate::View * kv = tv->kateView();
00103                         p_ktechlab->factory()->removeClient( kv );
00104                 }
00105         }
00106         
00107         delete m_doc;
00108         delete m_pDocumentIface;
00109 }
00110 
00111 bool TextDocument::fileClose()
00112 {
00113         const QString path = url().prettyURL();
00114         if ( !path.isEmpty() )
00115                 fileMetaInfo()->grabMetaInfo( path, this );
00116         
00117         return Document::fileClose();
00118 }
00119 
00120 TextView* TextDocument::textView() const
00121 {
00122         return static_cast<TextView*>(activeView());
00123 }
00124 
00125 View * TextDocument::createView( ViewContainer *viewContainer, uint viewAreaId, const char *name )
00126 {
00127         TextView * textView = new TextView( this, viewContainer, viewAreaId, name );
00128         
00129         fileMetaInfo()->initializeFromMetaInfo( url().prettyURL(), textView );
00130         
00131         handleNewView(textView);
00132         return textView;
00133 }
00134 
00135 Kate::View* TextDocument::createKateView( QWidget *parent, const char *name )
00136 {
00137         return static_cast<Kate::View*>((m_doc->createView( parent, name ))->qt_cast("Kate::View"));
00138 }
00139 
00140 
00141 void TextDocument::cut()
00142 {
00143         if (textView()) textView()->cut();
00144 }
00145 
00146 void TextDocument::copy()
00147 {
00148         if (textView()) textView()->copy();
00149 }
00150 
00151 void TextDocument::paste()
00152 {
00153         if (textView()) textView()->paste();
00154 }
00155 
00156 void TextDocument::setText( const QString & text, bool asInitial )
00157 {
00158         if(asInitial) {
00159                 disconnect( m_doc, SIGNAL(undoChanged()), this, SIGNAL(undoRedoStateChanged()) );
00160                 disconnect( m_doc, SIGNAL(undoChanged()), this, SLOT(slotSyncModifiedStates()) );
00161                 disconnect( m_doc, SIGNAL(textChanged()), this, SLOT(slotSyncModifiedStates()) );
00162         }
00163 
00164         const ViewList::iterator end = m_viewList.end();
00165         for ( ViewList::iterator it = m_viewList.begin(); it != end; ++it )
00166                 (static_cast<TextView*>((View*)*it))->saveCursorPosition();
00167 
00168         m_doc->setText(text);
00169         
00170         for ( ViewList::iterator it = m_viewList.begin(); it != end; ++it )
00171                 (static_cast<TextView*>((View*)*it))->restoreCursorPosition();
00172 
00173         if ( asInitial ) {
00174                 m_doc->clearUndo();
00175                 m_doc->clearRedo();
00176                 setModified(false);
00177         
00178                 connect( m_doc, SIGNAL(undoChanged()), this, SIGNAL(undoRedoStateChanged()) );
00179                 connect( m_doc, SIGNAL(undoChanged()), this, SLOT(slotSyncModifiedStates()) );
00180                 connect( m_doc, SIGNAL(textChanged()), this, SLOT(slotSyncModifiedStates()) );
00181         }
00182 }
00183 
00184 void TextDocument::undo()
00185 {
00186         m_doc->undo();
00187         slotSyncModifiedStates();
00188 }
00189 
00190 void TextDocument::redo()
00191 {
00192         m_doc->redo();
00193         slotSyncModifiedStates();
00194 }
00195 
00196 void TextDocument::slotSyncModifiedStates()
00197 {
00198         setModified( m_doc->isModified() );
00199 }
00200 void TextDocument::setModified( bool modified )
00201 {
00202         if ( (modified == b_modified) && (modified == isModified()) ) {
00203                 return;
00204         }
00205         m_doc->setModified(modified);
00206         b_modified = modified;
00207         
00208         emit modifiedStateChanged();
00209 }
00210 
00211 void TextDocument::guessScheme( bool allowDisable )
00212 {
00213         // And specific file actions depending on the current type of file
00214         QString fileName = url().fileName();
00215         QString extension = fileName.right( fileName.length() - fileName.findRev('.') - 1 );
00216         
00217         if ( extension == "asm" || extension == "src" || extension == "inc" )
00218                 slotInitLanguage(ct_asm);
00219         else if ( extension == "hex" )
00220                 slotInitLanguage(ct_hex);
00221         else if ( extension == "basic" || extension == "microbe" )
00222                 slotInitLanguage(ct_microbe);
00223         else if ( extension == "c" )
00224                 slotInitLanguage(ct_c);
00225         else if ( m_guessedCodeType != TextDocument::ct_unknown )
00226                 slotInitLanguage(m_guessedCodeType);
00227         else if ( allowDisable && activeView() )
00228                 textView()->disableActions();
00229 }
00230 
00231 void TextDocument::slotInitLanguage( CodeType type )
00232 {
00233         QString hlName;
00234         
00235         switch (type)
00236         {
00237                 case ct_asm:
00238                         hlName = "PicAsm";
00239                         break;
00240                         
00241                 case ct_c:
00242                         hlName = "C";
00243                         break;
00244                         
00245                 case ct_hex:
00246                         break;
00247                         
00248                 case ct_microbe:
00249                         hlName = "Microbe";
00250                         break;
00251                         
00252                 case ct_unknown:
00253                         break;
00254         }
00255         
00256         if ( !hlName.isEmpty() ) {
00257                 int i = 0;
00258                 int hlModeCount = m_doc->hlModeCount();
00259                 while ( i<hlModeCount && m_doc->hlModeName(i) != hlName )
00260                         i++;
00261                 
00262                 m_doc->setHlMode(i);
00263         }
00264         
00265         m_guessedCodeType = type;
00266         
00267         ViewList::iterator end = m_viewList.end();
00268         for ( ViewList::iterator it = m_viewList.begin(); it != end; ++it )
00269         {
00270                 if ( TextView * tv = dynamic_cast<TextView*>( (View*)*it ) )
00271                         tv->initCodeActions();
00272         }
00273 }
00274 
00275 void TextDocument::formatAssembly()
00276 {
00277         AsmFormatter formatter;
00278         QStringList lines = QStringList::split( "\n", m_doc->text(), true );
00279         setText( formatter.tidyAsm(lines), false );
00280         setModified(true);
00281 }
00282 
00283 void TextDocument::fileSave( const KURL& url )
00284 {
00285         if ( m_doc->url().path() != url.path() )
00286         {
00287                 kdError() << k_funcinfo << "Error: Kate::View url and passed url do not match; cannot save." << endl;
00288                 return;
00289         }
00290         
00291         if ( activeView() && (textView()->save() == Kate::View::SAVE_OK ) )
00292                 saveDone();
00293 }
00294 
00295 void TextDocument::fileSaveAs()
00296 {
00297         if (  activeView() && (textView()->saveAs() == Kate::View::SAVE_OK) )
00298                 saveDone();
00299         
00300         // Our modified state may not have changed, but we emit this to force the
00301         // main window to update our caption.
00302         emit modifiedStateChanged();
00303 }
00304 
00305 void TextDocument::saveDone()
00306 {
00307         setURL( m_doc->url() );
00308         guessScheme(false);
00309         setModified(false);
00310         emit modifiedStateChanged();
00311 }
00312 
00313 bool TextDocument::openURL( const KURL& url )
00314 {
00315         m_doc->openURL(url);
00316         setURL(url);
00317         
00318         fileMetaInfo()->initializeFromMetaInfo( url.prettyURL(), this );
00319         guessScheme();
00320 
00321 #ifndef NO_GPSIM
00322         DebugManager::self()->urlOpened( this );
00323 #endif
00324         
00325         return true;
00326 }
00327 
00328 void TextDocument::setLastTextOutputTarget( TextDocument * target )
00329 {
00330         m_pLastTextOutputTarget = target;
00331 }
00332 
00333 QString TextDocument::outputFilePath( const QString &ext )
00334 {
00335         QString filePath = url().path();
00336         if(filePath.isEmpty()) {
00337                 KTempFile f( QString::null, ext );
00338                 (*f.textStream()) <<  m_doc->text();
00339                 f.close();
00340                 DocManager::self()->associateDocument( f.name(), this );
00341                 return f.name();
00342         }
00343 
00344         if(isModified()) fileSave();
00345 
00346         return filePath;
00347 }
00348 
00349 
00350 void TextDocument::slotConvertTo( int target )
00351 {
00352         switch ( (ConvertToTarget)target )
00353         {
00354                 case TextDocument::MicrobeOutput:
00355                         break;
00356                 case TextDocument::AssemblyOutput:
00357                         convertToAssembly();
00358                         break;
00359                 case TextDocument::HexOutput:
00360                         convertToHex();
00361                         break;
00362                 case TextDocument::PICOutput:
00363                         convertToPIC();
00364                         break;
00365         }
00366 }
00367 
00368 void TextDocument::convertToAssembly()
00369 {
00370         QString filePath;
00371         bool showPICSelect = false;
00372         ProcessOptions::ProcessPath::MediaType toType;
00373 
00374         if ( m_guessedCodeType == TextDocument::ct_microbe ) {
00375                 toType = ProcessOptions::ProcessPath::AssemblyAbsolute;
00376                 filePath = outputFilePath(".microbe");
00377         } else if ( m_guessedCodeType == TextDocument::ct_hex ) {
00378                 toType = ProcessOptions::ProcessPath::Disassembly;
00379                 filePath = outputFilePath(".hex");
00380         } else if ( m_guessedCodeType == TextDocument::ct_c ) {
00381                 toType = ProcessOptions::ProcessPath::AssemblyRelocatable;
00382                 filePath = outputFilePath(".c");
00383                 showPICSelect = true;
00384         } else {
00385                 kdError() << "Could not get file type for converting to assembly!"<<endl;
00386                 return;
00387         }
00388         
00389         OutputMethodDlg dlg( i18n("Assembly Code Output"), url(), showPICSelect, p_ktechlab );
00390         
00391         if ( m_guessedCodeType == TextDocument::ct_c )
00392                 dlg.microSelect()->setAllowedAsmSet( AsmInfo::PIC14 | AsmInfo::PIC16 );
00393         
00394         dlg.setOutputExtension(".asm");
00395         dlg.setFilter("*.asm *.src *.inc|Assembly Code (*.asm, *.src, *.inc)\n*|All Files");
00396         dlg.exec();
00397         if (!dlg.isAccepted()) return;
00398         
00399         ProcessOptions o( dlg.info() );
00400         o.setTextOutputTarget( m_pLastTextOutputTarget, this, SLOT(setLastTextOutputTarget( TextDocument* )) );
00401         o.setInputFiles(filePath);
00402         o.setProcessPath( ProcessOptions::ProcessPath::path( ProcessOptions::guessMediaType(filePath), toType ) );
00403         LanguageManager::self()->compile(o);
00404 }
00405 
00406 
00407 void TextDocument::convertToHex()
00408 {
00409         QString filePath;
00410         bool showPICSelect = false;
00411 
00412         if ( m_guessedCodeType == TextDocument::ct_microbe )
00413                 filePath = outputFilePath(".microbe");
00414         else if ( m_guessedCodeType == TextDocument::ct_asm )
00415                 filePath = outputFilePath(".asm");
00416         else if ( m_guessedCodeType == TextDocument::ct_c ) {
00417                 filePath = outputFilePath(".c");
00418                 showPICSelect = true;
00419         } else {
00420                 kdError() << "Could not get file type for converting to hex!"<<endl;
00421                 return;
00422         }
00423         
00424         OutputMethodDlg dlg( i18n("Hex Code Output"), url(), showPICSelect, p_ktechlab );
00425         dlg.setOutputExtension(".hex");
00426         dlg.setFilter("*.hex|Hex (*.hex)\n*|All Files");
00427         
00428         if ( m_guessedCodeType == TextDocument::ct_c )
00429                 dlg.microSelect()->setAllowedAsmSet( AsmInfo::PIC14 | AsmInfo::PIC16 );
00430         
00431         dlg.exec();
00432         if (!dlg.isAccepted())
00433                 return;
00434         
00435         ProcessOptions o( dlg.info() );
00436         o.setTextOutputTarget( m_pLastTextOutputTarget, this, SLOT(setLastTextOutputTarget( TextDocument* )) );
00437         o.setInputFiles(filePath);
00438         o.setProcessPath( ProcessOptions::ProcessPath::path( ProcessOptions::guessMediaType(filePath), ProcessOptions::ProcessPath::Program ) );
00439         LanguageManager::self()->compile(o);
00440 }
00441 
00442 void TextDocument::convertToPIC()
00443 {
00444         QString filePath;
00445         
00446         QString picID;
00447         
00448         switch ( m_guessedCodeType )
00449         {
00450                 case ct_microbe:
00451                         filePath = outputFilePath(".microbe");
00452                         break;
00453                         
00454                 case ct_asm:
00455                 {
00456                         filePath = outputFilePath(".asm");
00457                         AsmParser p( filePath );
00458                         p.parse();
00459                         picID = p.picID();
00460                         break;
00461                 }
00462                         
00463                 case ct_c:
00464                         filePath = outputFilePath(".c");
00465                         break;
00466         
00467                 case ct_hex:
00468                         filePath = outputFilePath(".hex");
00469                         break;
00470                         
00471                 case ct_unknown:
00472                         kdError() << "Could not get file type for converting to hex!"<<endl;
00473                         return;
00474         }
00475         
00476         ProgrammerDlg * dlg = new ProgrammerDlg( picID, (QWidget*)p_ktechlab, "Programmer Dlg" );
00477         
00478         if ( m_guessedCodeType == TextDocument::ct_c )
00479                 dlg->microSelect()->setAllowedAsmSet( AsmInfo::PIC14 | AsmInfo::PIC16 );        
00480 
00481         dlg->exec();
00482         if ( !dlg->isAccepted() ) {
00483                 dlg->deleteLater();
00484                 return;
00485         }
00486         
00487         ProcessOptions o;
00488         dlg->initOptions( & o );
00489         o.setInputFiles( filePath );
00490         o.setProcessPath( ProcessOptions::ProcessPath::path( ProcessOptions::guessMediaType(filePath), ProcessOptions::ProcessPath::Pic ) );
00491         LanguageManager::self()->compile( o );
00492         
00493         dlg->deleteLater();
00494 }
00495 
00496 void TextDocument::print()
00497 {
00498         KTextEditor::printInterface(m_doc)->print ();
00499 }
00500 
00501 void TextDocument::slotSelectionmChanged()
00502 {
00503         p_ktechlab->action( "edit_cut" )->setEnabled( m_doc->hasSelection () );
00504         p_ktechlab->action( "edit_copy" )->setEnabled( m_doc->hasSelection () );
00505 }
00506 
00507 IntList TextDocument::bookmarkList() const
00508 {
00509         IntList bookmarkList;
00510         
00511         typedef QPtrList<KTextEditor::Mark> MarkList;
00512         MarkList markList = m_doc->marks();
00513         
00514         // Find out what marks need adding to our internal lists
00515         for ( KTextEditor::Mark * mark = markList.first(); mark; mark = markList.next() ) {
00516                 if ( mark->type & Bookmark )
00517                         bookmarkList += mark->line;
00518         }
00519         return bookmarkList;
00520 }
00521 
00522 void TextDocument::slotUpdateMarksInfo()
00523 {
00524         if ( activeView() )
00525                 textView()->slotUpdateMarksInfo();
00526 
00527 #ifndef NO_GPSIM
00528         syncBreakpoints();
00529 #endif
00530         
00531         // Update our list of bookmarks in the menu
00532         p_ktechlab->unplugActionList("bookmark_actionlist");
00533         m_bookmarkActions.clear();
00534         
00535         QPtrList<KTextEditor::Mark> markList = m_doc->marks();
00536         
00537         // Find out what marks need adding to our internal lists
00538         for ( KTextEditor::Mark * mark = markList.first(); mark; mark = markList.next() ) {
00539                 if ( mark->type & Bookmark ) {
00540                         KAction * a = new KAction( i18n("%1 - %2").arg( QString::number( mark->line+1 ) ).arg( m_doc->textLine(mark->line) ),
00541                                                                            0, this, SLOT(slotBookmarkRequested()), this,
00542                                                                            QString("bookmark_%1").arg(QString::number(mark->line).ascii()) );
00543                         m_bookmarkActions.append(a);
00544                 }
00545         }
00546 
00547         p_ktechlab->plugActionList( "bookmark_actionlist", m_bookmarkActions );
00548 }
00549 
00550 void TextDocument::slotBookmarkRequested()
00551 {
00552         const QObject * s = sender();
00553         if (!s) return;
00554 
00555         QString name = s->name();
00556         if(!name.startsWith("bookmark_")) return;
00557 
00558         name.remove("bookmark_");
00559         int line = -1;
00560         bool ok;
00561         line = name.toInt(&ok);
00562         if ( ok && line >= 0 && activeView() )
00563                 (static_cast<TextView*>(activeView()))->gotoLine(line);
00564 }
00565 
00566 void TextDocument::setBookmarks( const IntList &lines )
00567 {
00568         clearBookmarks();
00569         const IntList::const_iterator end = lines.end();
00570         for ( IntList::const_iterator it = lines.begin(); it != end; ++it )
00571                 setBookmark( *it, true );
00572 }
00573 
00574 void TextDocument::clearBookmarks()
00575 {
00576         QPtrList<KTextEditor::Mark> markList = m_doc->marks();
00577         
00578         // Find out what marks need adding to our internal lists
00579         for ( KTextEditor::Mark * mark = markList.first(); mark; mark = markList.next() ) {
00580                 if ( mark->type & Bookmark )
00581                         m_doc->removeMark( mark->line, Bookmark );
00582         }
00583 
00584         slotUpdateMarksInfo();
00585 }
00586 
00587 void TextDocument::setBookmark( uint line, bool isBookmark )
00588 {
00589         if (isBookmark)
00590                 m_doc->addMark( line, Bookmark );
00591         else m_doc->removeMark( line, Bookmark );
00592 }
00593 
00594 void TextDocument::setBreakpoints( const IntList &lines )
00595 {
00596 #ifndef NO_GPSIM
00597         clearBreakpoints();
00598         const IntList::const_iterator end = lines.end();
00599         for ( IntList::const_iterator it = lines.begin(); it != end; ++it )
00600                 setBreakpoint( *it, true );
00601 #endif // !NO_GPSIM
00602 }
00603 
00604 IntList TextDocument::breakpointList() const
00605 {
00606         IntList breakpointList;
00607 #ifndef NO_GPSIM
00608         typedef QPtrList<KTextEditor::Mark> MarkList;
00609         MarkList markList = m_doc->marks();
00610 
00611         // Find out what marks need adding to our internal lists
00612         for ( KTextEditor::Mark * mark = markList.first(); mark; mark = markList.next() ) {
00613                 if ( mark->type & Breakpoint )
00614                         breakpointList += mark->line;
00615         }
00616 #endif // !NO_GPSIM
00617 
00618         return breakpointList;
00619 }
00620 
00621 
00622 void TextDocument::setBreakpoint( uint line, bool isBreakpoint )
00623 {
00624 #ifndef NO_GPSIM
00625         if (isBreakpoint) {
00626                 m_doc->addMark( line, Breakpoint );
00627                 if (m_pDebugger)
00628                         m_pDebugger->setBreakpoint( m_debugFile, line, true );
00629         } else {
00630                 m_doc->removeMark( line, Breakpoint );
00631                 if (m_pDebugger)
00632                         m_pDebugger->setBreakpoint( m_debugFile, line, false );
00633         }
00634 #endif // !NO_GPSIM
00635 }
00636 
00637 
00638 void TextDocument::debugRun()
00639 {
00640 #ifndef NO_GPSIM
00641         if (m_pDebugger) {
00642                 m_pDebugger->gpsim()->setRunning(true);
00643                 slotInitDebugActions();
00644                 return;
00645         }
00646         
00647         switch ( guessedCodeType() )
00648         {
00649                 case ct_unknown:
00650                         KMessageBox::sorry( 0, i18n("Unknown code type."), i18n("Cannot debug") );
00651                         return;
00652                         
00653                 case ct_hex:
00654                         KMessageBox::sorry( 0, i18n("Cannot debug hex."), i18n("Cannot debug") );
00655                         return;
00656                         
00657                 case ct_microbe:
00658                         m_bLoadDebuggerAsHLL = true;
00659                         m_debugFile = outputFilePath(".microbe");
00660                         break;
00661                         
00662                 case ct_asm:
00663                         m_bLoadDebuggerAsHLL = false;
00664                         m_debugFile = outputFilePath(".asm");
00665                         break;
00666                         
00667                 case ct_c:
00668                         m_bLoadDebuggerAsHLL = true;
00669                         m_debugFile = outputFilePath(".c");
00670                         break;
00671         }
00672         
00673         m_symbolFile = GpsimProcessor::generateSymbolFile( m_debugFile, this, SLOT(slotCODCreationSucceeded()), SLOT(slotCODCreationFailed()) );
00674 #endif // !NO_GPSIM
00675 }
00676 
00677 void TextDocument::debugInterrupt()
00678 {
00679 #ifndef NO_GPSIM
00680         if (!m_pDebugger) return;
00681 
00682         m_pDebugger->gpsim()->setRunning(false);
00683         slotInitDebugActions();
00684 #endif // !NO_GPSIM
00685 }
00686 
00687 void TextDocument::debugStop()
00688 {
00689 #ifndef NO_GPSIM
00690         if(!m_pDebugger || !m_bOwnDebugger) return;
00691         
00692         m_pDebugger->gpsim()->deleteLater();
00693         m_pDebugger = 0;
00694         slotDebugSetCurrentLine( SourceLine() );
00695         slotInitDebugActions();
00696 #endif // !NO_GPSIM
00697 }
00698 
00699 void TextDocument::debugStep()
00700 {
00701 #ifndef NO_GPSIM
00702         if (!m_pDebugger) return;
00703         
00704         m_pDebugger->stepInto();
00705 #endif // !NO_GPSIM
00706 }
00707 
00708 
00709 void TextDocument::debugStepOver()
00710 {
00711 #ifndef NO_GPSIM
00712         if (!m_pDebugger) return;
00713 
00714         m_pDebugger->stepOver();
00715 #endif // !NO_GPSIM
00716 }
00717 
00718 
00719 void TextDocument::debugStepOut()
00720 {
00721 #ifndef NO_GPSIM
00722         if (!m_pDebugger) return;
00723         
00724         m_pDebugger->stepOut();
00725 #endif // !NO_GPSIM
00726 }
00727 
00728 
00729 void TextDocument::slotDebugSetCurrentLine( const SourceLine & line )
00730 {
00731 #ifndef NO_GPSIM
00732         int textLine = line.line();
00733         
00734         if ( DocManager::self()->findDocument( line.fileName() ) != this )
00735                 textLine = -1;
00736         
00737         m_doc->removeMark( m_lastDebugLineAt, ExecutionPoint );
00738         m_doc->addMark( textLine, ExecutionPoint );
00739         
00740         if ( activeView() )
00741                 textView()->setCursorPosition( textLine, 0 );
00742 
00743         m_lastDebugLineAt = textLine;
00744 #endif // !NO_GPSIM
00745 }
00746 
00747 
00748 void TextDocument::slotInitDebugActions()
00749 {
00750 #ifndef NO_GPSIM
00751         if ( m_pDebugger )
00752         {
00753                 if ( m_pDebugger->gpsim()->isRunning() )
00754                         slotDebugSetCurrentLine( SourceLine() );
00755                 else slotDebugSetCurrentLine( m_pDebugger->currentLine() );
00756         }
00757         
00758         if ( activeView() )
00759                 textView()->slotInitDebugActions();
00760 #endif // !NO_GPSIM
00761 }
00762 
00763 void TextDocument::slotCODCreationSucceeded()
00764 {
00765 #ifndef NO_GPSIM
00766         GpsimProcessor * gpsim = new GpsimProcessor( m_symbolFile, this );
00767         
00768         if (m_bLoadDebuggerAsHLL)
00769                 gpsim->setDebugMode( GpsimDebugger::HLLDebugger );
00770         else gpsim->setDebugMode( GpsimDebugger::AsmDebugger );
00771         
00772         setDebugger( gpsim->currentDebugger(), true );
00773 #endif // !NO_GPSIM
00774 }
00775 
00776 void TextDocument::slotCODCreationFailed()
00777 {
00778 #ifndef NO_GPSIM
00779         m_debugFile = QString::null;
00780         m_symbolFile = QString::null;
00781 #endif // !NO_GPSIM
00782 }
00783 
00784 void TextDocument::slotDebuggerDestroyed()
00785 {
00786 #ifndef NO_GPSIM
00787         slotDebugSetCurrentLine( SourceLine() );
00788         m_pDebugger = 0;
00789         m_debugFile = QString::null;
00790         slotInitDebugActions();
00791 #endif // !NO_GPSIM
00792 }
00793 
00794 #ifndef NO_GPSIM
00795 void TextDocument::clearBreakpoints()
00796 {
00797         QPtrList<KTextEditor::Mark> markList = m_doc->marks();
00798 
00799         // Find out what marks need adding to our internal lists
00800         for(KTextEditor::Mark * mark = markList.first(); mark; mark = markList.next()) {
00801                 if ( mark->type & Bookmark )
00802                         m_doc->removeMark( mark->line, Breakpoint );
00803         }
00804 
00805         slotUpdateMarksInfo();
00806 }
00807 
00808 void TextDocument::syncBreakpoints()
00809 {
00810         if (b_lockSyncBreakpoints) return;
00811 
00812         // We don't really care about synching marks if we aren't debugging / aren't able to take use of the marks
00813         if (!m_pDebugger) return;
00814 
00815         b_lockSyncBreakpoints = true;
00816 
00817         typedef QPtrList<KTextEditor::Mark> MarkList;
00818         MarkList markList = m_doc->marks();
00819         IntList bpList;
00820 
00821         // Find out what marks need adding to our internal lists
00822         for ( KTextEditor::Mark * mark = markList.first(); mark; mark = markList.next() ) {
00823                 const int line = mark->line;
00824                 
00825                 if ( mark->type & Breakpoint )
00826                         bpList.append(line);
00827                 
00828                 if ( mark->type == ExecutionPoint )
00829                         m_lastDebugLineAt = line;
00830         }
00831 
00832         m_pDebugger->setBreakpoints( m_debugFile, bpList );
00833         b_lockSyncBreakpoints = false;
00834 }
00835 
00836 bool TextDocument::debuggerIsRunning() const
00837 {
00838         return m_pDebugger;
00839 }
00840 
00841 bool TextDocument::debuggerIsStepping() const
00842 {
00843         return m_pDebugger && !m_pDebugger->gpsim()->isRunning();
00844 }
00845 
00846 void TextDocument::setDebugger(GpsimDebugger *debugger, bool ownDebugger )
00847 {
00848         if(debugger == m_pDebugger) return;
00849         
00850         // If we create a gpsim, then we may get called by DebugManager, which will
00851         // try to claim we don't own it. So if we have a symbol file waiting, thne
00852         // wait until we are called from its successful creation
00853         if ( !m_symbolFile.isEmpty() && !ownDebugger ) return;
00854         
00855         // Reset it for use next time
00856         m_symbolFile = QString::null;
00857         
00858         if(m_bOwnDebugger) delete m_pDebugger;
00859         m_pDebugger = debugger;
00860         m_bOwnDebugger = ownDebugger;
00861 
00862         if(!m_pDebugger) return;
00863 
00864         if(m_debugFile.isEmpty()) m_debugFile = url().path();
00865         
00866         connect( m_pDebugger,                   SIGNAL(destroyed()),                                            this, SLOT(slotDebuggerDestroyed()) );
00867         connect( m_pDebugger->gpsim(),  SIGNAL(runningStatusChanged(bool )),            this, SLOT(slotInitDebugActions()) );
00868         connect( m_pDebugger,                   SIGNAL(lineReached(const SourceLine &)),        this, SLOT(slotDebugSetCurrentLine(const SourceLine &)) );
00869         m_pDebugger->setBreakpoints( m_debugFile, breakpointList() );
00870         
00871         slotInitDebugActions();
00872         if ( !m_pDebugger->gpsim()->isRunning() )
00873                 slotDebugSetCurrentLine( m_pDebugger->currentLine() );
00874         
00875         if ( this == dynamic_cast<TextDocument*>(DocManager::self()->getFocusedDocument()) )
00876                 SymbolViewer::self()->setContext( m_pDebugger->gpsim() );
00877 }
00878 #endif // !NO_GPSIM
00879 
00880 
00881 const QPixmap* TextDocument::inactiveBreakpointPixmap()
00882 {
00883         const char*breakpoint_gr_xpm[]={
00884                 "11 16 6 1",
00885                 "c c #c6c6c6",
00886                 "d c #2c2c2c",
00887                 "# c #000000",
00888                 ". c None",
00889                 "a c #ffffff",
00890                 "b c #555555",
00891                 "...........",
00892                 "...........",
00893                 "...#####...",
00894                 "..#aaaaa#..",
00895                 ".#abbbbbb#.",
00896                 "#abbbbbbbb#",
00897                 "#abcacacbd#",
00898                 "#abbbbbbbb#",
00899                 "#abcacacbd#",
00900                 "#abbbbbbbb#",
00901                 ".#bbbbbbb#.",
00902                 "..#bdbdb#..",
00903                 "...#####...",
00904                 "...........",
00905                 "...........",
00906                 "..........."};
00907                 static QPixmap pixmap( breakpoint_gr_xpm );
00908                 return &pixmap;
00909 }
00910 
00911 
00912 const QPixmap* TextDocument::activeBreakpointPixmap()
00913 {
00914         const char* breakpoint_xpm[]={
00915                 "11 16 6 1",
00916                 "c c #c6c6c6",
00917                 ". c None",
00918                 "# c #000000",
00919                 "d c #840000",
00920                 "a c #ffffff",
00921                 "b c #ff0000",
00922                 "...........",
00923                 "...........",
00924                 "...#####...",
00925                 "..#aaaaa#..",
00926                 ".#abbbbbb#.",
00927                 "#abbbbbbbb#",
00928                 "#abcacacbd#",
00929                 "#abbbbbbbb#",
00930                 "#abcacacbd#",
00931                 "#abbbbbbbb#",
00932                 ".#bbbbbbb#.",
00933                 "..#bdbdb#..",
00934                 "...#####...",
00935                 "...........",
00936                 "...........",
00937                 "..........."};
00938                 static QPixmap pixmap( breakpoint_xpm );
00939                 return &pixmap;
00940 }
00941 
00942 
00943 
00944 const QPixmap* TextDocument::reachedBreakpointPixmap()
00945 {
00946         const char*breakpoint_bl_xpm[]={
00947                 "11 16 7 1",
00948                 "a c #c0c0ff",
00949                 "# c #000000",
00950                 "c c #0000c0",
00951                 "e c #0000ff",
00952                 "b c #dcdcdc",
00953                 "d c #ffffff",
00954                 ". c None",
00955                 "...........",
00956                 "...........",
00957                 "...#####...",
00958                 "..#ababa#..",
00959                 ".#bcccccc#.",
00960                 "#acccccccc#",
00961                 "#bcadadace#",
00962                 "#acccccccc#",
00963                 "#bcadadace#",
00964                 "#acccccccc#",
00965                 ".#ccccccc#.",
00966                 "..#cecec#..",
00967                 "...#####...",
00968                 "...........",
00969                 "...........",
00970                 "..........."};
00971                 static QPixmap pixmap( breakpoint_bl_xpm );
00972                 return &pixmap;
00973 }
00974 
00975 
00976 const QPixmap* TextDocument::disabledBreakpointPixmap()
00977 {
00978         const char*breakpoint_wh_xpm[]={
00979                 "11 16 7 1",
00980                 "a c #c0c0ff",
00981                 "# c #000000",
00982                 "c c #0000c0",
00983                 "e c #0000ff",
00984                 "b c #dcdcdc",
00985                 "d c #ffffff",
00986                 ". c None",
00987                 "...........",
00988                 "...........",
00989                 "...#####...",
00990                 "..#ddddd#..",
00991                 ".#ddddddd#.",
00992                 "#ddddddddd#",
00993                 "#ddddddddd#",
00994                 "#ddddddddd#",
00995                 "#ddddddddd#",
00996                 "#ddddddddd#",
00997                 ".#ddddddd#.",
00998                 "..#ddddd#..",
00999                 "...#####...",
01000                 "...........",
01001                 "...........",
01002                 "..........."};
01003                 static QPixmap pixmap( breakpoint_wh_xpm );
01004                 return &pixmap;
01005 }
01006 
01007 
01008 const QPixmap* TextDocument::executionPointPixmap()
01009 {
01010         const char*exec_xpm[]={
01011                 "11 16 4 1",
01012                 "a c #00ff00",
01013                 "b c #000000",
01014                 ". c None",
01015                 "# c #00c000",
01016                 "...........",
01017                 "...........",
01018                 "...........",
01019                 "#a.........",
01020                 "#aaa.......",
01021                 "#aaaaa.....",
01022                 "#aaaaaaa...",
01023                 "#aaaaaaaaa.",
01024                 "#aaaaaaa#b.",
01025                 "#aaaaa#b...",
01026                 "#aaa#b.....",
01027                 "#a#b.......",
01028                 "#b.........",
01029                 "...........",
01030                 "...........",
01031                 "..........."};
01032                 static QPixmap pixmap( exec_xpm );
01033                 return &pixmap;
01034 }
01035 
01036 #include "textdocument.moc"

Generated on Tue May 8 17:05:32 2007 for KTechLab by  doxygen 1.5.1