#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kdevhtmlpart.h" KDevHTMLPart::KDevHTMLPart() : KHTMLPart(0L, 0L, 0L, "KDevHTMLPart", DefaultGUI ) { setXMLFile(locate("data", "kdevelop/kdevhtml_partui.rc"), true); connect(browserExtension(), TQT_SIGNAL(openURLRequestDelayed(const KURL &,const KParts::URLArgs &)), this, TQT_SLOT(openURLRequest(const KURL &)) ); connect(this, TQT_SIGNAL(started(KIO::Job *)), this, TQT_SLOT(slotStarted(KIO::Job* ))); connect(this, TQT_SIGNAL(completed()), this, TQT_SLOT(slotCompleted())); connect(this, TQT_SIGNAL(canceled(const TQString &)), this, TQT_SLOT(slotCancelled(const TQString &))); KActionCollection * actions = actionCollection();// new KActionCollection( this ); reloadAction = new KAction( i18n( "Reload" ), "reload", 0, this, TQT_SLOT( slotReload() ), actions, "doc_reload" ); reloadAction->setWhatsThis(i18n("Reload

Reloads the current document.")); stopAction = new KAction( i18n( "Stop" ), "stop", 0, this, TQT_SLOT( slotStop() ), actions, "doc_stop" ); stopAction->setWhatsThis(i18n("Stop

Stops the loading of current document.")); duplicateAction = new KAction( i18n( "Duplicate Tab" ), "window_new", 0, this, TQT_SLOT( slotDuplicate() ), actions, "doc_dup" ); duplicateAction->setWhatsThis(i18n("Duplicate window

Opens current document in a new window.")); printAction = KStdAction::print(this, TQT_SLOT(slotPrint()), actions, "print_doc"); copyAction = KStdAction::copy(this, TQT_SLOT(slotCopy()), actions, "copy_doc_selection"); connect( this, TQT_SIGNAL(popupMenu(const TQString &, const TQPoint &)), this, TQT_SLOT(popup(const TQString &, const TQPoint &))); connect(this, TQT_SIGNAL(selectionChanged()), this, TQT_SLOT(slotSelectionChanged())); //BEGIN documentation history stuff m_backAction = new KToolBarPopupAction(i18n("Back"), "back", 0, this, TQT_SLOT(slotBack()), actions, "browser_back"); m_backAction->setEnabled( false ); m_backAction->setToolTip(i18n("Back")); m_backAction->setWhatsThis(i18n("Back

Moves backwards one step in the documentation browsing history.")); connect(m_backAction->popupMenu(), TQT_SIGNAL(aboutToShow()), this, TQT_SLOT(slotBackAboutToShow())); connect(m_backAction->popupMenu(), TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotPopupActivated(int))); m_forwardAction = new KToolBarPopupAction(i18n("Forward"), "forward", 0, this, TQT_SLOT(slotForward()), actions, "browser_forward"); m_forwardAction->setEnabled( false ); m_forwardAction->setToolTip(i18n("Forward")); m_forwardAction->setWhatsThis(i18n("Forward

Moves forward one step in the documentation browsing history.")); connect(m_forwardAction->popupMenu(), TQT_SIGNAL(aboutToShow()), this, TQT_SLOT(slotForwardAboutToShow())); connect(m_forwardAction->popupMenu(), TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotPopupActivated(int))); m_restoring = false; m_Current = m_history.end(); //END documentation history stuff //settings: KConfig *appConfig = KGlobal::config(); appConfig->setGroup("KHTMLPart"); setStandardFont(appConfig->readEntry("StandardFont", settings()->stdFontName())); setFixedFont(appConfig->readEntry("FixedFont", settings()->fixedFontName())); setZoomFactor(appConfig->readEntry("Zoom", "100").toInt()); } void KDevHTMLPart::popup( const TQString & url, const TQPoint & p ) { // KPopupMenu popup( i18n( "Documentation Viewer" ), this->widget() ); KPopupMenu popup(this->widget()); bool needSep = false; int idNewWindow = -2; if (!url.isEmpty() && (m_options & CanOpenInNewWindow)) { idNewWindow = popup.insertItem(SmallIcon("window_new"),i18n("Open in New Tab")); popup.setWhatsThis(idNewWindow, i18n("Open in new window

Opens current link in a new window.")); needSep = true; } if (m_options & CanDuplicate) { duplicateAction->plug(&popup); needSep = true; } if (needSep) popup.insertSeparator(); m_backAction->plug( &popup ); m_forwardAction->plug( &popup ); reloadAction->plug(&popup); // stopAction->plug(&popup); popup.insertSeparator(); copyAction->plug( &popup ); popup.insertSeparator(); printAction->plug(&popup); popup.insertSeparator(); KAction * incFontAction = this->action("incFontSizes"); KAction * decFontAction = this->action("decFontSizes"); if ( incFontAction && decFontAction ) { incFontAction->plug( &popup ); decFontAction->plug( &popup ); popup.insertSeparator(); } KAction *ac = action("setEncoding"); if (ac) ac->plug(&popup); int r = popup.exec(p); if (r == idNewWindow) { KURL kurl; if (!KURL(url).path().startsWith("/")) { kdDebug() << "processing relative url: " << url << endl; if (url.startsWith("#")) { kurl = KURL(KDevHTMLPart::url()); kurl.setRef(url.mid(1)); } else kurl = KURL(KDevHTMLPart::url().upURL().url(true)+url); } else kurl = KURL(url); if (kurl.isValid()) slotOpenInNewWindow(kurl); } } void KDevHTMLPart::setContext(const TQString &context) { m_context = context; } TQString KDevHTMLPart::context() const { return m_context; } // Note: this function is a copy of code in kdecore/kconfigbase.cpp ;) static bool isUtf8(const char *buf) { int i, n; register unsigned char c; bool gotone = false; #define F 0 /* character never appears in text */ #define T 1 /* character appears in plain ASCII text */ #define I 2 /* character appears in ISO-8859 text */ #define X 3 /* character appears in non-ISO extended ASCII (Mac, IBM PC) */ static const unsigned char text_chars[256] = { /* BEL BS HT LF FF CR */ F, F, F, F, F, F, F, T, T, T, T, F, T, T, F, F, /* 0x0X */ /* ESC */ F, F, F, F, F, F, F, F, F, F, F, T, F, F, F, F, /* 0x1X */ T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x2X */ T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x3X */ T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x4X */ T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x5X */ T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x6X */ T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, F, /* 0x7X */ /* NEL */ X, X, X, X, X, T, X, X, X, X, X, X, X, X, X, X, /* 0x8X */ X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, /* 0x9X */ I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xaX */ I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xbX */ I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xcX */ I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xdX */ I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xeX */ I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I /* 0xfX */ }; /* *ulen = 0; */ for (i = 0; (c = buf[i]); i++) { if ((c & 0x80) == 0) { /* 0xxxxxxx is plain ASCII */ /* * Even if the whole file is valid UTF-8 sequences, * still reject it if it uses weird control characters. */ if (text_chars[c] != T) return false; } else if ((c & 0x40) == 0) { /* 10xxxxxx never 1st byte */ return false; } else { /* 11xxxxxx begins UTF-8 */ int following; if ((c & 0x20) == 0) { /* 110xxxxx */ following = 1; } else if ((c & 0x10) == 0) { /* 1110xxxx */ following = 2; } else if ((c & 0x08) == 0) { /* 11110xxx */ following = 3; } else if ((c & 0x04) == 0) { /* 111110xx */ following = 4; } else if ((c & 0x02) == 0) { /* 1111110x */ following = 5; } else return false; for (n = 0; n < following; n++) { i++; if (!(c = buf[i])) goto done; if ((c & 0x80) == 0 || (c & 0x40)) return false; } gotone = true; } } done: return gotone; /* don't claim it's UTF-8 if it's all 7-bit */ } #undef F #undef T #undef I #undef X TQString KDevHTMLPart::resolveEnvVarsInURL(const TQString& url) { // check for environment variables and make necessary translations TQString path = url; int nDollarPos = path.find( '$' ); // Note: the while loop below is a copy of code in kdecore/kconfigbase.cpp ;) while( nDollarPos != -1 && nDollarPos+1 < static_cast(path.length())) { // there is at least one $ if( (path)[nDollarPos+1] == '(' ) { uint nEndPos = nDollarPos+1; // the next character is no $ while ( (nEndPos <= path.length()) && (path[nEndPos]!=')') ) nEndPos++; nEndPos++; TQString cmd = path.mid( nDollarPos+2, nEndPos-nDollarPos-3 ); TQString result; FILE *fs = popen(TQFile::encodeName(cmd).data(), "r"); if (fs) { TQTextStream ts(fs, IO_ReadOnly); result = ts.read().stripWhiteSpace(); pclose(fs); } path.replace( nDollarPos, nEndPos-nDollarPos, result ); } else if( (path)[nDollarPos+1] != '$' ) { uint nEndPos = nDollarPos+1; // the next character is no $ TQString aVarName; if (path[nEndPos]=='{') { while ( (nEndPos <= path.length()) && (path[nEndPos]!='}') ) nEndPos++; nEndPos++; aVarName = path.mid( nDollarPos+2, nEndPos-nDollarPos-3 ); } else { while ( nEndPos <= path.length() && (path[nEndPos].isNumber() || path[nEndPos].isLetter() || path[nEndPos]=='_' ) ) nEndPos++; aVarName = path.mid( nDollarPos+1, nEndPos-nDollarPos-1 ); } const char* pEnv = 0; if (!aVarName.isEmpty()) pEnv = getenv( aVarName.ascii() ); if( pEnv ) { // !!! Sergey A. Sukiyazov !!! // A environment variables may contain values in 8bit // locale cpecified encoding or in UTF8 encoding. if (isUtf8( pEnv )) path.replace( nDollarPos, nEndPos-nDollarPos, TQString::fromUtf8(pEnv) ); else path.replace( nDollarPos, nEndPos-nDollarPos, TQString::fromLocal8Bit(pEnv) ); } else path.remove( nDollarPos, nEndPos-nDollarPos ); } else { // remove one of the dollar signs path.remove( nDollarPos, 1 ); nDollarPos++; } nDollarPos = path.find( '$', nDollarPos ); } return path; } bool KDevHTMLPart::openURL(const KURL &url) { TQString path = resolveEnvVarsInURL(url.url()); KURL newUrl(path); bool retval = KHTMLPart::openURL(newUrl); if ( retval ) { emit fileNameChanged(this); if ( !m_restoring ) { addHistoryEntry(); } } m_backAction->setEnabled( m_Current != m_history.begin() ); m_forwardAction->setEnabled( m_Current != m_history.fromLast() ); return retval; } void KDevHTMLPart::openURLRequest(const KURL &url) { openURL( url ); } void KDevHTMLPart::slotReload( ) { openURL( url() ); } void KDevHTMLPart::slotStop( ) { closeURL(); } void KDevHTMLPart::slotStarted( KIO::Job * ) { stopAction->setEnabled(true); } void KDevHTMLPart::slotCompleted( ) { stopAction->setEnabled(false); } void KDevHTMLPart::slotCancelled( const TQString & /*errMsg*/ ) { stopAction->setEnabled(false); } /*void KDevHTMLPart::slotDuplicate( ) { PartController::getInstance()->showDocument(url(), true); }*/ void KDevHTMLPart::slotPrint( ) { view()->print(); } void KDevHTMLPart::slotBack() { if ( m_Current != m_history.begin() ) { --m_Current; m_restoring = true; openURL( (*m_Current).url ); m_restoring = false; } } void KDevHTMLPart::slotForward() { if ( m_Current != m_history.fromLast() ) { ++m_Current; m_restoring = true; openURL( (*m_Current).url ); m_restoring = false; } } void KDevHTMLPart::slotBackAboutToShow() { KPopupMenu *popup = m_backAction->popupMenu(); popup->clear(); if ( m_Current == m_history.begin() ) return; TQValueList::Iterator it = m_Current; --it; int i = 0; while( i < 10 ) { if ( it == m_history.begin() ) { popup->insertItem( (*it).url.url(), (*it).id ); return; } popup->insertItem( (*it).url.url(), (*it).id ); ++i; --it; } } void KDevHTMLPart::slotForwardAboutToShow() { KPopupMenu *popup = m_forwardAction->popupMenu(); popup->clear(); if ( m_Current == m_history.fromLast() ) return; TQValueList::Iterator it = m_Current; ++it; int i = 0; while( i < 10 ) { if ( it == m_history.fromLast() ) { popup->insertItem( (*it).url.url(), (*it).id ); return; } popup->insertItem( (*it).url.url(), (*it).id ); ++i; ++it; } } void KDevHTMLPart::slotPopupActivated( int id ) { kdDebug(9000) << "id: " << id << endl; TQValueList::Iterator it = m_history.begin(); while( it != m_history.end() ) { kdDebug(9000) << "(*it).id: " << (*it).id << endl; if ( (*it).id == id ) { m_Current = it; m_restoring = true; openURL( (*m_Current).url ); m_restoring = false; return; } ++it; } } void KDevHTMLPart::addHistoryEntry() { TQValueList::Iterator it = m_Current; // if We're not already the last entry, we truncate the list here before adding an entry if ( it != m_history.end() && it != m_history.fromLast() ) { m_history.erase( ++it, m_history.end() ); } DocumentationHistoryEntry newEntry( url() ); // Only save the new entry if it is different from the last if ( newEntry.url != (*m_Current).url ) { m_history.append( newEntry ); m_Current = m_history.fromLast(); } } void KDevHTMLPart::slotCopy( ) { TQString text = selectedText(); text.replace( TQChar( 0xa0 ), ' ' ); QClipboard *cb = TQApplication::clipboard(); disconnect( cb, TQT_SIGNAL( selectionChanged() ), this, TQT_SLOT( slotClearSelection() ) ); cb->setText(text); connect( cb, TQT_SIGNAL( selectionChanged() ), this, TQT_SLOT( slotClearSelection() ) ); } void KDevHTMLPart::slotSelectionChanged( ) { if (selectedText().isEmpty()) copyAction->setEnabled(false); else copyAction->setEnabled(true); } #include "kdevhtmlpart.moc"