-rw-r--r-- | libopie2/opieui/big-screen/osplitter.cpp | 2 | ||||
-rw-r--r-- | library/qpeapplication.cpp | 6 | ||||
-rw-r--r-- | noncore/applets/pcmcia/pcmcia.cpp | 6 | ||||
-rw-r--r-- | noncore/apps/checkbook/mainwindow.cpp | 3 | ||||
-rw-r--r-- | noncore/apps/opie-console/procctl.cpp | 3 | ||||
-rw-r--r-- | noncore/apps/tinykate/libkate/document/katedocument.cpp | 63 | ||||
-rw-r--r-- | noncore/settings/sysinfo/devicesinfo.cpp | 2 | ||||
-rw-r--r-- | noncore/todayplugins/stockticker/libstocks/http.c | 2 |
8 files changed, 48 insertions, 39 deletions
diff --git a/libopie2/opieui/big-screen/osplitter.cpp b/libopie2/opieui/big-screen/osplitter.cpp index 78e919a..5d1e2cf 100644 --- a/libopie2/opieui/big-screen/osplitter.cpp +++ b/libopie2/opieui/big-screen/osplitter.cpp @@ -1,625 +1,625 @@ /* =. This file is part of the OPIE Project .=l. Copyright (c) 2003 hOlgAr <zecke@handhelds.org> .>+-= _;:, .> :=|. This library is free software; you can .> <`_, > . <= redistribute it and/or modify it under :`=1 )Y*s>-.-- : the terms of the GNU Library General Public .="- .-=="i, .._ License as published by the Free Software - . .-<_> .<> Foundation; either version 2 of the License, ._= =} : or (at your option) any later version. .%`+i> _;_. .i_,=:_. -<s. This library is distributed in the hope that + . -:. = it will be useful, but WITHOUT ANY WARRANTY; : .. .:, . . . without even the implied warranty of =_ + =;=|` MERCHANTABILITY or FITNESS FOR A _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU ..}^=.= = ; Library General Public License for more ++= -. .` .: details. : = ...= . :.=- -. .:....=;==+<; You should have received a copy of the GNU -_. . . )=. = Library General Public License along with -- :-=` this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "osplitter.h" /* OPIE */ #include <opie2/otabwidget.h> #include <opie2/odebug.h> /* QT */ #include <qvaluelist.h> #include <qvbox.h> using namespace Opie::Ui; using namespace Opie::Ui::Internal; /** * * This is the constructor of OSplitter * You might want to call setSizeChange to tell * OSplitter to change its layout when a specefic * mark was crossed. OSplitter sets a default value. * * You cann add widget with addWidget to the OSplitter. * OSplitter supports also grouping of Splitters where they * can share one OTabBar in small screen mode. This can be used * for email clients like vies but see the example. * * @param orient The orientation wether to layout horizontal or vertical * @param parent The parent of this widget * @param name The name passed on to QObject * @param fl Additional widgets flags passed to QWidget * * @short single c'tor of the OSplitter */ OSplitter::OSplitter( Orientation orient, QWidget* parent, const char* name, WFlags fl ) : QFrame( parent, name, fl ) { m_orient = orient; m_hbox = 0; m_size_policy = 330; setFontPropagation( AllChildren ); setPalettePropagation( AllChildren ); /* start by default with the tab widget */ m_tabWidget = 0; m_parentTab = 0; changeTab(); } /** * Destructor destructs this object and cleans up. All child * widgets will be deleted * @see addWidget */ OSplitter::~OSplitter() { m_splitter.setAutoDelete( true ); m_splitter.clear(); delete m_hbox; delete m_tabWidget; } /** * Sets the label for the Splitter. This label will be used * if a parent splitter is arranged as TabWidget but * this splitter is in fullscreen mode. Then a tab with OSplitter::label() * and iconName() gets added. * * @param name The name of the Label */ void OSplitter::setLabel( const QString& name ) { m_name = name; } /** * @see setLabel but this is for the icon retrieved by Resource * * @param name The name of the icon in example ( "zoom" ) */ void OSplitter::setIconName( const QString& name ) { m_icon = name; } /** * returns the iconName * @see setIconName */ QString OSplitter::iconName()const { return m_icon; } /** * returns the label set with setLabel * @see setLabel */ QString OSplitter::label()const { return m_name; } /** * This function sets the size change policy of the splitter. * If this size marked is crossed the splitter will relayout. * Note: that depending on the set Orientation it'll either look * at the width or height. * Note: If you want to from side to side view to tabbed view you need * to make sure that the size you supply is not smaller than the minimum * size of your added widgets. Note that if you use widgets like QComboBoxes * you need to teach them to accept smaller sizes as well @see QWidget::setSizePolicy * * @param width_height The mark that will be watched. Interpreted depending on the Orientation of the Splitter. * @return void */ void OSplitter::setSizeChange( int width_height ) { m_size_policy = width_height; QSize sz(width(), height() ); QResizeEvent ev(sz, sz ); resizeEvent(&ev); } /** * This functions allows to add another OSplitter and to share * the OTabBar in small screen mode. The ownerships gets transfered. * OSplitters are always added after normal widget items */ void OSplitter::addWidget( OSplitter* split ) { m_splitter.append( split ); /* * set tab widget */ if (m_tabWidget ) setTabWidget( m_parentTab ); else { OSplitterContainer con; con.widget =split; addToBox( con ); } } /* * If in a tab it should be removed * and if in a hbox the reparent kills it too */ /** * This removes the splitter again. You currently need to call this * before you delete or otherwise you can get mem corruption * or other weird behaviour. * Owner ship gets transfered back to you it's current parent * is 0 */ void OSplitter::removeWidget( OSplitter* split) { split->setTabWidget( 0 ); split->reparent( 0, 0, QPoint(0, 0) ); } /** * Adds a widget to the Splitter. The widgets gets inserted * at the end of either the Box or TabWidget. * Ownership gets transfered and the widgets gets reparented. * Note: icon and label is only available on small screensizes * if size is smaller than the mark * Warning: No null checking of the widget is done. Only on debug * a message will be outputtet * * @param wid The widget which will be added * @param icon The icon of the possible Tab * @param label The label of the possible Tab */ void OSplitter::addWidget( QWidget* wid, const QString& icon, const QString& label ) { #ifdef DEBUG if (!wid ) return; #endif OSplitterContainer cont; cont.widget = wid; cont.icon =icon; cont.name = label; m_container.append( cont ); /* * */ if (!m_splitter.isEmpty() && (m_tabWidget || m_parentTab ) ) setTabWidget( m_parentTab ); else { if (m_hbox ) addToBox( cont ); - else + else if (m_tabWidget) addToTab( cont ); } } /** * Removes the widget from the tab widgets if necessary. * OSplitter drops ownership of this widget and the widget * will be reparented i tto 0. * The widget will not be deleted. * * @param w The widget to be removed */ void OSplitter::removeWidget( QWidget* w) { ContainerList::Iterator it; for ( it = m_container.begin(); it != m_container.end(); ++it ) if ( (*it).widget == w ) break; if (it == m_container.end() ) return; /* only tab needs to be removed.. box recognizes it */ if ( !m_hbox ) removeFromTab( w ); /* Find reparent it and remove it from our list */ w->reparent( 0, 0, QPoint(0, 0)); it = m_container.remove( it ); } /** * This method will give focus to the widget. If in a tabwidget * the tabbar will be changed * * @param w The widget which will be set the current one */ void OSplitter::setCurrentWidget( QWidget* w) { if (m_tabWidget ) m_tabWidget->setCurrentTab( w ); // else // m_hbox->setFocus( w ); } /** * This is an overloaded member function and only differs in the * argument it takes. * Searches list of widgets for label. It'll pick the first label it finds * * @param label Label to look for. First match will be taken */ void OSplitter::setCurrentWidget( const QString& label ) { ContainerList::Iterator it; for (it = m_container.begin(); it != m_container.end(); ++it ) { if ( (*it).name == label ) { setCurrentWidget( (*it).widget ); break; } } } /** * This will only work when the TabWidget is active * If everything is visible this signal is kindly ignored * @see OTabWidget::setCurrentTab(int) * * @param tab The tab to make current */ void OSplitter::setCurrentWidget( int tab ) { if (m_tabWidget ) m_tabWidget->setCurrentTab( tab ); } /** * return the currently activated widget if in tab widget mode * or null because all widgets are visible */ QWidget* OSplitter::currentWidget() const { if (m_tabWidget) return m_tabWidget->currentWidget(); else if (m_parentTab ) return m_parentTab->currentWidget(); return 0l; } /* wrong */ #if 0 /** * @reimplented for internal reasons * returns the sizeHint of one of its sub widgets */ QSize OSplitter::sizeHint()const { if (m_parentTab ) return QFrame::sizeHint(); if (m_hbox ) return m_hbox->sizeHint(); else return m_tabWidget->sizeHint(); } QSize OSplitter::minimumSizeHint()const { if (m_parentTab ) return QFrame::minimumSizeHint(); if (m_hbox) return m_hbox->sizeHint(); else return m_tabWidget->sizeHint(); } #endif /** * @reimplemented for internal reasons */ void OSplitter::resizeEvent( QResizeEvent* res ) { QFrame::resizeEvent( res ); /* * */ bool mode = true; if ( res->size().width() > m_size_policy && m_orient == Horizontal ) { changeHBox(); mode = false; } else if ( (res->size().width() <= m_size_policy && m_orient == Horizontal ) || (res->size().height() <= m_size_policy && m_orient == Vertical ) ) { changeTab(); } else if ( res->size().height() > m_size_policy && m_orient == Vertical ) { changeVBox(); mode = false; } emit sizeChanged(mode, m_orient ); } /* * Adds a container to a tab either the parent tab * or our own */ void OSplitter::addToTab( const Opie::Ui::Internal::OSplitterContainer& con ) { QWidget *wid = con.widget; // not needed widgetstack will reparent as well wid.reparent(m_tabWidget, wid->getWFlags(), QPoint(0, 0) ); if (m_parentTab ) m_parentTab->addTab( wid, con.icon, con.name ); else m_tabWidget->addTab( wid, con.icon, con.name ); } /* * adds a container to the box */ void OSplitter::addToBox( const Opie::Ui::Internal::OSplitterContainer& con ) { QWidget* wid = con.widget; wid->reparent(m_hbox, 0, QPoint(0, 0) ); } /* * Removes a widget from the tab */ void OSplitter::removeFromTab( QWidget* wid ) { if (m_parentTab ) m_parentTab->removePage( wid ); else m_tabWidget->removePage( wid ); } /* * switches over to a OTabWidget layout * it is recursive */ void OSplitter::changeTab() { /* if we're the owner of the tab widget */ if (m_tabWidget ) { raise(); show(); m_tabWidget->setGeometry( frameRect() ); return; } /* * and add all widgets this will reparent them * delete m_hbox set it to 0 * */ OTabWidget *tab; if ( m_parentTab ) { hide(); tab = m_parentTab; /* expensive but needed cause we're called from setTabWidget and resizeEvent*/ if (!m_container.isEmpty() ) { ContainerList::Iterator it = m_container.begin(); for (; it != m_container.end(); ++it ) m_parentTab->removePage( (*it).widget ); } } else tab = m_tabWidget = new OTabWidget( this ); connect(tab, SIGNAL(currentChanged(QWidget*) ), this, SIGNAL(currentChanged(QWidget*) ) ); for ( ContainerList::Iterator it = m_container.begin(); it != m_container.end(); ++it ) { addToTab( (*it) ); } for ( OSplitter* split = m_splitter.first(); split; split = m_splitter.next() ) { split->reparent(this, 0, QPoint(0, 0) ); split->setTabWidget( tab ); } delete m_hbox; m_hbox = 0; if (!m_tabWidget ) return; m_tabWidget->setGeometry( frameRect() ); m_tabWidget->show(); } /* * changes over to a box * this is recursive as well */ void OSplitter::changeHBox() { if (m_hbox ) { m_hbox->setGeometry( frameRect() ); return; } m_hbox = new QHBox( this ); commonChangeBox(); } void OSplitter::changeVBox() { if (m_hbox ) { m_hbox->setGeometry( frameRect() ); return; } m_hbox = new QVBox( this ); commonChangeBox(); } /* * common box code * first remove and add children * the other splitters * it is recursive as well due the call to setTabWidget */ void OSplitter::commonChangeBox() { for (ContainerList::Iterator it = m_container.begin(); it != m_container.end(); ++it ) { /* only if parent tab.. m_tabWidgets gets deleted and would do that as well */ if (m_parentTab ) removeFromTab( (*it).widget ); addToBox( (*it) ); } for ( OSplitter* split = m_splitter.first(); split; split = m_splitter.next() ) { /* tell them the world had changed */ split->setTabWidget( 0 ); OSplitterContainer con; con.widget = split; // con.widget = split->m_tabWidget ? static_cast<QWidget*>(split->m_tabWidget) // : static_cast<QWidget*>(split->m_hbox); addToBox( con ); } if (m_parentTab ) m_parentTab->addTab(m_hbox, iconName(), label() ); else { m_hbox->setGeometry( frameRect() ); m_hbox->show(); delete m_tabWidget; m_tabWidget = 0; show(); // also show this widget } } /* * sets the tabwidget, removes tabs, and relayouts the widget */ void OSplitter::setTabWidget( OTabWidget* wid) { /* clean up cause m_parentTab will not be available for us */ if ( m_parentTab ) { if (m_hbox ) m_parentTab->removePage( m_hbox ); else if (!m_container.isEmpty() ) { ContainerList::Iterator it = m_container.begin(); for ( ; it != m_container.end(); ++it ) m_parentTab->removePage( (*it).widget ); } } /* the parent Splitter changed so either make us indepent or dep */ m_parentTab = wid; QWidget *tab = m_tabWidget; QWidget *box = m_hbox; m_hbox = 0; m_tabWidget = 0; if ( layoutMode() ) changeTab(); else if (m_orient == Horizontal ) changeHBox(); else changeVBox(); /* our own crap is added and children from change* */ delete tab; delete box; } #if 0 void OSplitter::reparentAll() { if (m_container.isEmpty() ) return; ContainerList::Iterator it = m_container.begin(); for ( ; it != m_container.end(); ++it ) (*it).wid->reparent(0, 0, QPoint(0, 0) ); } #endif /** * @internal */ bool OSplitter::layoutMode()const { if ( size().width() > m_size_policy && m_orient == Horizontal ) { return false; } else if ( size().height() > m_size_policy && m_orient == Vertical ) { return false; } return true; } diff --git a/library/qpeapplication.cpp b/library/qpeapplication.cpp index 34f5e6a..d959c7a 100644 --- a/library/qpeapplication.cpp +++ b/library/qpeapplication.cpp @@ -1,2296 +1,2296 @@ /********************************************************************** ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** ** This file is part of the Qtopia Environment. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** */ #define QTOPIA_INTERNAL_LANGLIST #include <stdlib.h> #include <unistd.h> #ifndef Q_OS_MACX #include <linux/limits.h> // needed for some toolchains (PATH_MAX) #endif #include <qfile.h> #include <qqueue.h> #ifdef Q_WS_QWS #ifndef QT_NO_COP #if QT_VERSION <= 231 #define private public #define sendLocally processEvent #include "qcopenvelope_qws.h" #undef private #else #include "qcopenvelope_qws.h" #endif #endif #include <qwindowsystem_qws.h> #endif #include <qtextstream.h> #include <qpalette.h> #include <qbuffer.h> #include <qptrdict.h> #include <qregexp.h> #include <qdir.h> #include <qlabel.h> #include <qdialog.h> #include <qdragobject.h> #include <qtextcodec.h> #include <qevent.h> #include <qtooltip.h> #include <qsignal.h> #include <qmainwindow.h> #include <qwidgetlist.h> #include <qpixmapcache.h> #if defined(Q_WS_QWS) && !defined(QT_NO_COP) #define QTOPIA_INTERNAL_INITAPP #include "qpeapplication.h" #include "qpestyle.h" #include "styleinterface.h" #if QT_VERSION >= 0x030000 #include <qstylefactory.h> #else #include <qplatinumstyle.h> #include <qwindowsstyle.h> #include <qmotifstyle.h> #include <qmotifplusstyle.h> #include "lightstyle.h" #include <qpe/qlibrary.h> #endif #include "global.h" #include "resource.h" #if QT_VERSION <= 230 && defined(QT_NO_CODECS) #include "qutfcodec.h" #endif #include "config.h" #include "network.h" #ifdef QWS #include "fontmanager.h" #include "fontdatabase.h" #endif #include "alarmserver.h" #include "applnk.h" #include "qpemenubar.h" #include "textcodecinterface.h" #include "imagecodecinterface.h" #include <qtopia/qpeglobal.h> #include <unistd.h> #include <sys/file.h> #include <sys/ioctl.h> #ifndef QT_NO_SOUND #include <sys/soundcard.h> #endif #include <backend/rohfeedback.h> static bool useBigPixmaps = 0; static bool saveWindowsPos = 0; class HackWidget : public QWidget { public: bool needsOk() { return (getWState() & WState_Reserved1 ); } QRect normalGeometry() { return topData()->normalGeometry; }; }; class QPEApplicationData { public: QPEApplicationData ( ) : presstimer( 0 ), presswidget( 0 ), rightpressed( false ), kbgrabbed( false ), notbusysent( false ), preloaded( false ), forceshow( false ), nomaximize( false ), keep_running( true ), qcopQok( false ), fontFamily( "Vera" ), fontSize( 10 ), smallIconSize( 14 ), bigIconSize( 32 ), qpe_main_widget( 0 ) { Config cfg( "qpe" ); cfg.setGroup( "Appearance" ); useBigPixmaps = cfg.readBoolEntry( "useBigPixmaps", false ); fontFamily = cfg.readEntry( "FontFamily", "Vera" ); fontSize = cfg.readNumEntry( "FontSize", 10 ); smallIconSize = cfg.readNumEntry( "SmallIconSize", 14 ); bigIconSize = cfg.readNumEntry( "BigIconSize", 32 ); saveWindowsPos = cfg.readBoolEntry( "AllowWindowed", false ); #ifdef OPIE_WITHROHFEEDBACK RoH = 0; #endif } int presstimer; QWidget* presswidget; QPoint presspos; #ifdef OPIE_WITHROHFEEDBACK Opie::Internal::RoHFeedback *RoH; #endif bool rightpressed : 1; bool kbgrabbed : 1; bool notbusysent : 1; bool preloaded : 1; bool forceshow : 1; bool nomaximize : 1; bool keep_running : 1; bool qcopQok : 1; QCString fontFamily; int fontSize; int smallIconSize; int bigIconSize; QString appName; struct QCopRec { QCopRec( const QCString &ch, const QCString &msg, const QByteArray &d ) : channel( ch ), message( msg ), data( d ) { } QCString channel; QCString message; QByteArray data; }; QGuardedPtr<QWidget> qpe_main_widget; QGuardedPtr<QWidget> lastraised; QQueue<QCopRec> qcopq; QString styleName; QString decorationName; void enqueueQCop( const QCString &ch, const QCString &msg, const QByteArray &data ) { qcopq.enqueue( new QCopRec( ch, msg, data ) ); } void sendQCopQ() { if (!qcopQok ) return; QCopRec * r; while((r=qcopq.dequeue())) { // remove from queue before sending... // event loop can come around again before getting // back from sendLocally #ifndef QT_NO_COP QCopChannel::sendLocally( r->channel, r->message, r->data ); #endif delete r; } } static void show_mx(QWidget* mw, bool nomaximize, QString &strName) { if ( mw->inherits("QMainWindow") || mw->isA("QMainWindow") ) { ( ( QMainWindow* ) mw )->setUsesBigPixmaps( useBigPixmaps ); } QPoint p; QSize s; bool max; if ( mw->isVisible() ) { if ( read_widget_rect(strName, max, p, s) && validate_widget_size(mw, p, s) ) { mw->resize(s); mw->move(p); } mw->raise(); } else { if ( mw->layout() && mw->inherits("QDialog") ) { if ( read_widget_rect(strName, max, p, s) && validate_widget_size(mw, p, s) ) { mw->resize(s); mw->move(p); if ( max && !nomaximize ) { mw->showMaximized(); } else { mw->show(); } } else { QPEApplication::showDialog((QDialog*)mw,nomaximize); } } else { if ( read_widget_rect(strName, max, p, s) && validate_widget_size(mw, p, s) ) { mw->resize(s); mw->move(p); } else { //no stored rectangle, make an estimation int x = (qApp->desktop()->width()-mw->frameGeometry().width())/2; int y = (qApp->desktop()->height()-mw->frameGeometry().height())/2; mw->move( QMAX(x,0), QMAX(y,0) ); #ifdef Q_WS_QWS if ( !nomaximize ) mw->showMaximized(); #endif } if ( max && !nomaximize ) mw->showMaximized(); else mw->show(); } } } static bool read_widget_rect(const QString &app, bool &maximized, QPoint &p, QSize &s) { if (!saveWindowsPos) return FALSE; maximized = TRUE; // 350 is the trigger in qwsdefaultdecoration for providing a resize button if ( qApp->desktop()->width() <= 350 ) return FALSE; Config cfg( "qpe" ); cfg.setGroup("ApplicationPositions"); QString str = cfg.readEntry( app, QString::null ); QStringList l = QStringList::split(",", str); if ( l.count() == 5) { p.setX( l[0].toInt() ); p.setY( l[1].toInt() ); s.setWidth( l[2].toInt() ); s.setHeight( l[3].toInt() ); maximized = l[4].toInt(); return TRUE; } } static bool validate_widget_size(const QWidget *w, QPoint &p, QSize &s) { #ifndef Q_WS_QWS QRect qt_maxWindowRect = qApp->desktop()->geometry(); #endif int maxX = qt_maxWindowRect.width(); int maxY = qt_maxWindowRect.height(); int wWidth = s.width() + ( w->frameGeometry().width() - w->geometry().width() ); int wHeight = s.height() + ( w->frameGeometry().height() - w->geometry().height() ); // total window size is not allowed to be larger than desktop window size if ( ( wWidth >= maxX ) && ( wHeight >= maxY ) ) return FALSE; if ( wWidth > maxX ) { s.setWidth( maxX - (w->frameGeometry().width() - w->geometry().width() ) ); wWidth = maxX; } if ( wHeight > maxY ) { s.setHeight( maxY - (w->frameGeometry().height() - w->geometry().height() ) ); wHeight = maxY; } // any smaller than this and the maximize/close/help buttons will be overlapping if ( wWidth < 80 || wHeight < 60 ) return FALSE; if ( p.x() < 0 ) p.setX(0); if ( p.y() < 0 ) p.setY(0); if ( p.x() + wWidth > maxX ) p.setX( maxX - wWidth ); if ( p.y() + wHeight > maxY ) p.setY( maxY - wHeight ); return TRUE; } static void store_widget_rect(QWidget *w, QString &app) { if( !w ) return; if (!saveWindowsPos) return; // 350 is the trigger in qwsdefaultdecoration for providing a resize button if ( qApp->desktop()->width() <= 350 ) return; // we use these to map the offset of geometry and pos. ( we can only use normalGeometry to // get the non-maximized version, so we have to do it the hard way ) int offsetX = w->x() - w->geometry().left(); int offsetY = w->y() - w->geometry().top(); QRect r; if ( w->isMaximized() ) r = ( (HackWidget *) w)->normalGeometry(); else r = w->geometry(); // Stores the window placement as pos(), size() (due to the offset mapping) Config cfg( "qpe" ); cfg.setGroup("ApplicationPositions"); QString s; s.sprintf("%d,%d,%d,%d,%d", r.left() + offsetX, r.top() + offsetY, r.width(), r.height(), w->isMaximized() ); cfg.writeEntry( app, s ); } static bool setWidgetCaptionFromAppName( QWidget* /*mw*/, const QString& /*appName*/, const QString& /*appsPath*/ ) { /* // This works but disable it for now until it is safe to apply // What is does is scan the .desktop files of all the apps for // the applnk that has the corresponding argv[0] as this program // then it uses the name stored in the .desktop file as the caption // for the main widget. This saves duplicating translations for // the app name in the program and in the .desktop files. AppLnkSet apps( appsPath ); QList<AppLnk> appsList = apps.children(); for ( QListIterator<AppLnk> it(appsList); it.current(); ++it ) { if ( (*it)->exec() == appName ) { mw->setCaption( (*it)->name() ); return TRUE; } } */ return FALSE; } void show(QWidget* mw, bool nomax) { setWidgetCaptionFromAppName( mw, appName, QPEApplication::qpeDir() + "apps" ); nomaximize = nomax; qpe_main_widget = mw; qcopQok = TRUE; #ifndef QT_NO_COP sendQCopQ(); #endif if ( preloaded ) { if (forceshow) show_mx(mw, nomax, appName); } else if ( keep_running ) { show_mx(mw, nomax, appName); } } void loadTextCodecs() { QString path = QPEApplication::qpeDir() + "plugins/textcodecs"; #ifdef Q_OS_MACX QDir dir( path, "lib*.dylib" ); #else QDir dir( path, "lib*.so" ); #endif QStringList list; if ( dir. exists ( )) list = dir.entryList(); QStringList::Iterator it; for ( it = list.begin(); it != list.end(); ++it ) { TextCodecInterface *iface = 0; QLibrary *lib = new QLibrary( path + "/" + *it ); if ( lib->queryInterface( IID_QtopiaTextCodec, (QUnknownInterface**)&iface ) == QS_OK && iface ) { QValueList<int> mibs = iface->mibEnums(); for (QValueList<int>::ConstIterator i = mibs.begin(); i != mibs.end(); ++i) { (void)iface->createForMib(*i); // ### it exists now; need to remember if we can delete it } } else { lib->unload(); delete lib; } } } void loadImageCodecs() { QString path = QPEApplication::qpeDir() + "plugins/imagecodecs"; #ifdef Q_OS_MACX QDir dir( path, "lib*.dylib" ); #else QDir dir( path, "lib*.so" ); #endif QStringList list; if ( dir. exists ( )) list = dir.entryList(); QStringList::Iterator it; for ( it = list.begin(); it != list.end(); ++it ) { ImageCodecInterface *iface = 0; QLibrary *lib = new QLibrary( path + "/" + *it ); if ( lib->queryInterface( IID_QtopiaImageCodec, (QUnknownInterface**)&iface ) == QS_OK && iface ) { QStringList formats = iface->keys(); for (QStringList::ConstIterator i = formats.begin(); i != formats.end(); ++i) { (void)iface->installIOHandler(*i); // ### it exists now; need to remember if we can delete it } } else { lib->unload(); delete lib; } } } }; class ResourceMimeFactory : public QMimeSourceFactory { public: ResourceMimeFactory() : resImage( 0 ) { setFilePath( Global::helpPath() ); setExtensionType( "html", "text/html;charset=UTF-8" ); } ~ResourceMimeFactory() { delete resImage; } const QMimeSource* data( const QString& abs_name ) const { const QMimeSource * r = QMimeSourceFactory::data( abs_name ); if ( !r ) { int sl = abs_name.length(); do { sl = abs_name.findRev( '/', sl - 1 ); QString name = sl >= 0 ? abs_name.mid( sl + 1 ) : abs_name; int dot = name.findRev( '.' ); if ( dot >= 0 ) name = name.left( dot ); QImage img = Resource::loadImage( name ); if ( !img.isNull() ) { delete resImage; resImage = new QImageDrag( img ); r = resImage; } } while ( !r && sl > 0 ); } return r; } private: mutable QImageDrag *resImage; }; static int& hack(int& i) { #if QT_VERSION <= 230 && defined(QT_NO_CODECS) // These should be created, but aren't in Qt 2.3.0 (void)new QUtf8Codec; (void)new QUtf16Codec; #endif return i; } static int muted = 0; static int micMuted = 0; static void setVolume( int t = 0, int percent = -1 ) { switch ( t ) { case 0: { Config cfg( "qpe" ); cfg.setGroup( "Volume" ); if ( percent < 0 ) percent = cfg.readNumEntry( "VolumePercent", 50 ); #ifndef QT_NO_SOUND int fd = 0; #ifdef QT_QWS_DEVFS if ( ( fd = open( "/dev/sound/mixer", O_RDWR ) ) >= 0 ) { #else if ( ( fd = open( "/dev/mixer", O_RDWR ) ) >= 0 ) { #endif int vol = muted ? 0 : percent; // set both channels to same volume vol |= vol << 8; ioctl( fd, MIXER_WRITE( SOUND_MIXER_VOLUME ), &vol ); ::close( fd ); } #endif } break; } } static void setMic( int t = 0, int percent = -1 ) { switch ( t ) { case 0: { Config cfg( "qpe" ); cfg.setGroup( "Volume" ); if ( percent < 0 ) percent = cfg.readNumEntry( "Mic", 50 ); #ifndef QT_NO_SOUND int fd = 0; int mic = micMuted ? 0 : percent; #ifdef QT_QWS_DEVFS if ( ( fd = open( "/dev/sound/mixer", O_RDWR ) ) >= 0 ) { #else if ( ( fd = open( "/dev/mixer", O_RDWR ) ) >= 0 ) { #endif ioctl( fd, MIXER_WRITE( SOUND_MIXER_MIC ), &mic ); ::close( fd ); } #endif } break; } } static void setBass( int t = 0, int percent = -1 ) { switch ( t ) { case 0: { Config cfg( "qpe" ); cfg.setGroup( "Volume" ); if ( percent < 0 ) percent = cfg.readNumEntry( "BassPercent", 50 ); #ifndef QT_NO_SOUND int fd = 0; int bass = percent; #ifdef QT_QWS_DEVFS if ( ( fd = open( "/dev/sound/mixer", O_RDWR ) ) >= 0 ) { #else if ( ( fd = open( "/dev/mixer", O_RDWR ) ) >= 0 ) { #endif ioctl( fd, MIXER_WRITE( SOUND_MIXER_BASS ), &bass ); ::close( fd ); } #endif } break; } } static void setTreble( int t = 0, int percent = -1 ) { switch ( t ) { case 0: { Config cfg( "qpe" ); cfg.setGroup( "Volume" ); if ( percent < 0 ) percent = cfg.readNumEntry( "TreblePercent", 50 ); #ifndef QT_NO_SOUND int fd = 0; int treble = percent; #ifdef QT_QWS_DEVFS if ( ( fd = open( "/dev/sound/mixer", O_RDWR ) ) >= 0 ) { #else if ( ( fd = open( "/dev/mixer", O_RDWR ) ) >= 0 ) { #endif ioctl( fd, MIXER_WRITE( SOUND_MIXER_TREBLE ), &treble ); ::close( fd ); } #endif } break; } } /** \class QPEApplication \brief The QPEApplication class implements various system services that are available to all Qtopia applications. Simply by using QPEApplication instead of QApplication, a standard Qt application becomes a Qtopia application. It automatically follows style changes, quits and raises, and in the case of \link docwidget.html document-oriented\endlink applications, changes the currently displayed document in response to the environment. To create a \link docwidget.html document-oriented\endlink application use showMainDocumentWidget(); to create a non-document-oriented application use showMainWidget(). The keepRunning() function indicates whether the application will continue running after it's processed the last \link qcop.html QCop\endlink message. This can be changed using setKeepRunning(). A variety of signals are emitted when certain events occur, for example, timeChanged(), clockChanged(), weekChanged(), dateFormatChanged() and volumeChanged(). If the application receives a \link qcop.html QCop\endlink message on the application's QPE/Application/\e{appname} channel, the appMessage() signal is emitted. There are also flush() and reload() signals, which are emitted when synching begins and ends respectively - upon these signals, the application should save and reload any data files that are involved in synching. Most of these signals will initially be received and unfiltered through the appMessage() signal. This class also provides a set of useful static functions. The qpeDir() and documentDir() functions return the respective paths. The grabKeyboard() and ungrabKeyboard() functions are used to control whether the application takes control of the device's physical buttons (e.g. application launch keys). The stylus' mode of operation is set with setStylusOperation() and retrieved with stylusOperation(). There are also setInputMethodHint() and inputMethodHint() functions. \ingroup qtopiaemb */ /*! \fn void QPEApplication::clientMoused() \internal */ /*! \fn void QPEApplication::timeChanged(); This signal is emitted when the time changes outside the normal passage of time, i.e. if the time is set backwards or forwards. */ /*! \fn void QPEApplication::clockChanged( bool ampm ); This signal is emitted when the user changes the clock's style. If \a ampm is TRUE, the user wants a 12-hour AM/PM clock, otherwise, they want a 24-hour clock. */ /*! \fn void QPEApplication::volumeChanged( bool muted ) This signal is emitted whenever the mute state is changed. If \a muted is TRUE, then sound output has been muted. */ /*! \fn void QPEApplication::weekChanged( bool startOnMonday ) This signal is emitted if the week start day is changed. If \a startOnMonday is TRUE then the first day of the week is Monday; if \a startOnMonday is FALSE then the first day of the week is Sunday. */ /*! \fn void QPEApplication::dateFormatChanged(DateFormat) This signal is emitted whenever the date format is changed. */ /*! \fn void QPEApplication::flush() ### */ /*! \fn void QPEApplication::reload() */ void QPEApplication::processQCopFile() { QString qcopfn("/tmp/qcop-msg-"); qcopfn += d->appName; // append command name QFile f(qcopfn); if ( f.open(IO_ReadWrite) ) { #ifndef Q_OS_WIN32 flock(f.handle(), LOCK_EX); #endif QDataStream ds(&f); QCString channel, message; QByteArray data; while(!ds.atEnd()) { ds >> channel >> message >> data; d->enqueueQCop(channel,message,data); } ::ftruncate(f.handle(), 0); #ifndef Q_OS_WIN32 f.flush(); flock(f.handle(), LOCK_UN); #endif } #endif } /*! \fn void QPEApplication::appMessage( const QCString& msg, const QByteArray& data ) This signal is emitted when a message is received on this application's QPE/Application/<i>appname</i> \link qcop.html QCop\endlink channel. The slot to which you connect this signal uses \a msg and \a data in the following way: \code void MyWidget::receive( const QCString& msg, const QByteArray& data ) { QDataStream stream( data, IO_ReadOnly ); if ( msg == "someMessage(int,int,int)" ) { int a,b,c; stream >> a >> b >> c; ... } else if ( msg == "otherMessage(QString)" ) { ... } } \endcode \sa qcop.html Note that messages received here may be processed by qpe application and emitted as signals, such as flush() and reload(). */ #ifndef QT_NO_TRANSLATION static void qtopia_loadTranslations( const QStringList& qms ) { QStringList langs = Global::languageList(); for (QStringList::ConstIterator it = langs.begin(); it!=langs.end(); ++it) { QString lang = *it; QTranslator * trans; QString tfn; for (QStringList::ConstIterator qmit = qms.begin(); qmit!=qms.end(); ++qmit) { trans = new QTranslator(qApp); tfn = QPEApplication::qpeDir() + "i18n/" + lang + "/" + *qmit + ".qm"; if ( trans->load( tfn )) qApp->installTranslator( trans ); else delete trans; } } } #endif /* Turn off qDebug in release mode */ static void qtopiaMsgHandler(QtMsgType type, const char* msg) { switch ( type ) { case QtDebugMsg: #ifdef QT_DEBUG fprintf( stderr, "Debug: %s\n", msg ); #endif break; case QtWarningMsg: #ifdef QT_DEBUG fprintf( stderr, "Warning: %s\n", msg ); #endif break; case QtFatalMsg: fprintf( stderr, "Fatal: %s\n", msg ); abort(); } } /*! Constructs a QPEApplication just as you would construct a QApplication, passing \a argc, \a argv, and \a t. For applications, \a t should be the default, GuiClient. Only the Qtopia server passes GuiServer. */ QPEApplication::QPEApplication( int & argc, char **argv, Type t ) : QApplication( hack(argc), argv, t ), pidChannel( 0 ) { QPixmapCache::setCacheLimit(256); // sensible default for smaller devices. qInstallMsgHandler(qtopiaMsgHandler); d = new QPEApplicationData; d->loadTextCodecs(); d->loadImageCodecs(); setFont( QFont( d->fontFamily, d->fontSize ) ); AppLnk::setSmallIconSize( d->smallIconSize ); AppLnk::setBigIconSize( d->bigIconSize ); QMimeSourceFactory::setDefaultFactory( new ResourceMimeFactory ); connect( this, SIGNAL( lastWindowClosed() ), this, SLOT( hideOrQuit() ) ); sysChannel = new QCopChannel( "QPE/System", this ); connect( sysChannel, SIGNAL( received(const QCString&,const QByteArray&) ), this, SLOT( systemMessage(const QCString&,const QByteArray&) ) ); /* COde now in initapp */ #if 0 #if defined(Q_WS_QWS) && !defined(QT_NO_COP) QString qcopfn( "/tmp/qcop-msg-" ); qcopfn += QString( argv[ 0 ] ); // append command name QFile f( qcopfn ); if ( f.open( IO_ReadOnly ) ) { flock( f.handle(), LOCK_EX ); } QCString channel = QCString( argv[ 0 ] ); channel.replace( QRegExp( ".*/" ), "" ); d->appName = channel; channel = "QPE/Application/" + channel; pidChannel = new QCopChannel( channel, this ); connect( pidChannel, SIGNAL( received(const QCString&,const QByteArray&) ), this, SLOT( pidMessage(const QCString&,const QByteArray&) ) ); if ( f.isOpen() ) { d->keep_running = FALSE; QDataStream ds( &f ); QCString channel, message; QByteArray data; while ( !ds.atEnd() ) { ds >> channel >> message >> data; d->enqueueQCop( channel, message, data ); } flock( f.handle(), LOCK_UN ); f.close(); f.remove(); } for ( int a = 0; a < argc; a++ ) { if ( qstrcmp( argv[ a ], "-preload" ) == 0 ) { argv[ a ] = argv[ a + 1 ]; a++; d->preloaded = TRUE; argc -= 1; } else if ( qstrcmp( argv[ a ], "-preload-show" ) == 0 ) { argv[ a ] = argv[ a + 1 ]; a++; d->preloaded = TRUE; d->forceshow = TRUE; argc -= 1; } } /* overide stored arguments */ setArgs( argc, argv ); #endif #else initApp( argc, argv ); #endif #ifdef Q_WS_QWS /* load the font renderer factories */ FontDatabase::loadRenderers(); #endif #ifndef QT_NO_TRANSLATION QStringList qms; qms << "libqpe"; qms << "libopie"; qms << d->appName; qtopia_loadTranslations(qms); #endif applyStyle(); if ( type() == GuiServer ) { setVolume(); } installEventFilter( this ); QPEMenuToolFocusManager::initialize(); #ifdef QT_NO_QWS_CURSOR // if we have no cursor, probably don't want tooltips QToolTip::setEnabled( FALSE ); #endif } #ifdef QTOPIA_INTERNAL_INITAPP void QPEApplication::initApp( int argc, char **argv ) { delete pidChannel; d->keep_running = TRUE; d->preloaded = FALSE; d->forceshow = FALSE; QCString channel = QCString(argv[0]); channel.replace(QRegExp(".*/"),""); d->appName = channel; #ifndef QT_NO_TRANSLATION qtopia_loadTranslations( QStringList()<<channel ); #endif #if QT_VERSION > 235 qt_fbdpy->setIdentity( channel ); // In Qt/E 2.3.6 #endif channel = "QPE/Application/" + channel; pidChannel = new QCopChannel( channel, this); connect( pidChannel, SIGNAL(received(const QCString&,const QByteArray&)), this, SLOT(pidMessage(const QCString&,const QByteArray&))); processQCopFile(); d->keep_running = d->qcopq.isEmpty(); for (int a=0; a<argc; a++) { if ( qstrcmp(argv[a],"-preload")==0 ) { argv[a] = argv[a+1]; a++; d->preloaded = TRUE; argc-=1; } else if ( qstrcmp(argv[a],"-preload-show")==0 ) { argv[a] = argv[a+1]; a++; d->preloaded = TRUE; d->forceshow = TRUE; argc-=1; } } /* overide stored arguments */ setArgs(argc, argv); } #endif static QPtrDict<void>* inputMethodDict = 0; static void createInputMethodDict() { if ( !inputMethodDict ) inputMethodDict = new QPtrDict<void>; } /*! Returns the currently set hint to the system as to whether widget \a w has any use for text input methods. \sa setInputMethodHint() InputMethodHint */ QPEApplication::InputMethodHint QPEApplication::inputMethodHint( QWidget * w ) { if ( inputMethodDict && w ) return ( InputMethodHint ) ( int ) inputMethodDict->find( w ); return Normal; } /*! \enum QPEApplication::InputMethodHint \value Normal the application sometimes needs text input (the default). \value AlwaysOff the application never needs text input. \value AlwaysOn the application always needs text input. */ /*! Hints to the system that widget \a w has use for text input methods as specified by \a mode. \sa inputMethodHint() InputMethodHint */ void QPEApplication::setInputMethodHint( QWidget * w, InputMethodHint mode ) { createInputMethodDict(); if ( mode == Normal ) { inputMethodDict->remove ( w ); } else { inputMethodDict->insert( w, ( void* ) mode ); } } class HackDialog : public QDialog { public: void acceptIt() { accept(); } void rejectIt() { reject(); } }; void QPEApplication::mapToDefaultAction( QWSKeyEvent * ke, int key ) { // specialised actions for certain widgets. May want to // add more stuff here. if ( activePopupWidget() && activePopupWidget() ->inherits( "QListBox" ) && activePopupWidget() ->parentWidget() && activePopupWidget() ->parentWidget() ->inherits( "QComboBox" ) ) key = Qt::Key_Return; if ( activePopupWidget() && activePopupWidget() ->inherits( "QPopupMenu" ) ) key = Qt::Key_Return; #ifdef QWS ke->simpleData.keycode = key; #endif } /*! \internal */ #ifdef QWS bool QPEApplication::qwsEventFilter( QWSEvent * e ) { if ( !d->notbusysent && e->type == QWSEvent::Focus ) { if ( qApp->type() != QApplication::GuiServer ) { QCopEnvelope e( "QPE/System", "notBusy(QString)" ); e << d->appName; } d->notbusysent = TRUE; } if ( type() == GuiServer ) { switch ( e->type ) { case QWSEvent::Mouse: if ( e->asMouse() ->simpleData.state && !QWidget::find( e->window() ) ) emit clientMoused(); break; default: break; } } if ( e->type == QWSEvent::Key ) { QWSKeyEvent *ke = ( QWSKeyEvent * ) e; if ( ke->simpleData.keycode == Qt::Key_F33 ) { // Use special "OK" key to press "OK" on top level widgets QWidget * active = activeWindow(); QWidget *popup = 0; if ( active && active->isPopup() ) { popup = active; active = active->parentWidget(); } if ( active && ( int ) active->winId() == ke->simpleData.window && !active->testWFlags( WStyle_Customize | WType_Popup | WType_Desktop ) ) { if ( ke->simpleData.is_press ) { if ( popup ) popup->close(); if ( active->inherits( "QDialog" ) ) { HackDialog * d = ( HackDialog * ) active; d->acceptIt(); return TRUE; } else if ( ( ( HackWidget * ) active ) ->needsOk() ) { QSignal s; s.connect( active, SLOT( accept() ) ); s.activate(); } else { // do the same as with the select key: Map to the default action of the widget: mapToDefaultAction( ke, Qt::Key_Return ); } } } } else if ( ke->simpleData.keycode == Qt::Key_F30 ) { // Use special "select" key to do whatever default action a widget has mapToDefaultAction( ke, Qt::Key_Space ); } else if ( ke->simpleData.keycode == Qt::Key_Escape && ke->simpleData.is_press ) { // Escape key closes app if focus on toplevel QWidget * active = activeWindow(); if ( active && active->testWFlags( WType_TopLevel ) && ( int ) active->winId() == ke->simpleData.window && !active->testWFlags( WStyle_Dialog | WStyle_Customize | WType_Popup | WType_Desktop ) ) { if ( active->inherits( "QDialog" ) ) { HackDialog * d = ( HackDialog * ) active; d->rejectIt(); return TRUE; } else /*if ( strcmp( argv() [ 0 ], "embeddedkonsole" ) != 0 )*/ { active->close(); } } } else if ( ke->simpleData.keycode >= Qt::Key_F1 && ke->simpleData.keycode <= Qt::Key_F29 ) { // this should be if ( ODevice::inst ( )-> buttonForKeycode ( ... )) // but we cannot access libopie function within libqpe :( QWidget * active = activeWindow ( ); if ( active && ((int) active-> winId ( ) == ke-> simpleData.window )) { if ( d-> kbgrabbed ) { // we grabbed the keyboard QChar ch ( ke-> simpleData.unicode ); QKeyEvent qke ( ke-> simpleData. is_press ? QEvent::KeyPress : QEvent::KeyRelease, ke-> simpleData.keycode, ch. latin1 ( ), ke-> simpleData.modifiers, QString ( ch ), ke-> simpleData.is_auto_repeat, 1 ); QObject *which = QWidget::keyboardGrabber ( ); if ( !which ) which = QApplication::focusWidget ( ); if ( !which ) which = QApplication::activeWindow ( ); if ( !which ) which = qApp; QApplication::sendEvent ( which, &qke ); } else { // we didn't grab the keyboard, so send the event to the launcher QCopEnvelope e ( "QPE/Launcher", "deviceButton(int,int,int)" ); e << int( ke-> simpleData.keycode ) << int( ke-> simpleData. is_press ) << int( ke-> simpleData.is_auto_repeat ); } } return true; } } if ( e->type == QWSEvent::Focus ) { QWSFocusEvent * fe = ( QWSFocusEvent* ) e; if ( !fe->simpleData.get_focus ) { QWidget * active = activeWindow(); while ( active && active->isPopup() ) { active->close(); active = activeWindow(); } } else { // make sure our modal widget is ALWAYS on top QWidget *topm = activeModalWidget(); if ( topm && static_cast<int>( topm->winId() ) != fe->simpleData.window) { topm->raise(); } } if ( fe->simpleData.get_focus && inputMethodDict ) { InputMethodHint m = inputMethodHint( QWidget::find( e->window() ) ); if ( m == AlwaysOff ) Global::hideInputMethod(); if ( m == AlwaysOn ) Global::showInputMethod(); } } return QApplication::qwsEventFilter( e ); } #endif /*! Destroys the QPEApplication. */ QPEApplication::~QPEApplication() { ungrabKeyboard(); #if defined(Q_WS_QWS) && !defined(QT_NO_COP) // Need to delete QCopChannels early, since the display will // be gone by the time we get to ~QObject(). delete sysChannel; delete pidChannel; #endif #ifdef OPIE_WITHROHFEEDBACK if( d->RoH ) delete d->RoH; #endif delete d; } /*! Returns <tt>$OPIEDIR/</tt>. */ QString QPEApplication::qpeDir() { QString base, dir; if (getenv( "OPIEDIR" )) base = QString(getenv("OPIEDIR")).stripWhiteSpace(); if ( !base.isNull() && (base.length() > 0 )){ #ifdef Q_OS_WIN32 QString temp(base); if (temp[(int)temp.length()-1] != QDir::separator()) temp.append(QDir::separator()); dir = temp; #else dir = QString( base ) + "/"; #endif }else{ dir = QString( ".." ) + QDir::separator(); } return dir; } /*! Returns the user's current Document directory. There is a trailing "/". .. well, it does now,, and there's no trailing '/' */ QString QPEApplication::documentDir() { const char* base = getenv( "HOME"); if ( base ) return QString( base ) + "/Documents"; return QString( "../Documents" ); } static int deforient = -1; /*! \internal */ int QPEApplication::defaultRotation() { if ( deforient < 0 ) { QString d = getenv( "QWS_DISPLAY" ); if ( d.contains( "Rot90" ) ) { deforient = 90; } else if ( d.contains( "Rot180" ) ) { deforient = 180; } else if ( d.contains( "Rot270" ) ) { deforient = 270; } else { deforient = 0; } } return deforient; } /*! \internal */ void QPEApplication::setDefaultRotation( int r ) { if ( qApp->type() == GuiServer ) { deforient = r; int j = 0; QCString old = getenv( "QWS_DISPLAY" ) ? getenv( "QWS_DISPLAY" ) : "Transformed"; QString driver( old.left( ( ( j = old.find( ':' ) ) >= 0 ) ? j : old.size() ).data() ); setenv( "QWS_DISPLAY", QString( "%1:Rot%2:0" ).arg(driver).arg( r ).latin1(), 1 ); Config config("qpe"); config.setGroup( "Rotation" ); config.writeEntry( "Rot", r ); } else { #ifndef QT_NO_COP { QCopEnvelope e( "QPE/System", "setDefaultRotation(int)" ); e << r; } #endif } } #include <qgfx_qws.h> #include <qwindowsystem_qws.h> #if QT_VERSION > 236 extern void qws_clearLoadedFonts(); #endif void QPEApplication::setCurrentMode( int x, int y, int depth ) { // Reset the caches #if QT_VERSION > 236 qws_clearLoadedFonts(); #endif QPixmapCache::clear(); // Change the screen mode qt_screen->setMode(x, y, depth); if ( qApp->type() == GuiServer ) { #if QT_VERSION > 236 // Reconfigure the GuiServer qwsServer->beginDisplayReconfigure(); qwsServer->endDisplayReconfigure(); #endif // Get all the running apps to reset QCopEnvelope env( "QPE/System", "reset()" ); } } void QPEApplication::reset() { // Reconnect to the screen qt_screen->disconnect(); qt_screen->connect( QString::null ); // Redraw everything applyStyle(); } #if (QT_VERSION < 238) && defined Q_OS_MACX bool qt_left_hand_scrollbars = false; #else extern bool qt_left_hand_scrollbars QPE_WEAK_SYMBOL; #endif /*! \internal */ void QPEApplication::applyStyle() { Config config( "qpe" ); config.setGroup( "Appearance" ); #if QT_VERSION > 233 // Widget style QString style = config.readEntry( "Style", "FlatStyle" ); internalSetStyle ( style ); // Colors - from /etc/colors/Liquid.scheme QColor bgcolor( config.readEntry( "Background", "#E0E0E0" ) ); QColor btncolor( config.readEntry( "Button", "#96c8fa" ) ); QPalette pal( btncolor, bgcolor ); QString color = config.readEntry( "Highlight", "#73adef" ); pal.setColor( QColorGroup::Highlight, QColor( color ) ); color = config.readEntry( "HighlightedText", "#FFFFFF" ); pal.setColor( QColorGroup::HighlightedText, QColor( color ) ); color = config.readEntry( "Text", "#000000" ); pal.setColor( QColorGroup::Text, QColor( color ) ); color = config.readEntry( "ButtonText", "#000000" ); pal.setColor( QPalette::Active, QColorGroup::ButtonText, QColor( color ) ); color = config.readEntry( "Base", "#FFFFFF" ); pal.setColor( QColorGroup::Base, QColor( color ) ); pal.setColor( QPalette::Disabled, QColorGroup::Text, pal.color( QPalette::Active, QColorGroup::Background ).dark() ); setPalette( pal, TRUE ); // Set the ScrollBar on the 'right' side but only if the weak symbol is present if (&qt_left_hand_scrollbars ) qt_left_hand_scrollbars = config.readBoolEntry( "LeftHand", false ); // Window Decoration QString dec = config.readEntry( "Decoration", "Flat" ); if ( dec != d->decorationName ) { qwsSetDecoration( new QPEDecoration( dec ) ); d->decorationName = dec; } // Font QString ff = config.readEntry( "FontFamily", font().family() ); int fs = config.readNumEntry( "FontSize", font().pointSize() ); setFont ( QFont ( ff, fs ), true ); #endif } void QPEApplication::systemMessage( const QCString& msg, const QByteArray& data ) { #ifdef Q_WS_QWS QDataStream stream( data, IO_ReadOnly ); if ( msg == "applyStyle()" ) { applyStyle(); } else if ( msg == "toggleApplicationMenu()" ) { QWidget *active = activeWindow ( ); if ( active ) { QPEMenuToolFocusManager *man = QPEMenuToolFocusManager::manager ( ); bool oldactive = man-> isActive ( ); man-> setActive( !man-> isActive() ); if ( !oldactive && !man-> isActive ( )) { // no menubar to toggle -> try O-Menu QCopEnvelope e ( "QPE/TaskBar", "toggleStartMenu()" ); } } } else if ( msg == "setDefaultRotation(int)" ) { if ( type() == GuiServer ) { int r; stream >> r; setDefaultRotation( r ); } } else if ( msg == "setCurrentMode(int,int,int)" ) { // Added: 2003-06-11 by Tim Ansell <mithro@mithis.net> if ( type() == GuiServer ) { int x, y, depth; stream >> x; stream >> y; stream >> depth; setCurrentMode( x, y, depth ); } } else if ( msg == "reset()" ) { if ( type() != GuiServer ) reset(); } else if ( msg == "setCurrentRotation(int)" ) { int r; stream >> r; setCurrentRotation( r ); } else if ( msg == "shutdown()" ) { if ( type() == GuiServer ) shutdown(); } else if ( msg == "quit()" ) { if ( type() != GuiServer ) tryQuit(); } else if ( msg == "forceQuit()" ) { if ( type() != GuiServer ) quit(); } else if ( msg == "restart()" ) { if ( type() == GuiServer ) restart(); } else if ( msg == "language(QString)" ) { if ( type() == GuiServer ) { QString l; stream >> l; QString cl = getenv( "LANG" ); if ( cl != l ) { if ( l.isNull() ) unsetenv( "LANG" ); else setenv( "LANG", l.latin1(), 1 ); restart(); } } } else if ( msg == "timeChange(QString)" ) { QString t; stream >> t; if ( t.isNull() ) unsetenv( "TZ" ); else setenv( "TZ", t.latin1(), 1 ); // emit the signal so everyone else knows... emit timeChanged(); } else if ( msg == "addAlarm(QDateTime,QCString,QCString,int)" ) { if ( type() == GuiServer ) { QDateTime when; QCString channel, message; int data; stream >> when >> channel >> message >> data; AlarmServer::addAlarm( when, channel, message, data ); } } else if ( msg == "deleteAlarm(QDateTime,QCString,QCString,int)" ) { if ( type() == GuiServer ) { QDateTime when; QCString channel, message; int data; stream >> when >> channel >> message >> data; AlarmServer::deleteAlarm( when, channel, message, data ); } } else if ( msg == "clockChange(bool)" ) { int tmp; stream >> tmp; emit clockChanged( tmp ); } else if ( msg == "weekChange(bool)" ) { int tmp; stream >> tmp; emit weekChanged( tmp ); } else if ( msg == "setDateFormat(DateFormat)" ) { DateFormat tmp; stream >> tmp; emit dateFormatChanged( tmp ); } else if ( msg == "setVolume(int,int)" ) { int t, v; stream >> t >> v; setVolume( t, v ); emit volumeChanged( muted ); } else if ( msg == "volumeChange(bool)" ) { stream >> muted; setVolume(); emit volumeChanged( muted ); } else if ( msg == "setMic(int,int)" ) { // Added: 2002-02-08 by Jeremy Cowgar <jc@cowgar.com> int t, v; stream >> t >> v; setMic( t, v ); emit micChanged( micMuted ); } else if ( msg == "micChange(bool)" ) { // Added: 2002-02-08 by Jeremy Cowgar <jc@cowgar.com> stream >> micMuted; setMic(); emit micChanged( micMuted ); } else if ( msg == "setBass(int,int)" ) { // Added: 2002-12-13 by Maximilian Reiss <harlekin@handhelds.org> int t, v; stream >> t >> v; setBass( t, v ); } else if ( msg == "bassChange(bool)" ) { // Added: 2002-12-13 by Maximilian Reiss <harlekin@handhelds.org> setBass(); } else if ( msg == "setTreble(int,int)" ) { // Added: 2002-12-13 by Maximilian Reiss <harlekin@handhelds.org> int t, v; stream >> t >> v; setTreble( t, v ); } else if ( msg == "trebleChange(bool)" ) { // Added: 2002-12-13 by Maximilian Reiss <harlekin@handhelds.org> setTreble(); } else if ( msg == "getMarkedText()" ) { if ( type() == GuiServer ) { const ushort unicode = 'C'-'@'; const int scan = Key_C; qwsServer->processKeyEvent( unicode, scan, ControlButton, TRUE, FALSE ); qwsServer->processKeyEvent( unicode, scan, ControlButton, FALSE, FALSE ); } } else if ( msg == "newChannel(QString)") { QString myChannel = "QPE/Application/" + d->appName; QString channel; stream >> channel; if (channel == myChannel) { processQCopFile(); d->sendQCopQ(); } } #endif } /*! \internal */ bool QPEApplication::raiseAppropriateWindow() { bool r=FALSE; // 1. Raise the main widget QWidget *top = d->qpe_main_widget; if ( !top ) top = mainWidget(); if ( top && d->keep_running ) { if ( top->isVisible() ) r = TRUE; else if (d->preloaded) { // We are preloaded and not visible.. pretend we just started.. #ifndef QT_NO_COP QCopEnvelope e("QPE/System", "fastAppShowing(QString)"); e << d->appName; #endif } d->show_mx(top,d->nomaximize, d->appName); top->raise(); } QWidget *topm = activeModalWidget(); // 2. Raise any parentless widgets (except top and topm, as they // are raised before and after this loop). Order from most // recently raised as deepest to least recently as top, so // that repeated calls cycle through widgets. QWidgetList *list = topLevelWidgets(); if ( list ) { bool foundlast = FALSE; QWidget* topsub = 0; if ( d->lastraised ) { for (QWidget* w = list->first(); w; w = list->next()) { if ( !w->parentWidget() && w != topm && w->isVisible() && !w->isDesktop() ) { if ( w == d->lastraised ) foundlast = TRUE; if ( foundlast ) { w->raise(); topsub = w; } } } } for (QWidget* w = list->first(); w; w = list->next()) { if ( !w->parentWidget() && w != topm && w->isVisible() && !w->isDesktop() ) { if ( w == d->lastraised ) break; w->raise(); topsub = w; } } d->lastraised = topsub; delete list; } // 3. Raise the active modal widget. if ( topm ) { topm->show(); topm->raise(); // If we haven't already handled the fastAppShowing message if (!top && d->preloaded) { #ifndef QT_NO_COP QCopEnvelope e("QPE/System", "fastAppShowing(QString)"); e << d->appName; #endif } r = FALSE; } return r; } void QPEApplication::pidMessage( const QCString& msg, const QByteArray& data) { #ifdef Q_WS_QWS if ( msg == "quit()" ) { tryQuit(); } else if ( msg == "quitIfInvisible()" ) { if ( d->qpe_main_widget && !d->qpe_main_widget->isVisible() ) quit(); } else if ( msg == "close()" ) { hideOrQuit(); } else if ( msg == "disablePreload()" ) { d->preloaded = FALSE; d->keep_running = TRUE; /* so that quit will quit */ } else if ( msg == "enablePreload()" ) { if (d->qpe_main_widget) d->preloaded = TRUE; d->keep_running = TRUE; /* so next quit won't quit */ } else if ( msg == "raise()" ) { d->keep_running = TRUE; d->notbusysent = FALSE; raiseAppropriateWindow(); // Tell the system we're still chugging along... QCopEnvelope e("QPE/System", "appRaised(QString)"); e << d->appName; } else if ( msg == "flush()" ) { emit flush(); // we need to tell the desktop QCopEnvelope e( "QPE/Desktop", "flushDone(QString)" ); e << d->appName; } else if ( msg == "reload()" ) { emit reload(); } else if ( msg == "setDocument(QString)" ) { d->keep_running = TRUE; QDataStream stream( data, IO_ReadOnly ); QString doc; stream >> doc; QWidget *mw = mainWidget(); if ( !mw ) mw = d->qpe_main_widget; if ( mw ) Global::setDocument( mw, doc ); } else if ( msg == "QPEProcessQCop()" ) { processQCopFile(); d->sendQCopQ(); }else { bool p = d->keep_running; d->keep_running = FALSE; emit appMessage( msg, data); if ( d->keep_running ) { d->notbusysent = FALSE; raiseAppropriateWindow(); if ( !p ) { // Tell the system we're still chugging along... #ifndef QT_NO_COP QCopEnvelope e("QPE/System", "appRaised(QString)"); e << d->appName; #endif } } if ( p ) d->keep_running = p; } #endif } /*! Sets widget \a mw as the mainWidget() and shows it. For small windows, consider passing TRUE for \a nomaximize rather than the default FALSE. \sa showMainDocumentWidget() */ void QPEApplication::showMainWidget( QWidget* mw, bool nomaximize ) { // setMainWidget(mw); this breaks FastLoading because lastWindowClose() would quit d->show(mw, nomaximize ); } /*! Sets widget \a mw as the mainWidget() and shows it. For small windows, consider passing TRUE for \a nomaximize rather than the default FALSE. This calls designates the application as a \link docwidget.html document-oriented\endlink application. The \a mw widget \e must have this slot: setDocument(const QString&). \sa showMainWidget() */ void QPEApplication::showMainDocumentWidget( QWidget* mw, bool nomaximize ) { - if ( mw && argc() == 2 ) + if ( mw ) { + if ( argc() == 2 ) Global::setDocument( mw, QString::fromUtf8(argv()[1]) ); - -// setMainWidget(mw); see above d->show(mw, nomaximize ); } +} /*! If an application is started via a \link qcop.html QCop\endlink message, the application will process the \link qcop.html QCop\endlink message and then quit. If the application calls this function while processing a \link qcop.html QCop\endlink message, after processing its outstanding \link qcop.html QCop\endlink messages the application will start 'properly' and show itself. \sa keepRunning() */ void QPEApplication::setKeepRunning() { if ( qApp && qApp->inherits( "QPEApplication" ) ) { QPEApplication * qpeApp = ( QPEApplication* ) qApp; qpeApp->d->keep_running = TRUE; } } /*! Returns TRUE if the application will quit after processing the current list of qcop messages; otherwise returns FALSE. \sa setKeepRunning() */ bool QPEApplication::keepRunning() const { return d->keep_running; } /*! \internal */ void QPEApplication::internalSetStyle( const QString &style ) { #if QT_VERSION >= 0x030000 if ( style == "QPE" ) { setStyle( new QPEStyle ); } else { QStyle *s = QStyleFactory::create( style ); if ( s ) setStyle( s ); } #else if ( style == "Windows" ) { setStyle( new QWindowsStyle ); } else if ( style == "QPE" ) { setStyle( new QPEStyle ); } else if ( style == "Light" ) { setStyle( new LightStyle ); } #ifndef QT_NO_STYLE_PLATINUM else if ( style == "Platinum" ) { setStyle( new QPlatinumStyle ); } #endif #ifndef QT_NO_STYLE_MOTIF else if ( style == "Motif" ) { setStyle( new QMotifStyle ); } #endif #ifndef QT_NO_STYLE_MOTIFPLUS else if ( style == "MotifPlus" ) { setStyle( new QMotifPlusStyle ); } #endif else { QStyle *sty = 0; QString path = QPEApplication::qpeDir ( ) + "plugins/styles/"; #ifdef Q_OS_MACX if ( style. find ( ".dylib" ) > 0 ) path += style; else path = path + "lib" + style. lower ( ) + ".dylib"; // compatibility #else if ( style. find ( ".so" ) > 0 ) path += style; else path = path + "lib" + style. lower ( ) + ".so"; // compatibility #endif static QLibrary *lastlib = 0; static StyleInterface *lastiface = 0; QLibrary *lib = new QLibrary ( path ); StyleInterface *iface = 0; if (( lib-> queryInterface ( IID_Style, ( QUnknownInterface ** ) &iface ) == QS_OK ) && iface ) sty = iface-> style ( ); if ( sty ) { setStyle ( sty ); if ( lastiface ) lastiface-> release ( ); lastiface = iface; if ( lastlib ) { lastlib-> unload ( ); delete lastlib; } lastlib = lib; } else { if ( iface ) iface-> release ( ); delete lib; setStyle ( new LightStyle ( )); } } #endif } /*! \internal */ void QPEApplication::prepareForTermination( bool willrestart ) { if ( willrestart ) { QLabel *lblWait = new QLabel( tr( "Please wait..." ), 0, "wait hack", QWidget::WStyle_Customize | QWidget::WStyle_NoBorder | QWidget::WStyle_Tool ); lblWait->setAlignment( QWidget::AlignCenter ); lblWait->show(); lblWait->showMaximized(); } { QCopEnvelope envelope( "QPE/System", "forceQuit()" ); } processEvents(); // ensure the message goes out. } /*! \internal */ void QPEApplication::shutdown() { // Implement in server's QPEApplication subclass } /*! \internal */ void QPEApplication::restart() { // Implement in server's QPEApplication subclass } static QPtrDict<void>* stylusDict = 0; static void createDict() { if ( !stylusDict ) stylusDict = new QPtrDict<void>; } /*! Returns the current StylusMode for widget \a w. \sa setStylusOperation() StylusMode */ QPEApplication::StylusMode QPEApplication::stylusOperation( QWidget* w ) { if ( stylusDict ) return ( StylusMode ) ( int ) stylusDict->find( w ); return LeftOnly; } /*! \enum QPEApplication::StylusMode \value LeftOnly the stylus only generates LeftButton events (the default). \value RightOnHold the stylus generates RightButton events if the user uses the press-and-hold gesture. \sa setStylusOperation() stylusOperation() */ /*! Causes widget \a w to receive mouse events according to the stylus \a mode. \sa stylusOperation() StylusMode */ void QPEApplication::setStylusOperation( QWidget * w, StylusMode mode ) { createDict(); if ( mode == LeftOnly ) { stylusDict->remove ( w ); w->removeEventFilter( qApp ); } else { stylusDict->insert( w, ( void* ) mode ); connect( w, SIGNAL( destroyed() ), qApp, SLOT( removeSenderFromStylusDict() ) ); w->installEventFilter( qApp ); } } /*! \reimp */ bool QPEApplication::eventFilter( QObject *o, QEvent *e ) { if ( !o->isWidgetType() ) return FALSE; if ( stylusDict && e->type() >= QEvent::MouseButtonPress && e->type() <= QEvent::MouseMove ) { QMouseEvent * me = ( QMouseEvent* ) e; StylusMode mode = (StylusMode)(int)stylusDict->find(o); switch (mode) { case RightOnHold: switch ( me->type() ) { case QEvent::MouseButtonPress: if ( me->button() == LeftButton ) { static long Pref = 500; // #### pref. d->presswidget = (QWidget*)o; d->presspos = me->pos(); d->rightpressed = FALSE; #ifdef OPIE_WITHROHFEEDBACK if( ! d->RoH ) d->RoH = new Opie::Internal::RoHFeedback; d->RoH->init( me->globalPos(), d->presswidget ); Pref = d->RoH->delay(); #endif if (!d->presstimer ) d->presstimer = startTimer( Pref ); // #### pref. } break; case QEvent::MouseMove: if (d->presstimer && (me->pos() - d->presspos).manhattanLength() > 8) { killTimer(d->presstimer); #ifdef OPIE_WITHROHFEEDBACK d->RoH->stop(); #endif d->presstimer = 0; } break; case QEvent::MouseButtonRelease: if ( me->button() == LeftButton ) { if ( d->presstimer ) { killTimer(d->presstimer); #ifdef OPIE_WITHROHFEEDBACK d->RoH->stop( ); #endif d->presstimer = 0; } if ( d->rightpressed && d->presswidget ) { printf( "Send ButtonRelease\n" ); // Right released postEvent( d->presswidget, new QMouseEvent( QEvent::MouseButtonRelease, me->pos(), RightButton, LeftButton + RightButton ) ); // Left released, off-widget postEvent( d->presswidget, new QMouseEvent( QEvent::MouseMove, QPoint( -1, -1), LeftButton, LeftButton ) ); postEvent( d->presswidget, new QMouseEvent( QEvent::MouseButtonRelease, QPoint( -1, -1), LeftButton, LeftButton ) ); d->rightpressed = FALSE; return TRUE; // don't send the real Left release } } break; default: break; } break; default: ; } } else if ( e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease ) { QKeyEvent *ke = (QKeyEvent *)e; if ( ke->key() == Key_Enter ) { if ( o->isA( "QRadioButton" ) || o->isA( "QCheckBox" ) ) { postEvent( o, new QKeyEvent( e->type(), Key_Space, ' ', ke->state(), " ", ke->isAutoRepeat(), ke->count() ) ); return TRUE; } } } return FALSE; } /*! \reimp */ void QPEApplication::timerEvent( QTimerEvent *e ) { if ( e->timerId() == d->presstimer && d->presswidget ) { // Right pressed postEvent( d->presswidget, new QMouseEvent( QEvent::MouseButtonPress, d->presspos, RightButton, LeftButton ) ); killTimer( d->presstimer ); d->presstimer = 0; d->rightpressed = TRUE; #ifdef OPIE_WITHROHFEEDBACK d->RoH->stop(); #endif } } void QPEApplication::removeSenderFromStylusDict() { stylusDict->remove ( ( void* ) sender() ); if ( d->presswidget == sender() ) d->presswidget = 0; } /*! \internal */ bool QPEApplication::keyboardGrabbed() const { return d->kbgrabbed; } /*! Reverses the effect of grabKeyboard(). This is called automatically on program exit. */ void QPEApplication::ungrabKeyboard() { ((QPEApplication *) qApp )-> d-> kbgrabbed = false; } /*! Grabs the physical keyboard keys, e.g. the application's launching keys. Instead of launching applications when these keys are pressed the signals emitted are sent to this application instead. Some games programs take over the launch keys in this way to make interaction easier. \sa ungrabKeyboard() */ void QPEApplication::grabKeyboard() { ((QPEApplication *) qApp )-> d-> kbgrabbed = true; } /*! \reimp */ int QPEApplication::exec() { d->qcopQok = true; #ifndef QT_NO_COP d->sendQCopQ(); if ( !d->keep_running ) processEvents(); // we may have received QCop messages in the meantime. #endif if ( d->keep_running ) //|| d->qpe_main_widget && d->qpe_main_widget->isVisible() ) return QApplication::exec(); #ifndef QT_NO_COP { QCopEnvelope e( "QPE/System", "closing(QString)" ); e << d->appName; } #endif processEvents(); return 0; } /*! \internal External request for application to quit. Quits if possible without loosing state. */ void QPEApplication::tryQuit() { if ( activeModalWidget() ) return ; // Inside modal loop or konsole. Too hard to save state. #ifndef QT_NO_COP { QCopEnvelope e( "QPE/System", "closing(QString)" ); e << d->appName; } #endif if ( d->keep_running ) d->store_widget_rect(d->qpe_main_widget, d->appName); processEvents(); quit(); } /*! \internal User initiated quit. Makes the window 'Go Away'. If preloaded this means hiding the window. If not it means quitting the application. As this is user initiated we don't need to check state. */ void QPEApplication::hideOrQuit() { if ( d->keep_running ) d->store_widget_rect(d->qpe_main_widget, d->appName); processEvents(); // If we are a preloaded application we don't actually quit, so emit // a System message indicating we're quasi-closing. if ( d->preloaded && d->qpe_main_widget ) #ifndef QT_NO_COP { QCopEnvelope e("QPE/System", "fastAppHiding(QString)" ); e << d->appName; d->qpe_main_widget->hide(); } #endif else quit(); } bool QPEApplication::isSaveWindowsPos() { return saveWindowsPos; } #if (__GNUC__ > 2 ) && !defined(_OS_MACX_) extern "C" void __cxa_pure_virtual(); void __cxa_pure_virtual() { fprintf( stderr, "Pure virtual called\n"); abort(); } #endif #if defined(OPIE_NEW_MALLOC) // The libraries with the skiff package (and possibly others) have // completely useless implementations of builtin new and delete that // use about 50% of your CPU. Here we revert to the simple libc // functions. void* operator new[]( size_t size ) { return malloc( size ); } void* operator new( size_t size ) { return malloc( size ); } void operator delete[]( void* p ) { if ( p ) free( p ); } void operator delete[]( void* p, size_t /*size*/ ) { if ( p ) free( p ); } void operator delete( void* p ) { if ( p ) free( p ); } void operator delete( void* p, size_t /*size*/ ) { if ( p ) free( p ); } #endif #if ( QT_VERSION <= 230 ) && !defined(SINGLE_APP) #include <qwidgetlist.h> #ifdef QWS #include <qgfx_qws.h> extern QRect qt_maxWindowRect; void qt_setMaxWindowRect(const QRect& r ) { qt_maxWindowRect = qt_screen->mapFromDevice( r, qt_screen->mapToDevice( QSize( qt_screen->width(), qt_screen->height() ) ) ); // Re-resize any maximized windows QWidgetList* l = QApplication::topLevelWidgets(); if ( l ) { QWidget * w = l->first(); while ( w ) { if ( w->isVisible() && w->isMaximized() ) { w->showMaximized(); } w = l->next(); } delete l; } } #endif #endif diff --git a/noncore/applets/pcmcia/pcmcia.cpp b/noncore/applets/pcmcia/pcmcia.cpp index 187adc6..c639002 100644 --- a/noncore/applets/pcmcia/pcmcia.cpp +++ b/noncore/applets/pcmcia/pcmcia.cpp @@ -1,368 +1,374 @@ /* This file is part of the Opie Project =. (C) 2005 Michael 'Mickey' Lauer <mickey@Vanille.de> .=l. .>+-= _;:, .> :=|. This program is free software; you can .> <`_, > . <= redistribute it and/or modify it under :`=1 )Y*s>-.-- : the terms of the GNU Library General Public .="- .-=="i, .._ License as published by the Free Software - . .-<_> .<> Foundation; either version 2 of the License, ._= =} : or (at your option) any later version. .%`+i> _;_. .i_,=:_. -<s. This program is distributed in the hope that + . -:. = it will be useful, but WITHOUT ANY WARRANTY; : .. .:, . . . without even the implied warranty of =_ + =;=|` MERCHANTABILITY or FITNESS FOR A _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU ..}^=.= = ; Library General Public License for more ++= -. .` .: details. : = ...= . :.=- -. .:....=;==+<; You should have received a copy of the GNU -_. . . )=. = Library General Public License along with -- :-=` this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pcmcia.h" #include "configdialog.h" #include "promptactiondialog.h" /* OPIE */ #include <opie2/odebug.h> #include <opie2/odevice.h> #include <opie2/oconfig.h> #include <opie2/oprocess.h> #include <opie2/opcmciasystem.h> #include <opie2/oresource.h> #include <opie2/otaskbarapplet.h> #include <qpe/applnk.h> #include <qpe/global.h> #include <qpe/resource.h> using namespace Opie::Core; using namespace Opie::Ui; /* QT */ #include <qcombobox.h> #include <qcopchannel_qws.h> #include <qpainter.h> #include <qfile.h> #include <qtextstream.h> #include <qmessagebox.h> #include <qsound.h> #include <qtimer.h> /* STD */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <fcntl.h> #if defined(_OS_LINUX_) || defined(Q_OS_LINUX) #include <sys/vfs.h> #include <mntent.h> #endif PcmciaManager::PcmciaManager( QWidget * parent ) : QWidget( parent ), popupMenu( 0 ) { QCopChannel * pcmciaChannel = new QCopChannel( "QPE/Card", this ); connect( pcmciaChannel, SIGNAL( received(const QCString&,const QByteArray&) ), this, SLOT( cardMessage(const QCString&,const QByteArray&) ) ); setFocusPolicy( NoFocus ); setFixedWidth ( AppLnk::smallIconSize() ); setFixedHeight ( AppLnk::smallIconSize() ); pm = Opie::Core::OResource::loadPixmap( "pcmcia", Opie::Core::OResource::SmallIcon ); configuring = false; QCopChannel *channel = new QCopChannel( "QPE/System", this ); connect( channel, SIGNAL(received(const QCString&,const QByteArray&)), this, SLOT(handleSystemChannel(const QCString&,const QByteArray&)) ); } PcmciaManager::~PcmciaManager() { } void PcmciaManager::handleSystemChannel( const QCString&msg, const QByteArray& ) { if ( msg == "returnFromSuspend()" ) { if ( !OPcmciaSystem::instance()->cardCount() ) return; OPcmciaSystem* sys = OPcmciaSystem::instance(); OPcmciaSystem::CardIterator it = sys->iterator(); while ( it.current() ) { if ( !it.current()->isEmpty() ) { executeAction( it.current(), "resume" ); } ++it; } } } void PcmciaManager::popUp( QString message, QString icon ) { if ( !popupMenu) { popupMenu = new QPopupMenu( this ); popupMenu->setFocusPolicy( QWidget::NoFocus ); } popupMenu->clear(); if ( icon.isEmpty() ) { popupMenu->insertItem( message, 0 ); } else { popupMenu->insertItem( QIconSet( Opie::Core::OResource::loadPixmap( icon, Opie::Core::OResource::SmallIcon ) ), message, 0 ); } QPoint p = mapToGlobal( QPoint( 0, 0 ) ); QSize s = popupMenu->sizeHint(); popupMenu->popup( QPoint( p.x() + ( width() / 2 ) - ( s.width() / 2 ), p.y() - s.height() ), 0 ); QTimer::singleShot( 2000, this, SLOT( popupTimeout() ) ); } void PcmciaManager::popupTimeout() { popupMenu->hide(); } enum { EJECT, INSERT, SUSPEND, RESUME, RESET, CONFIGURE, ACTIVATE }; static const char* actionText[] = { "eject", "insert", "suspend", "resum", "resett", "configur", "activat" }; void PcmciaManager::mousePressEvent( QMouseEvent* ) { QPopupMenu* menu = new QPopupMenu( this ); QStringList cmd; bool execute = true; OPcmciaSystem* sys = OPcmciaSystem::instance(); sys->synchronize(); OPcmciaSystem::CardIterator it = sys->iterator(); if ( !sys->count() ) return; int i = 0; while ( it.current() ) { QPopupMenu* submenu = new QPopupMenu( menu ); submenu->insertItem( "&Eject", EJECT+i*100 ); submenu->insertItem( "&Insert", INSERT+i*100 ); submenu->insertItem( "&Suspend", SUSPEND+i*100 ); submenu->insertItem( "&Resume", RESUME+i*100 ); submenu->insertItem( "Rese&t", RESET+i*100 ); submenu->insertItem( "&Configure", CONFIGURE+i*100 ); bool isSuspended = it.current()->isSuspended(); bool isEmpty = it.current()->isEmpty(); submenu->setItemEnabled( EJECT+i*100, !isEmpty ); submenu->setItemEnabled( INSERT+i*100, isEmpty ); submenu->setItemEnabled( SUSPEND+i*100, !isEmpty && !isSuspended ); submenu->setItemEnabled( RESUME+i*100, !isEmpty && isSuspended ); submenu->setItemEnabled( RESET+i*100, !isEmpty && !isSuspended ); submenu->setItemEnabled( CONFIGURE+i*100, !isEmpty && !configuring ); connect( submenu, SIGNAL(activated(int)), this, SLOT(userCardAction(int)) ); menu->insertItem( tr( "%1: %2" ).arg( i++ ).arg( it.current()->identity() ), submenu, 1 ); ++it; } QPoint p = mapToGlobal( QPoint( 0, 0 ) ); QSize s = menu->sizeHint(); int opt = menu->exec( QPoint( p.x() + ( width() / 2 ) - ( s.width() / 2 ), p.y() - s.height() ), 0 ); qDebug( "pcmcia: menu result = %d", opt ); delete menu; } void PcmciaManager::cardMessage( const QCString & msg, const QByteArray & ) { odebug << "PcmciaManager::cardMessage( '" << msg << "' )" << oendl; if ( msg != "stabChanged()" ) return; /* check if a previously unknown card has been inserted */ OPcmciaSystem::instance()->synchronize(); if ( !OPcmciaSystem::instance()->cardCount() ) return; OConfig cfg( "PCMCIA" ); cfg.setGroup( "Global" ); int nCards = cfg.readNumEntry( "nCards", 0 ); OPcmciaSystem* sys = OPcmciaSystem::instance(); OPcmciaSystem::CardIterator it = sys->iterator(); bool newCard = true; OPcmciaSocket* theCard = 0; while ( it.current() && newCard ) { if ( it.current()->isEmpty() ) { odebug << "pcmcia: skipping empty card in socket " << it.current()->number() << oendl; ++it; continue; } else { theCard = it.current(); QString cardName = theCard->productIdentity(); for ( int i = 0; i < nCards; ++i ) { QString cardSection = QString( "Card_%1" ).arg( i ); cfg.setGroup( cardSection ); QString name = cfg.readEntry( "name" ); odebug << "pcmcia: comparing card '" << cardName << "' with known card '" << name << "'" << oendl; if ( cardName == name ) { newCard = false; odebug << "pcmcia: we have seen this card before" << oendl; executeAction( theCard, "insert" ); break; } } if ( !newCard ) ++it; else break; } } + + if ( !theCard ) { + owarn << "pcmcia: Finished working through cards in PCMCIA system but I do not have a valid card handle" << oendl; + return; + } + if ( newCard ) { odebug << "pcmcia: unconfigured card detected" << oendl; QString newCardName = theCard->productIdentity(); int result = QMessageBox::information( qApp->desktop(), tr( "PCMCIA/CF Subsystem" ), tr( "<qt>You have inserted the card<br/><b>%1</b><br/>This card is not yet configured. Do you want to configure it now?</qt>" ).arg( newCardName ), tr( "Yes" ), tr( "No" ), 0, 0, 1 ); odebug << "pcmcia: result = " << result << oendl; if ( result == 0 ) { configure( theCard ); } else { odebug << "pcmcia: user doesn't want to configure " << newCardName << " now." << oendl; } } else // it's an already configured card { odebug << "pcmcia: doing nothing... why do we come here?" << oendl; } } void PcmciaManager::paintEvent( QPaintEvent * ) { QPainter p( this ); p.drawPixmap( 0, 0, pm ); } int PcmciaManager::position() { return 7; } void PcmciaManager::execCommand( const QStringList &strList ) { } void PcmciaManager::userCardAction( int action ) { odebug << "pcmcia: user action on socket " << action / 100 << " requested. action = " << action << oendl; int socket = action / 100; int what = action % 100; bool success = false; switch ( what ) { case CONFIGURE: { QString insertAction; QString resumeAction; QString driver; QString conf; configure( OPcmciaSystem::instance()->socket( socket ) ); return; } case EJECT: success = OPcmciaSystem::instance()->socket( socket )->eject(); break; case INSERT: success = OPcmciaSystem::instance()->socket( socket )->insert(); break; case SUSPEND: success = OPcmciaSystem::instance()->socket( socket )->suspend(); break; case RESUME: success = OPcmciaSystem::instance()->socket( socket )->resume(); break; case RESET: success = OPcmciaSystem::instance()->socket( socket )->reset(); break; case ACTIVATE: success = true; break; default: odebug << "pcmcia: not yet implemented" << oendl; } if ( success ) { odebug << tr( "Successfully %1ed card in socket #%2" ).arg( actionText[action] ).arg( socket ) << oendl; popUp( tr( "Successfully %1ed card in socket #%2" ).arg( actionText[action] ).arg( socket ) ); } else { odebug << tr( "Error while %1ing card in socket #%2" ).arg( actionText[action] ).arg( socket ) << oendl; popUp( tr( "Error while %1ing card in socket #%2" ).arg( actionText[action] ).arg( socket ) ); } } void PcmciaManager::configure( OPcmciaSocket* card ) { configuring = true; ConfigDialog dialog( card, qApp->desktop() ); int result = QPEApplication::execDialog( &dialog, false ); configuring = false; odebug << "pcmcia: configresult = " << result << oendl; if ( result ) { dialog.writeConfiguration( card ); } } void PcmciaManager::executeAction( Opie::Core::OPcmciaSocket* card, const QString& type ) { odebug << "pcmcia: performing " << type << " action ..." << oendl; QString theAction = ConfigDialog::preferredAction( card, type ); int intAction = card->number() * 100; if ( theAction == "prompt for" ) { PromptActionDialog dialog( qApp->desktop(), "promptfor", true ); dialog.setCaption( QString( "Choose action for card #%1" ).arg( card->number() ) ); int result = QPEApplication::execDialog( &dialog, true ); odebug << "pcmcia: configresult = " << result << oendl; if ( result ) { theAction = dialog.cbAction->currentText(); } else { odebug << "pcmcia: prompted to do nothing" << oendl; return; } } if ( theAction == "activate" ) intAction += ACTIVATE; else if ( theAction == "eject" ) intAction += EJECT; else if ( theAction == "suspend" ) intAction += SUSPEND; else { owarn << "pcmcia: action '" << theAction << "' not known. Huh?" << oendl; return; } userCardAction( intAction ); } EXPORT_OPIE_APPLET_v1( PcmciaManager ) diff --git a/noncore/apps/checkbook/mainwindow.cpp b/noncore/apps/checkbook/mainwindow.cpp index d9e2047..8e2e2e3 100644 --- a/noncore/apps/checkbook/mainwindow.cpp +++ b/noncore/apps/checkbook/mainwindow.cpp @@ -1,363 +1,362 @@ /* This file is part of the OPIE Project =. .=l. Copyright (c) 2002 Dan Williams <drw@handhelds.org> .>+-= _;:, .> :=|. This file is free software; you can .> <`_, > . <= redistribute it and/or modify it under :`=1 )Y*s>-.-- : the terms of the GNU General Public .="- .-=="i, .._ License as published by the Free Software - . .-<_> .<> Foundation; either version 2 of the License, ._= =} : or (at your option) any later version. .%`+i> _;_. .i_,=:_. -<s. This file is distributed in the hope that + . -:. = it will be useful, but WITHOUT ANY WARRANTY; : .. .:, . . . without even the implied warranty of =_ + =;=|` MERCHANTABILITY or FITNESS FOR A _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU General ..}^=.= = ; Public License for more details. ++= -. .` .: : = ...= . :.=- You should have received a copy of the GNU -. .:....=;==+<; General Public License along with this file; -_. . . )=. = see the file COPYING. If not, write to the -- :-=` Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "mainwindow.h" #include "cbinfo.h" #include "configuration.h" #include "password.h" #include "checkbook.h" #include <opie2/oresource.h> #include <qpe/config.h> #include <qpe/qpeapplication.h> #include <qpe/qpemessagebox.h> #include <qaction.h> #include <qdir.h> #include <qmenubar.h> #include <qtoolbar.h> #include <qwhatsthis.h> MainWindow::MainWindow( QWidget* parent, const char* name, WFlags /*fl*/ ) : QMainWindow( parent, name, WStyle_ContextHelp ) { setCaption( tr( "Checkbook" ) ); cbDir = Global::applicationFileName( "checkbook", "" ); lockIcon = Opie::Core::OResource::loadPixmap( "locked", Opie::Core::OResource::SmallIcon ); // Load configuration options Config config( "checkbook" ); _cfg.readConfig( config ); // Build menu and tool bars setToolBarsMovable( FALSE ); QToolBar *bar = new QToolBar( this ); bar->setHorizontalStretchable( TRUE ); QMenuBar *mb = new QMenuBar( bar ); mb->setMargin( 0 ); QPopupMenu *popup = new QPopupMenu( this ); bar = new QToolBar( this ); QAction *a = new QAction( tr( "New" ), Opie::Core::OResource::loadPixmap( "new", Opie::Core::OResource::SmallIcon ), QString::null, 0, this, 0 ); a->setWhatsThis( tr( "Click here to create a new checkbook.\n\nYou also can select New from the Checkbook menu." ) ); connect( a, SIGNAL( activated() ), this, SLOT( slotNew() ) ); a->addTo( popup ); a->addTo( bar ); actionOpen = new QAction( tr( "Edit" ), Opie::Core::OResource::loadPixmap( "edit", Opie::Core::OResource::SmallIcon ), QString::null, 0, this, 0 ); actionOpen->setWhatsThis( tr( "Select a checkbook and then click here to edit it.\n\nYou also can select Edit from the Checkbook menu, or click and hold on a checkbook name." ) ); connect( actionOpen, SIGNAL( activated() ), this, SLOT( slotEdit() ) ); actionOpen->addTo( popup ); actionOpen->addTo( bar ); actionDelete = new QAction( tr( "Delete" ), Opie::Core::OResource::loadPixmap( "trash", Opie::Core::OResource::SmallIcon ), QString::null, 0, this, 0 ); actionDelete->setWhatsThis( tr( "Select a checkbook and then click here delete it.\n\nYou also can select Delete from the Checkbook menu." ) ); connect( actionDelete, SIGNAL( activated() ), this, SLOT( slotDelete() ) ); actionDelete->addTo( popup ); actionDelete->addTo( bar ); popup->insertSeparator(); a = new QAction( tr( "Configure" ), Opie::Core::OResource::loadPixmap( "SettingsIcon", Opie::Core::OResource::SmallIcon ), QString::null, 0, this, 0 ); a->setWhatsThis( tr( "Click here to configure this app." ) ); connect( a, SIGNAL( activated() ), this, SLOT( slotConfigure() ) ); a->addTo( popup ); a->addTo( bar ); mb->insertItem( tr( "Checkbook" ), popup ); // Load Checkbook selection list checkbooks = new CBInfoList(); QDir checkdir( cbDir ); if (checkdir.exists() == true) { QStringList cblist = checkdir.entryList( "*.qcb", QDir::Files|QDir::Readable|QDir::Writable, QDir::Time ); CBInfo *cb = 0x0; QString filename; for ( QStringList::Iterator it = cblist.begin(); it != cblist.end(); it++ ) { filename = cbDir; filename.append( (*it) ); cb = new CBInfo( (*it).remove( (*it).find('.'), (*it).length() ), filename ); checkbooks->inSort( cb ); } } // Build Checkbook selection list control cbList = 0x0; buildList(); // open last book? if( _cfg.isOpenLastBook() ) { this->show(); this->showMaximized(); QListViewItem *itm=cbList->firstChild(); while( itm ) { if( itm->text(posName)==_cfg.getLastBook() ) { openBook( itm ); break; } itm=itm->nextSibling(); } } } // --- ~MainWindow ------------------------------------------------------------ MainWindow::~MainWindow() { writeConfig(); } // --- buildList -------------------------------------------------------------- void MainWindow::buildList() { if ( cbList ) delete cbList; cbList = new QListView( this ); QWhatsThis::add( cbList, tr( "This is a listing of all checkbooks currently available." ) ); if ( _cfg.getShowLocks() ) { cbList->addColumn( lockIcon, "", 24 ); posName = 1; } else { posName = 0; } cbList->addColumn( tr( "Checkbook Name" ) ); if ( _cfg.getShowBalances() ) { int colnum = cbList->addColumn( tr( "Balance" ) ); cbList->setColumnAlignment( colnum, Qt::AlignRight ); } cbList->setAllColumnsShowFocus( TRUE ); cbList->setSorting( posName ); QPEApplication::setStylusOperation( cbList->viewport(), QPEApplication::RightOnHold ); connect( cbList, SIGNAL( rightButtonPressed(QListViewItem*,const QPoint&,int) ), this, SLOT( slotEdit() ) ); setCentralWidget( cbList ); for ( CBInfo *cb = checkbooks->first(); cb; cb = checkbooks->next() ) { addCheckbook( cb ); } } void MainWindow::addCheckbook( CBInfo *cb ) { QListViewItem *lvi = new QListViewItem( cbList ); if ( _cfg.getShowLocks() && !cb->password().isNull() ) { lvi->setPixmap( 0, lockIcon ); } lvi->setText( posName, cb->name() ); if ( _cfg.getShowBalances() ) { QString balance; balance.sprintf( "%.2f", cb->balance() ); balance.prepend( _cfg.getCurrencySymbol() ); lvi->setText( posName + 1, balance ); } } void MainWindow::buildFilename( const QString &name ) { tempFilename = cbDir; tempFilename.append( name ); tempFilename.append( ".qcb" ); } void MainWindow::slotNew() { CBInfo *cb = new CBInfo(); Checkbook *currcb = new Checkbook( this, cb, &_cfg ); if ( QPEApplication::execDialog( currcb ) == QDialog::Accepted ) { // Save new checkbook buildFilename( cb->name() ); _cfg.setLastBook( cb->name() ); cb->setFilename( tempFilename ); cb->write(); // Add to listbox checkbooks->inSort( cb ); addCheckbook( cb ); } delete currcb; } // --- slotEdit --------------------------------------------------------------- void MainWindow::slotEdit() { // get name and open it QListViewItem *curritem = cbList->currentItem(); if ( !curritem ) return; openBook( curritem ); } // --- openBook --------------------------------------------------------------- void MainWindow::openBook(QListViewItem *curritem) { + if ( !curritem ) return; // find book in List QString currname=curritem->text(posName); CBInfo *cb = checkbooks->first(); while ( cb ) { if ( cb->name() == currname ) break; cb = checkbooks->next(); } if ( !cb ) return; // buildFilename( currname ); float currbalance = cb->balance(); bool currlock = !cb->password().isNull(); if ( currlock ) { Password *pw = new Password( this, tr( "Enter password" ), tr( "Please enter your password:" ) ); if ( pw->exec() != QDialog::Accepted || pw->password != cb->password() ) { delete pw; return; } delete pw; } _cfg.setLastBook( currname ); Checkbook *currcb = new Checkbook( this, cb, &_cfg ); if ( QPEApplication::execDialog( currcb ) == QDialog::Accepted ) { QString newname = cb->name(); if ( currname != newname ) { // Update name if changed - if( curritem ) { curritem->setText( posName, newname ); cbList->sort(); - } _cfg.setLastBook( newname ); // Remove old file QFile f( tempFilename ); if ( f.exists() ) f.remove(); // Get new filename buildFilename( newname ); cb->setFilename( tempFilename ); } cb->write(); // Update lock if changed if ( _cfg.getShowLocks() && !cb->password().isNull() != currlock ) { if ( !cb->password().isNull() ) curritem->setPixmap( 0, lockIcon ); else curritem->setPixmap( 0, nullIcon ); } // Update balance if changed if ( _cfg.getShowBalances() && cb->balance() != currbalance ) { QString tempstr; tempstr.sprintf( "%.2f", cb->balance() ); tempstr.prepend( _cfg.getCurrencySymbol() ); curritem->setText( posName + 1, tempstr ); } // write config, if needed if( _cfg.isDirty() ) { Config config("checkbook"); _cfg.writeConfig( config ); } } delete currcb; } // --- slotDelete ------------------------------------------------------------- void MainWindow::slotDelete() { QString currname = cbList->currentItem()->text( posName ); if ( QPEMessageBox::confirmDelete ( this, tr( "Delete checkbook" ), currname ) ) { buildFilename( currname ); QFile f( tempFilename ); if ( f.exists() ) { f.remove(); } delete cbList->currentItem(); } } // --- slotConfigure ---------------------------------------------------------- void MainWindow::slotConfigure() { Configuration *cfgdlg = new Configuration( this, _cfg ); if ( QPEApplication::execDialog( cfgdlg ) == QDialog::Accepted ) { // read data from config dialog & save it cfgdlg->saveConfig( _cfg ); writeConfig(); buildList(); } delete cfgdlg; } // --- writeConfig -------------------------------------------------------------- void MainWindow::writeConfig() { Config config("checkbook"); _cfg.writeConfig( config ); } diff --git a/noncore/apps/opie-console/procctl.cpp b/noncore/apps/opie-console/procctl.cpp index a44529b..5239e26 100644 --- a/noncore/apps/opie-console/procctl.cpp +++ b/noncore/apps/opie-console/procctl.cpp @@ -1,97 +1,100 @@ #include <sys/wait.h> #include <fcntl.h> #include <unistd.h> #include "procctl.h" ProcContainer *ProcCtl::m_last = 0; ProcCtl* ProcCtl::m_self = 0; ProcCtl::ProcCtl() { signal( SIGCHLD, signal_handler ); } ProcCtl::~ProcCtl() { } ProcCtl* ProcCtl::self() { if (!m_self ) { m_self = new ProcCtl; } return m_self; } void ProcCtl::add(pid_t pi, int fd ) { ProcContainer * con = new ProcContainer; //memset(con, 0, sizeof(con) ); con->pid = pi; con->fd = fd; con->status = 0; con->prev = m_last; m_last = con; } void ProcCtl::remove( pid_t pi ) { /* * We first check if the last item * is equal to pi the we * */ ProcContainer* con; if (m_last->pid == pi ) { con = m_last; m_last = con->prev; delete con; return; } con = m_last; ProcContainer* forw = 0l; while (con ) { /* remove it */ if ( pi == con->pid ) { + if (forw) forw->prev = con->prev; + else + forw = con->prev; delete con; return; } forw = con; con = con->prev; } } void ProcCtl::remove( ProcContainer con ) { remove( con.pid ); } int ProcCtl::status(pid_t pid )const{ ProcContainer *con = m_last; while (con) { if (con->pid == pid ) return con->status; con = con->prev; } return -1; } void ProcCtl::signal_handler(int) { int status; signal( SIGCHLD, signal_handler ); pid_t pi = waitpid( -1, &status, WNOHANG ); /* * find the container for pid * */ if ( pi < 0 ) { return; } ProcContainer* con = m_last; while (con) { if ( con->pid == pi ) { con->status = status; char result = 1; /* give a 'signal' */ ::write(con->fd, &result, 1 ); } con = con->prev; } } diff --git a/noncore/apps/tinykate/libkate/document/katedocument.cpp b/noncore/apps/tinykate/libkate/document/katedocument.cpp index b82a86a..692fd46 100644 --- a/noncore/apps/tinykate/libkate/document/katedocument.cpp +++ b/noncore/apps/tinykate/libkate/document/katedocument.cpp @@ -1,3180 +1,3181 @@ /*************************************************************************** katedocument.cpp - description ------------------- begin : Mon Jan 15 2001 copyright : (C) 2001 by Christoph "Crossfire" Cullmann (C) 2002 by Joseph Wenninger email : crossfire@babylon2k.de jowenn@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /* Copyright (C) 1998, 1999 Jochen Wilhelmy digisnap@cs.tu-berlin.de This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "katedocument.h" #include "kmessagebox.h" #include "kglobal.h" //#include "kcharsets.h" #include "kdebug.h" //#include "kinstance.h" #include "kglobalsettings.h" //#include "kaction.h" //#include "kstdaction.h" #include "../view/kateview.h" #include "katebuffer.h" #include "katetextline.h" #include "katecmd.h" /* OPIE */ #include <opie2/odebug.h> #include <qpe/config.h> /* QT */ #include <qfileinfo.h> #include <qdatetime.h> #include <qstring.h> #include <qtimer.h> #include <qobject.h> #include <qapplication.h> #include <qclipboard.h> #include <qfont.h> #include <qpainter.h> #include <qfile.h> #include <qtextstream.h> #include <qtextcodec.h> /* STD */ #include <sys/time.h> #include <unistd.h> #include <stdio.h> KateAction::KateAction(Action a, PointStruc &cursor, int len, const QString &text) : action(a), cursor(cursor), len(len), text(text) { } KateActionGroup::KateActionGroup(PointStruc &aStart, int type) : start(aStart), action(0L), undoType(type) { } KateActionGroup::~KateActionGroup() { KateAction *current, *next; current = action; while (current) { next = current->next; delete current; current = next; } } void KateActionGroup::insertAction(KateAction *a) { a->next = action; action = a; } const char * KateActionGroup::typeName(int type) { // return a short text description of the given undo group type suitable for a menu // not the lack of i18n's, the caller is expected to handle translation switch (type) { case ugPaste : return "Paste Text"; case ugDelBlock : return "Selection Overwrite"; case ugIndent : return "Indent"; case ugUnindent : return "Unindent"; case ugComment : return "Comment"; case ugUncomment : return "Uncomment"; case ugReplace : return "Text Replace"; case ugSpell : return "Spell Check"; case ugInsChar : return "Typing"; case ugDelChar : return "Delete Text"; case ugInsLine : return "New Line"; case ugDelLine : return "Delete Line"; } return ""; } const int KateDocument::maxAttribs = 32; QStringList KateDocument::searchForList = QStringList(); QStringList KateDocument::replaceWithList = QStringList(); uint KateDocument::uniqueID = 0; QPtrDict<KateDocument::KateDocPrivate>* KateDocument::d_ptr = 0; KateDocument::KateDocument(bool bSingleViewMode, bool bBrowserView, QWidget *parentWidget, const char *widgetName, QObject *, const char *) : Kate::Document (), myFont(KGlobalSettings::generalFont()), myFontBold(KGlobalSettings::generalFont()), myFontItalic(KGlobalSettings::generalFont()), myFontBI(KGlobalSettings::generalFont()), myFontMetrics (myFont), myFontMetricsBold (myFontBold), myFontMetricsItalic (myFontItalic), myFontMetricsBI (myFontBI), hlManager(HlManager::self ()) { d(this)->hlSetByUser = false; PreHighlightedTill=0; RequestPreHighlightTill=0; m_bSingleViewMode=bSingleViewMode; m_bBrowserView = bBrowserView; m_url = QString::null; // NOTE: QFont::CharSet doesn't provide all the charsets KDE supports // (esp. it doesn't distinguish between UTF-8 and iso10646-1) myEncoding = QString::fromLatin1(QTextCodec::codecForLocale()->name()); maxLength = -1; setFont (KGlobalSettings::generalFont()); myDocID = uniqueID; uniqueID++; myDocName = QString (""); fileInfo = new QFileInfo (); myCmd = new KateCmd (this); connect(this,SIGNAL(modifiedChanged()),this,SLOT(slotModChanged())); buffer = new KWBuffer; connect(buffer, SIGNAL(linesChanged(int)), this, SLOT(slotBufferChanged())); // connect(buffer, SIGNAL(textChanged()), this, SIGNAL(textChanged())); connect(buffer, SIGNAL(needHighlight(long,long)),this,SLOT(slotBufferHighlight(long,long))); colors[0] = KGlobalSettings::baseColor(); colors[1] = KGlobalSettings::highlightColor(); m_attribs = new Attribute[maxAttribs]; m_highlight = 0L; tabChars = 8; m_singleSelection = false; newDocGeometry = false; readOnly = false; newDoc = false; modified = false; undoList.setAutoDelete(true); undoState = 0; undoSteps = 50; pseudoModal = 0L; clear(); setHighlight(0); //calls updateFontData() // if the user changes the highlight with the dialog, notify the doc connect(hlManager,SIGNAL(changed()),SLOT(hlChanged())); newDocGeometry = false; readConfig(); setReadOnly(false); } void KateDocument::setDontChangeHlOnSave() { d(this)->hlSetByUser = true; } void KateDocument::setFont (QFont font) { kdDebug()<<"Kate:: setFont"<<endl; int oldwidth=myFontMetrics.width('W'); //Quick & Dirty Hack (by JoWenn) //Remove in KDE 3.0 myFont = font; myFontBold = QFont (font); myFontBold.setBold (true); myFontItalic = QFont (font); myFontItalic.setItalic (true); myFontBI = QFont (font); myFontBI.setBold (true); myFontBI.setItalic (true); myFontMetrics = CachedFontMetrics (myFont); myFontMetricsBold = CachedFontMetrics (myFontBold); myFontMetricsItalic = CachedFontMetrics (myFontItalic); myFontMetricsBI = CachedFontMetrics (myFontBI); int newwidth=myFontMetrics.width('W'); //Quick & Dirty Hack (by JoWenn) //Remove in KDE 3.0 maxLength=maxLength*(float)newwidth/(float)oldwidth; //Quick & Dirty Hack (by JoWenn) //Remove in KDE 3.0 updateFontData(); updateViews(); //Quick & Dirty Hack (by JoWenn) //Remove in KDE 3.0 } long KateDocument::needPreHighlight(long till) { int max=numLines()-1; if (till>max) { till=max; } if (PreHighlightedTill>=till) return -1; long tmp=RequestPreHighlightTill; if (RequestPreHighlightTill<till) { RequestPreHighlightTill=till; if (tmp<=PreHighlightedTill) QTimer::singleShot(10,this,SLOT(doPreHighlight())); } return RequestPreHighlightTill; } void KateDocument::doPreHighlight() { int from = PreHighlightedTill; int till = PreHighlightedTill+200; int max = numLines()-1; if (till > max) { till = max; } PreHighlightedTill = till; updateLines(from,till); emit preHighlightChanged(PreHighlightedTill); if (PreHighlightedTill<RequestPreHighlightTill) QTimer::singleShot(10,this,SLOT(doPreHighlight())); } KateDocument::~KateDocument() { m_highlight->release(); writeConfig(); if ( !m_bSingleViewMode ) { m_views.setAutoDelete( true ); m_views.clear(); m_views.setAutoDelete( false ); } delete_d(this); } void KateDocument::openURL(const QString &filename) { m_file=filename; fileInfo->setFile (m_file); setMTime(); if (!fileInfo->exists() || !fileInfo->isReadable()) { odebug << "File doesn't exit or couldn't be read" << oendl; return ; } buffer->clear(); #warning fixme // buffer->insertFile(0, m_file, KGlobal::charsets()->codecForName(myEncoding)); odebug << "Telling buffer to open file" << oendl; buffer->insertFile(0, m_file, QTextCodec::codecForLocale()); setMTime(); if (myWordWrap) wrapText (myWordWrapAt); int hl = hlManager->wildcardFind( m_file ); setHighlight(hl); updateLines(); updateViews(); emit fileNameChanged(); return ; } bool KateDocument::saveFile() { QFile f( m_file ); if ( !f.open( IO_WriteOnly ) ) return false; // Error QTextStream stream(&f); stream.setEncoding(QTextStream::RawUnicode); // disable Unicode headers #warning fixme // stream.setCodec(KGlobal::charsets()->codecForName(myEncoding)); stream.setCodec(QTextCodec::codecForLocale()); // this line sets the mapper to the correct codec int maxLine = numLines(); int line = 0; while(true) { stream << getTextLine(line)->getString(); line++; if (line >= maxLine) break; if (eolMode == KateDocument::eolUnix) stream << "\n"; else if (eolMode == KateDocument::eolDos) stream << "\r\n"; else if (eolMode == KateDocument::eolMacintosh) stream << '\r'; }; f.close(); fileInfo->setFile (m_file); setMTime(); if (!(d(this)->hlSetByUser)) { int hl = hlManager->wildcardFind( m_file ); setHighlight(hl); } emit fileNameChanged (); if(f.status() == IO_Ok) { setModified(false); return true; } else return false; } KTextEditor::View *KateDocument::createView( QWidget *parent, const char *name ) { return new KateView( this, parent, name); } QString KateDocument::textLine( int line ) const { TextLine::Ptr l = getTextLine( line ); if ( !l ) return QString(); return l->getString(); } void KateDocument::replaceLine(const QString& s,int line) { remove_Line(line,false); insert_Line(s,line,true); } void KateDocument::insertLine( const QString &str, int l ) { insert_Line(str,l,true); } void KateDocument::insert_Line(const QString& s,int line, bool update) { kdDebug(13020)<<"KateDocument::insertLine "<<s<<QString(" %1").arg(line)<<endl; TextLine::Ptr TL=new TextLine(); TL->append(s.unicode(),s.length()); buffer->insertLine(line,TL); if (update) { newDocGeometry=true; updateLines(line); updateViews(); } } void KateDocument::insertAt( const QString &s, int line, int col, bool ) { VConfig c; c.view = 0; // ### FIXME c.cursor.x = col; c.cursor.y = line; c.cXPos = 0; // ### FIXME c.flags = 0; // ### FIXME insert( c, s ); } void KateDocument::removeLine( int line ) { remove_Line(line,true); } void KateDocument::remove_Line(int line,bool update) { kdDebug(13020)<<"KateDocument::removeLine "<<QString("%1").arg(line)<<endl; buffer->removeLine(line); // newDocGeometry=true; // if line==0) if (update) { updateLines(line); updateViews(); } } int KateDocument::length() const { return text().length(); } void KateDocument::setSelection( int , int , int , int ) { } bool KateDocument::hasSelection() const { return (selectEnd >= selectStart); } QString KateDocument::selection() const { uint flags = 0; TextLine::Ptr textLine; int len, z, start, end, i; len = 1; if (!(flags & KateView::cfVerticalSelect)) { for (z = selectStart; z <= selectEnd; z++) { textLine = getTextLine(z); len += textLine->numSelected(); if (textLine->isSelected()) len++; } QString s; len = 0; for (z = selectStart; z <= selectEnd; z++) { textLine = getTextLine(z); end = 0; do { start = textLine->findUnselected(end); end = textLine->findSelected(start); for (i = start; i < end; i++) { s[len] = textLine->getChar(i); len++; } } while (start < end); if (textLine->isSelected()) { s[len] = '\n'; len++; } } // s[len] = '\0'; return s; } else { for (z = selectStart; z <= selectEnd; z++) { textLine = getTextLine(z); len += textLine->numSelected() + 1; } QString s; len = 0; for (z = selectStart; z <= selectEnd; z++) { textLine = getTextLine(z); end = 0; do { start = textLine->findUnselected(end); end = textLine->findSelected(start); for (i = start; i < end; i++) { s[len] = textLine->getChar(i); len++; } } while (start < end); s[len] = '\n'; len++; } // s[len] = '\0'; // the final \0 is not counted in length() return s; } } int KateDocument::numLines() const { return buffer->count(); } TextLine::Ptr KateDocument::getTextLine(int line) const { // This is a hack to get this stuff working. return buffer->line(line); } int KateDocument::textLength(int line) { TextLine::Ptr textLine = getTextLine(line); if (!textLine) return 0; return textLine->length(); } void KateDocument::setTabWidth(int chars) { if (tabChars == chars) return; if (chars < 1) chars = 1; if (chars > 16) chars = 16; tabChars = chars; updateFontData(); maxLength = -1; for (int i=0; i < buffer->count(); i++) { TextLine::Ptr textLine = buffer->line(i); int len = textWidth(textLine,textLine->length()); if (len > maxLength) { maxLength = len; longestLine = textLine; } } } void KateDocument::setReadOnly(bool m) { KTextEditor::View *view; if (m != readOnly) { readOnly = m; // if (readOnly) recordReset(); for (view = m_views.first(); view != 0L; view = m_views.next() ) { emit static_cast<KateView *>( view )->newStatus(); } } } bool KateDocument::isReadOnly() const { return readOnly; } void KateDocument::setNewDoc( bool m ) { // KTextEditor::View *view; if ( m != newDoc ) { newDoc = m; //// if (readOnly) recordReset(); // for (view = m_views.first(); view != 0L; view = m_views.next() ) { // emit static_cast<KateView *>( view )->newStatus(); // } } } bool KateDocument::isNewDoc() const { return newDoc; } void KateDocument::setModified(bool m) { KTextEditor::View *view; if (m != modified) { modified = m; for (view = m_views.first(); view != 0L; view = m_views.next() ) { emit static_cast<KateView *>( view )->newStatus(); } emit modifiedChanged (); } } bool KateDocument::isModified() const { return modified; } void KateDocument::readConfig() { KateConfig *config = KGlobal::config(); config->setGroup("Kate Document"); myWordWrap = config->readBoolEntry("Word Wrap On", false); myWordWrapAt = config->readNumEntry("Word Wrap At", 80); if (myWordWrap) wrapText (myWordWrapAt); setTabWidth(config->readNumEntry("TabWidth", 8)); setUndoSteps(config->readNumEntry("UndoSteps", 50)); m_singleSelection = config->readBoolEntry("SingleSelection", false); myEncoding = config->readEntry("Encoding", QString::fromLatin1(QTextCodec::codecForLocale()->name())); setFont (config->readFontEntry("Font", myFont)); colors[0] = config->readColorEntry("Color Background", colors[0]); colors[1] = config->readColorEntry("Color Selected", colors[1]); // config->sync(); } void KateDocument::writeConfig() { KateConfig *config = KGlobal::config(); config->setGroup("Kate Document"); config->writeEntry("Word Wrap On", myWordWrap); config->writeEntry("Word Wrap At", myWordWrapAt); config->writeEntry("TabWidth", tabChars); config->writeEntry("UndoSteps", undoSteps); config->writeEntry("SingleSelection", m_singleSelection); config->writeEntry("Encoding", myEncoding); config->writeEntry("Font", myFont); config->writeEntry("Color Background", colors[0]); config->writeEntry("Color Selected", colors[1]); // config->sync(); } void KateDocument::readSessionConfig(KateConfig *config) { m_url = config->readEntry("URL"); // ### doesn't this break the encoding? (Simon) setHighlight(hlManager->nameFind(config->readEntry("Highlight"))); // anders: restore bookmarks if possible QValueList<int> l = config->readIntListEntry("Bookmarks"); if ( l.count() ) { for (uint i=0; i < l.count(); i++) { if ( numLines() < l[i] ) break; getTextLine( l[i] )->addMark( Bookmark ); } } } void KateDocument::writeSessionConfig(KateConfig *config) { #if 0 config->writeEntry("URL", m_url); // ### encoding?? (Simon) config->writeEntry("Highlight", m_highlight->name()); // anders: save bookmarks QList<Kate::Mark> l = marks(); QValueList<int> ml; for (uint i=0; i < l.count(); i++) { if ( l.at(i)->type == 1) // only save bookmarks ml << l.at(i)->line; } if ( ml.count() ) config->writeEntry("Bookmarks", ml); #endif } void KateDocument::setHighlight(int n) { Highlight *h; // hlNumber = n; h = hlManager->getHl(n); if (h == m_highlight) { updateLines(); } else { if (m_highlight != 0L) m_highlight->release(); h->use(); m_highlight = h; makeAttribs(); } PreHighlightedTill=0; RequestPreHighlightTill=0; emit(highlightChanged()); } void KateDocument::makeAttribs() { odebug << "KateDocument::makeAttribs()" << oendl; m_numAttribs = hlManager->makeAttribs(m_highlight, m_attribs, maxAttribs); updateFontData(); updateLines(); } void KateDocument::updateFontData() { int maxAscent, maxDescent; int tabWidth; KateView *view; maxAscent = myFontMetrics.ascent(); maxDescent = myFontMetrics.descent(); tabWidth = myFontMetrics.width(' '); fontHeight = maxAscent + maxDescent + 1; fontAscent = maxAscent; m_tabWidth = tabChars*tabWidth; for (view = views.first(); view != 0L; view = views.next() ) { view->myViewInternal->drawBuffer->resize(view->width(),fontHeight); view->tagAll(); view->updateCursor(); } } void KateDocument::hlChanged() { //slot makeAttribs(); updateViews(); } void KateDocument::addView(KTextEditor::View *view) { views.append( static_cast<KateView *>( view ) ); KTextEditor::Document::addView( view ); connect( static_cast<KateView *>( view ), SIGNAL( destroyed() ), this, SLOT( slotViewDestroyed() ) ); } void KateDocument::removeView(KTextEditor::View *view) { // if (undoView == view) recordReset(); disconnect( static_cast<KateView *>( view ), SIGNAL( destroyed() ), this, SLOT( slotViewDestroyed() ) ); views.removeRef( static_cast<KateView *>( view ) ); KTextEditor::Document::removeView( view ); } void KateDocument::slotViewDestroyed() { views.removeRef( static_cast<const KateView *>( sender() ) ); } bool KateDocument::ownedView(KateView *view) { // do we own the given view? return (views.containsRef(view) > 0); } bool KateDocument::isLastView(int numViews) { return ((int) views.count() == numViews); } int KateDocument::textWidth(const TextLine::Ptr &textLine, int cursorX) { int x; int z; QChar ch; Attribute *a; x = 0; for (z = 0; z < cursorX; z++) { ch = textLine->getChar(z); a = &m_attribs[textLine->getAttr(z)]; if (ch == '\t') x += m_tabWidth - (x % m_tabWidth); else if (a->bold && a->italic) x += myFontMetricsBI.width(ch); else if (a->bold) x += myFontMetricsBold.width(ch); else if (a->italic) x += myFontMetricsItalic.width(ch); else x += myFontMetrics.width(ch); } return x; } int KateDocument::textWidth(PointStruc &cursor) { if (cursor.x < 0) cursor.x = 0; if (cursor.y < 0) cursor.y = 0; if (cursor.y >= numLines()) cursor.y = lastLine(); return textWidth(getTextLine(cursor.y),cursor.x); } int KateDocument::textWidth(bool wrapCursor, PointStruc &cursor, int xPos) { int len; int x, oldX; int z; QChar ch; Attribute *a; if (cursor.y < 0) cursor.y = 0; if (cursor.y > lastLine()) cursor.y = lastLine(); TextLine::Ptr textLine = getTextLine(cursor.y); len = textLine->length(); x = oldX = z = 0; while (x < xPos && (!wrapCursor || z < len)) { oldX = x; ch = textLine->getChar(z); a = &m_attribs[textLine->getAttr(z)]; if (ch == '\t') x += m_tabWidth - (x % m_tabWidth); else if (a->bold && a->italic) x += myFontMetricsBI.width(ch); else if (a->bold) x += myFontMetricsBold.width(ch); else if (a->italic) x += myFontMetricsItalic.width(ch); else x += myFontMetrics.width(ch); z++; } if (xPos - oldX < x - xPos && z > 0) { z--; x = oldX; } cursor.x = z; return x; } int KateDocument::textPos(const TextLine::Ptr &textLine, int xPos) { int x, oldX; int z; QChar ch; Attribute *a; x = oldX = z = 0; while (x < xPos) { // && z < len) { oldX = x; ch = textLine->getChar(z); a = &m_attribs[textLine->getAttr(z)]; if (ch == '\t') x += m_tabWidth - (x % m_tabWidth); else if (a->bold && a->italic) x += myFontMetricsBI.width(ch); else if (a->bold) x += myFontMetricsBold.width(ch); else if (a->italic) x += myFontMetricsItalic.width(ch); else x += myFontMetrics.width(ch); z++; } if (xPos - oldX < x - xPos && z > 0) { z--; // newXPos = oldX; }// else newXPos = x; return z; } int KateDocument::textWidth() { return int(maxLength + 8); } int KateDocument::textHeight() { return numLines()*fontHeight; } void KateDocument::insert(VConfig &c, const QString &s) { int pos; QChar ch; QString buf; if (s.isEmpty()) return; recordStart(c, KateActionGroup::ugPaste); pos = 0; if (!(c.flags & KateView::cfVerticalSelect)) { do { ch = s[pos]; if (ch.isPrint() || ch == '\t') { buf += ch; // append char to buffer } else if (ch == '\n') { recordAction(KateAction::newLine, c.cursor); // wrap contents behind cursor to new line recordInsert(c, buf); // append to old line // c.cursor.x += buf.length(); buf.truncate(0); // clear buffer c.cursor.y++; c.cursor.x = 0; } pos++; } while (pos < (int) s.length()); } else { int xPos; xPos = textWidth(c.cursor); do { ch = s[pos]; if (ch.isPrint() || ch == '\t') { buf += ch; } else if (ch == '\n') { recordInsert(c, buf); c.cursor.x += buf.length(); buf.truncate(0); c.cursor.y++; if (c.cursor.y >= numLines()) recordAction(KateAction::insLine, c.cursor); c.cursor.x = textPos(getTextLine(c.cursor.y), xPos); } pos++; } while (pos < (int) s.length()); } recordInsert(c, buf); c.cursor.x += buf.length(); recordEnd(c); } void KateDocument::insertFile(VConfig &c, QIODevice &dev) { recordStart(c, KateActionGroup::ugPaste); QString buf; QChar ch, last; QTextStream stream( &dev ); while ( !stream.atEnd() ) { stream >> ch; if (ch.isPrint() || ch == '\t') { buf += ch; } else if (ch == '\n' || ch == '\r') { if (last != '\r' || ch != '\n') { recordAction(KateAction::newLine, c.cursor); recordInsert(c, buf); buf.truncate(0); c.cursor.y++; c.cursor.x = 0; } last = ch; } } recordInsert(c, buf); recordEnd(c); } int KateDocument::currentColumn(PointStruc &cursor) { return getTextLine(cursor.y)->cursorX(cursor.x,tabChars); } bool KateDocument::insertChars(VConfig &c, const QString &chars) { int z, pos, l; bool onlySpaces; QChar ch; QString buf; TextLine::Ptr textLine = getTextLine(c.cursor.y); pos = 0; onlySpaces = true; for (z = 0; z < (int) chars.length(); z++) { ch = chars[z]; if (ch == '\t' && c.flags & KateView::cfReplaceTabs) { l = tabChars - (textLine->cursorX(c.cursor.x, tabChars) % tabChars); while (l > 0) { buf.insert(pos, ' '); pos++; l--; } } else if (ch.isPrint() || ch == '\t') { buf.insert(pos, ch); pos++; if (ch != ' ') onlySpaces = false; if (c.flags & KateView::cfAutoBrackets) { if (ch == '(') buf.insert(pos, ')'); if (ch == '[') buf.insert(pos, ']'); if (ch == '{') buf.insert(pos, '}'); } } } //pos = cursor increment //return false if nothing has to be inserted if (buf.isEmpty()) return false; //auto deletion of the marked text occurs not very often and can therefore // be recorded separately if (c.flags &KateView:: cfDelOnInput) delMarkedText(c); recordStart(c, KateActionGroup::ugInsChar); recordReplace(c/*.cursor*/, (c.flags & KateView::cfOvr) ? buf.length() : 0, buf); c.cursor.x += pos; if (myWordWrap && myWordWrapAt > 0) { int line; const QChar *s; // int pos; PointStruc actionCursor; line = c.cursor.y; do { textLine = getTextLine(line); s = textLine->getText(); l = textLine->length(); for (z = myWordWrapAt; z < l; z++) if (!s[z].isSpace()) break; //search for text to wrap if (z >= l) break; // nothing more to wrap pos = myWordWrapAt; for (; z >= 0; z--) { //find wrap position if (s[z].isSpace()) { pos = z + 1; break; } } //pos = wrap position if (line == c.cursor.y && pos <= c.cursor.x) { //wrap cursor c.cursor.y++; c.cursor.x -= pos; } if (line == lastLine() || (getTextLine(line+1)->length() == 0) ) { //at end of doc: create new line actionCursor.x = pos; actionCursor.y = line; recordAction(KateAction::newLine,actionCursor); } else { //wrap actionCursor.y = line + 1; if (!s[l - 1].isSpace()) { //add space in next line if necessary actionCursor.x = 0; recordInsert(actionCursor, " "); } actionCursor.x = textLine->length() - pos; recordAction(KateAction::wordWrap, actionCursor); } line++; } while (true); } recordEnd(c); return true; } QString tabString(int pos, int tabChars) { QString s; while (pos >= tabChars) { s += '\t'; pos -= tabChars; } while (pos > 0) { s += ' '; pos--; } return s; } void KateDocument::newLine(VConfig &c) { //auto deletion of marked text is done by the view to have a more // "low level" KateDocument::newLine method recordStart(c, KateActionGroup::ugInsLine); if (!(c.flags & KateView::cfAutoIndent)) { recordAction(KateAction::newLine,c.cursor); c.cursor.y++; c.cursor.x = 0; } else { TextLine::Ptr textLine = getTextLine(c.cursor.y); int pos = textLine->firstChar(); if (c.cursor.x < pos) c.cursor.x = pos; // place cursor on first char if before int y = c.cursor.y; while ((y > 0) && (pos < 0)) { // search a not empty text line textLine = getTextLine(--y); pos = textLine->firstChar(); } recordAction(KateAction::newLine, c.cursor); c.cursor.y++; c.cursor.x = 0; if (pos > 0) { pos = textLine->cursorX(pos, tabChars); // if (getTextLine(c.cursor.y)->length() > 0) { QString s = tabString(pos, (c.flags & KateView::cfSpaceIndent) ? 0xffffff : tabChars); recordInsert(c.cursor, s); pos = s.length(); // } // recordInsert(c.cursor, QString(textLine->getText(), pos)); c.cursor.x = pos; } } recordEnd(c); } void KateDocument::killLine(VConfig &c) { recordStart(c, KateActionGroup::ugDelLine); c.cursor.x = 0; recordDelete(c.cursor, 0xffffff); if (c.cursor.y < lastLine()) { recordAction(KateAction::killLine, c.cursor); } recordEnd(c); } void KateDocument::backspace(VConfig &c) { if (c.cursor.x <= 0 && c.cursor.y <= 0) return; if (c.cursor.x > 0) { recordStart(c, KateActionGroup::ugDelChar); if (!(c.flags & KateView::cfBackspaceIndents)) { // ordinary backspace c.cursor.x--; recordDelete(c.cursor, 1); } else { // backspace indents: erase to next indent position int l = 1; // del one char TextLine::Ptr textLine = getTextLine(c.cursor.y); int pos = textLine->firstChar(); if (pos < 0 || pos >= c.cursor.x) { // only spaces on left side of cursor // search a line with less spaces int y = c.cursor.y; while (y > 0) { textLine = getTextLine(--y); pos = textLine->firstChar(); if (pos >= 0 && pos < c.cursor.x) { l = c.cursor.x - pos; // del more chars break; } } } // break effectively jumps here c.cursor.x -= l; recordDelete(c.cursor, l); } } else { // c.cursor.x == 0: wrap to previous line recordStart(c, KateActionGroup::ugDelLine); c.cursor.y--; c.cursor.x = getTextLine(c.cursor.y)->length(); recordAction(KateAction::delLine,c.cursor); } recordEnd(c); } void KateDocument::del(VConfig &c) { TextLine::Ptr textLine = getTextLine(c.cursor.y); int len = (c.flags & KateView::cfRemoveSpaces) ? textLine->lastChar() : textLine->length(); if (c.cursor.x < len/*getTextLine(c.cursor.y)->length()*/) { // delete one character recordStart(c, KateActionGroup::ugDelChar); recordDelete(c.cursor, 1); recordEnd(c); } else { if (c.cursor.y < lastLine()) { // wrap next line to this line textLine->truncate(c.cursor.x); // truncate spaces recordStart(c, KateActionGroup::ugDelLine); recordAction(KateAction::delLine,c.cursor); recordEnd(c); } } } void KateDocument::clear() { PointStruc cursor; KateView *view; setPseudoModal(0L); cursor.x = cursor.y = 0; for (view = views.first(); view != 0L; view = views.next() ) { view->updateCursor(cursor); view->tagAll(); } eolMode = KateDocument::eolUnix; buffer->clear(); longestLine = buffer->line(0); maxLength = 0; select.x = -1; selectStart = 0xffffff; selectEnd = 0; oldMarkState = false; setModified(false); undoList.clear(); currentUndo = 0; newUndo(); } void KateDocument::cut(VConfig &c) { if (selectEnd < selectStart) return; copy(c.flags); delMarkedText(c); } void KateDocument::copy(int flags) { if (selectEnd < selectStart) return; QString s = markedText(flags); if (!s.isEmpty()) { //#if defined(_WS_X11_) if (m_singleSelection) disconnect(QApplication::clipboard(), SIGNAL(dataChanged()), this, 0); //#endif QApplication::clipboard()->setText(s); //#if defined(_WS_X11_) if (m_singleSelection) { connect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(clipboardChanged())); } //#endif } } void KateDocument::paste(VConfig &c) { QString s = QApplication::clipboard()->text(); if (!s.isEmpty()) { insert(c, s); } } void KateDocument::toggleRect(int start, int end, int x1, int x2) { int z, line; bool t; if (x1 > x2) { z = x1; x1 = x2; x2 = z; } if (start > end) { z = start; start = end; end = z; } t = false; for (line = start; line < end; line++) { int x, oldX, s, e, newX1, newX2; QChar ch; Attribute *a; TextLine::Ptr textLine = getTextLine(line); //--- speed optimization //s = textPos(textLine, x1, newX1); x = oldX = z = 0; while (x < x1) { // && z < len) { oldX = x; ch = textLine->getChar(z); a = &m_attribs[textLine->getAttr(z)]; if (ch == '\t') x += m_tabWidth - (x % m_tabWidth); else if (a->bold && a->italic) x += myFontMetricsBI.width(ch); else if (a->bold) x += myFontMetricsBold.width(ch); else if (a->italic) x += myFontMetricsItalic.width(ch); else x += myFontMetrics.width(ch); z++; } s = z; if (x1 - oldX < x - x1 && z > 0) { s--; newX1 = oldX; } else newX1 = x; //e = textPos(textLine, x2, newX2); while (x < x2) { // && z < len) { oldX = x; ch = textLine->getChar(z); a = &m_attribs[textLine->getAttr(z)]; if (ch == '\t') x += m_tabWidth - (x % m_tabWidth); else if (a->bold && a->italic) x += myFontMetricsBI.width(ch); else if (a->bold) x += myFontMetricsBold.width(ch); else if (a->italic) x += myFontMetricsItalic.width(ch); else x += myFontMetrics.width(ch); z++; } e = z; if (x2 - oldX < x - x2 && z > 0) { e--; newX2 = oldX; } else newX2 = x; //--- if (e > s) { textLine->toggleSelect(s, e); tagLineRange(line, newX1, newX2); t = true; } } if (t) { end--; // tagLines(start, end); if (start < selectStart) selectStart = start; if (end > selectEnd) selectEnd = end; emit selectionChanged(); } } void KateDocument::selectTo(VConfig &c, PointStruc &cursor, int cXPos) { //c.cursor = old cursor position //cursor = new cursor position if (c.cursor.x != select.x || c.cursor.y != select.y) { //new selection if (!(c.flags & KateView::cfKeepSelection)) deselectAll(); // else recordReset(); anchor = c.cursor; aXPos = c.cXPos; } if (!(c.flags & KateView::cfVerticalSelect)) { //horizontal selections int x, y, sXPos; int ex, ey, eXPos; bool sel; if (cursor.y > c.cursor.y || (cursor.y == c.cursor.y && cursor.x > c.cursor.x)) { x = c.cursor.x; y = c.cursor.y; sXPos = c.cXPos; ex = cursor.x; ey = cursor.y; eXPos = cXPos; sel = true; } else { x = cursor.x; y = cursor.y; sXPos = cXPos; ex = c.cursor.x; ey = c.cursor.y; eXPos = c.cXPos; sel = false; } // tagLines(y, ye); if (y < ey) { //tagLineRange(y, sXPos, 0xffffff); tagLines(y, ey -1); tagLineRange(ey, 0, eXPos); } else tagLineRange(y, sXPos, eXPos); if (y < selectStart) selectStart = y; if (ey > selectEnd) selectEnd = ey; TextLine::Ptr textLine = getTextLine(y); if (c.flags & KateView::cfXorSelect) { //xor selection with old selection while (y < ey) { textLine->toggleSelectEol(x); x = 0; y++; textLine = getTextLine(y); } textLine->toggleSelect(x, ex); } else { //set selection over old selection if (anchor.y > y || (anchor.y == y && anchor.x > x)) { if (anchor.y < ey || (anchor.y == ey && anchor.x < ex)) { sel = !sel; while (y < anchor.y) { textLine->selectEol(sel, x); x = 0; y++; textLine = getTextLine(y); } textLine->select(sel, x, anchor.x); x = anchor.x; } sel = !sel; } while (y < ey) { textLine->selectEol(sel, x); x = 0; y++; textLine = getTextLine(y); } textLine->select(sel, x, ex); } } else { //vertical (block) selections // int ax, sx, ex; // ax = textWidth(anchor); // sx = textWidth(start); // ex = textWidth(end); toggleRect(c.cursor.y + 1, cursor.y + 1, aXPos, c.cXPos); toggleRect(anchor.y, cursor.y + 1, c.cXPos, cXPos); } select = cursor; optimizeSelection(); emit selectionChanged(); } void KateDocument::selectAll() { int z; TextLine::Ptr textLine; select.x = -1; // if (selectStart != 0 || selectEnd != lastLine()) recordReset(); selectStart = 0; selectEnd = lastLine(); tagLines(selectStart,selectEnd); for (z = selectStart; z < selectEnd; z++) { textLine = getTextLine(z); textLine->selectEol(true,0); } textLine = getTextLine(z); textLine->select(true,0,textLine->length()); emit selectionChanged(); } void KateDocument::deselectAll() { select.x = -1; if (selectEnd < selectStart) return; // recordReset(); tagLines(selectStart,selectEnd); for (int z = selectStart; z <= selectEnd; z++) { TextLine::Ptr textLine = getTextLine(z); textLine->selectEol(false,0); } selectStart = 0xffffff; selectEnd = 0; emit selectionChanged(); } void KateDocument::invertSelection() { TextLine::Ptr textLine; select.x = -1; // if (selectStart != 0 || selectEnd != lastLine()) recordReset(); selectStart = 0; selectEnd = lastLine(); tagLines(selectStart,selectEnd); for (int z = selectStart; z < selectEnd; z++) { textLine = getTextLine(z); textLine->toggleSelectEol(0); } textLine = getTextLine(selectEnd); textLine->toggleSelect(0,textLine->length()); optimizeSelection(); emit selectionChanged(); } void KateDocument::selectWord(PointStruc &cursor, int flags) { int start, end, len; TextLine::Ptr textLine = getTextLine(cursor.y); len = textLine->length(); start = end = cursor.x; while (start > 0 && m_highlight->isInWord(textLine->getChar(start - 1))) start--; while (end < len && m_highlight->isInWord(textLine->getChar(end))) end++; if (end <= start) return; if (!(flags & KateView::cfKeepSelection)) deselectAll(); // else recordReset(); textLine->select(true, start, end); anchor.x = start; select.x = end; anchor.y = select.y = cursor.y; tagLines(cursor.y, cursor.y); if (cursor.y < selectStart) selectStart = cursor.y; if (cursor.y > selectEnd) selectEnd = cursor.y; emit selectionChanged(); } void KateDocument::selectLength(PointStruc &cursor, int length, int flags) { int start, end; TextLine::Ptr textLine = getTextLine(cursor.y); start = cursor.x; end = start + length; if (end <= start) return; if (!(flags & KateView::cfKeepSelection)) deselectAll(); textLine->select(true, start, end); anchor.x = start; select.x = end; anchor.y = select.y = cursor.y; tagLines(cursor.y, cursor.y); if (cursor.y < selectStart) selectStart = cursor.y; if (cursor.y > selectEnd) selectEnd = cursor.y; emit selectionChanged(); } void KateDocument::doIndent(VConfig &c, int change) { c.cursor.x = 0; recordStart(c, (change < 0) ? KateActionGroup::ugUnindent : KateActionGroup::ugIndent); if (selectEnd < selectStart) { // single line optimizeLeadingSpace(c.cursor.y, c.flags, change); } else { // entire selection TextLine::Ptr textLine; int line, z; QChar ch; if (c.flags & KateView::cfKeepIndentProfile && change < 0) { // unindent so that the existing indent profile doesn´t get screwed // if any line we may unindent is already full left, don't do anything for (line = selectStart; line <= selectEnd; line++) { textLine = getTextLine(line); if (textLine->isSelected() || textLine->numSelected()) { for (z = 0; z < tabChars; z++) { ch = textLine->getChar(z); if (ch == '\t') break; if (ch != ' ') { change = 0; goto jumpOut; } } } } jumpOut:; } for (line = selectStart; line <= selectEnd; line++) { textLine = getTextLine(line); if (textLine->isSelected() || textLine->numSelected()) { optimizeLeadingSpace(line, c.flags, change); } } } // recordEnd now removes empty undo records recordEnd(c.view, c.cursor, c.flags | KateView::cfPersistent); } /* Optimize the leading whitespace for a single line. If change is > 0, it adds indentation units (tabChars) if change is == 0, it only optimizes If change is < 0, it removes indentation units This will be used to indent, unindent, and optimal-fill a line. If excess space is removed depends on the flag cfKeepExtraSpaces which has to be set by the user */ void KateDocument::optimizeLeadingSpace(int line, int flags, int change) { int len; int chars, space, okLen; QChar ch; int extra; QString s; PointStruc cursor; TextLine::Ptr textLine = getTextLine(line); len = textLine->length(); space = 0; // length of space at the beginning of the textline okLen = 0; // length of space which does not have to be replaced for (chars = 0; chars < len; chars++) { ch = textLine->getChar(chars); if (ch == ' ') { space++; if (flags & KateView::cfSpaceIndent && okLen == chars) okLen++; } else if (ch == '\t') { space += tabChars - space % tabChars; if (!(flags & KateView::cfSpaceIndent) && okLen == chars) okLen++; } else break; } space += change*tabChars; // modify space width // if line contains only spaces it will be cleared if (space < 0 || chars == len) space = 0; extra = space % tabChars; // extra spaces which don´t fit the indentation pattern if (flags & KateView::cfKeepExtraSpaces) chars -= extra; if (flags & KateView::cfSpaceIndent) { space -= extra; ch = ' '; } else { space /= tabChars; ch = '\t'; } // don´t replace chars which are already ok cursor.x = QMIN(okLen, QMIN(chars, space)); chars -= cursor.x; space -= cursor.x; if (chars == 0 && space == 0) return; //nothing to do s.fill(ch, space); //printf("chars %d insert %d cursor.x %d\n", chars, insert, cursor.x); cursor.y = line; recordReplace(cursor, chars, s); } void KateDocument::doComment(VConfig &c, int change) { c.flags |=KateView:: cfPersistent; recordStart(c, (change < 0) ? KateActionGroup::ugUncomment : KateActionGroup::ugComment); QString startComment = m_highlight->getCommentStart(); QString startLineComment = m_highlight->getCommentSingleLineStart(); QString endComment = m_highlight->getCommentEnd(); int startCommentLen = startComment.length(); int startLineCommentLen = startLineComment.length(); int endCommentLen = endComment.length(); if (change > 0) { if ( !hasMarkedText() ) { if (startLineComment != "") { // Add a start comment mark c.cursor.x = 0; recordReplace(c.cursor, 0, startLineComment); } else if ((startComment != "") && (endComment != "")) { // Add a start comment mark c.cursor.x = 0; recordReplace(c.cursor, 0, startComment); // Add an end comment mark TextLine* textline = getTextLine(c.cursor.y); c.cursor.x = textline->length(); recordReplace(c.cursor, 0, endComment); c.cursor.x = 0; } } else if ((startComment != "") && (endComment != "")) { QString marked (c.view->markedText ()); int preDeleteLine = -1, preDeleteCol = -1; c.view->getCursorPosition (&preDeleteLine, &preDeleteCol); if (marked.length() > 0) c.view->keyDelete (); int line = -1, col = -1; c.view->getCursorPosition (&line, &col); c.view->insertText (startComment + marked + endComment); } } else { if ( !hasMarkedText() ) { TextLine* textline = getTextLine(c.cursor.y); if(textline->startingWith(startLineComment)) { // Remove start comment mark c.cursor.x = 0; recordReplace(c.cursor, startLineCommentLen, ""); } else if (textline->startingWith(startComment) && textline->endingWith(endComment)) { // Remove start comment mark c.cursor.x = 0; recordReplace(c.cursor, startCommentLen, ""); // Remove end comment mark if(endComment != "") { c.cursor.x = textline->length() - endCommentLen; recordReplace(c.cursor, endCommentLen, ""); c.cursor.x = 0; } } } else { QString marked (c.view->markedText ()); int preDeleteLine = -1, preDeleteCol = -1; c.view->getCursorPosition (&preDeleteLine, &preDeleteCol); int start = marked.find (startComment); int end = marked.findRev (endComment); if ((start > -1) && (end > -1)) { marked.remove (start, startCommentLen); marked.remove (end-startCommentLen, endCommentLen); c.view->keyDelete (); int line = -1, col = -1; c.view->getCursorPosition (&line, &col); c.view->insertText (marked); } } } recordEnd(c.view, c.cursor, c.flags | KateView::cfPersistent); } QString KateDocument::text() const { QString s; for (int i=0; i < buffer->count(); i++) { TextLine::Ptr textLine = buffer->line(i); s.insert(s.length(), textLine->getText(), textLine->length()); if ( (i < (buffer->count()-1)) ) s.append('\n'); } return s; } QString KateDocument::getWord(PointStruc &cursor) { int start, end, len; TextLine::Ptr textLine = getTextLine(cursor.y); len = textLine->length(); start = end = cursor.x; while (start > 0 && m_highlight->isInWord(textLine->getChar(start - 1))) start--; while (end < len && m_highlight->isInWord(textLine->getChar(end))) end++; len = end - start; return QString(&textLine->getText()[start], len); } void KateDocument::setText(const QString &s) { int pos; QChar ch; clear(); int line=1; TextLine::Ptr textLine = buffer->line(0); for (pos = 0; pos <= (int) s.length(); pos++) { ch = s[pos]; if (ch.isPrint() || ch == '\t') { textLine->append(&ch, 1); } else if (ch == '\n') { textLine = new TextLine(); buffer->insertLine (line, textLine); line++; } } updateLines(); } QString KateDocument::markedText(int flags) { TextLine::Ptr textLine; int len, z, start, end, i; len = 1; if (!(flags & KateView::cfVerticalSelect)) { for (z = selectStart; z <= selectEnd; z++) { textLine = getTextLine(z); len += textLine->numSelected(); if (textLine->isSelected()) len++; } QString s; len = 0; for (z = selectStart; z <= selectEnd; z++) { textLine = getTextLine(z); end = 0; do { start = textLine->findUnselected(end); end = textLine->findSelected(start); for (i = start; i < end; i++) { s[len] = textLine->getChar(i); len++; } } while (start < end); if (textLine->isSelected()) { s[len] = '\n'; len++; } } // s[len] = '\0'; return s; } else { for (z = selectStart; z <= selectEnd; z++) { textLine = getTextLine(z); len += textLine->numSelected() + 1; } QString s; len = 0; for (z = selectStart; z <= selectEnd; z++) { textLine = getTextLine(z); end = 0; do { start = textLine->findUnselected(end); end = textLine->findSelected(start); for (i = start; i < end; i++) { s[len] = textLine->getChar(i); len++; } } while (start < end); s[len] = '\n'; len++; } // s[len] = '\0'; // the final \0 is not counted in length() return s; } } void KateDocument::delMarkedText(VConfig &c/*, bool undo*/) { int end = 0; if (selectEnd < selectStart) return; // the caller may have already started an undo record for the current action // if (undo) //auto deletion of the marked text occurs not very often and can therefore // be recorded separately recordStart(c, KateActionGroup::ugDelBlock); for (c.cursor.y = selectEnd; c.cursor.y >= selectStart; c.cursor.y--) { TextLine::Ptr textLine = getTextLine(c.cursor.y); c.cursor.x = textLine->length(); do { end = textLine->findRevUnselected(c.cursor.x); if (end == 0) break; c.cursor.x = textLine->findRevSelected(end); recordDelete(c.cursor, end - c.cursor.x); } while (true); end = c.cursor.x; c.cursor.x = textLine->length(); if (textLine->isSelected()) recordAction(KateAction::delLine,c.cursor); } c.cursor.y++; /*if (end < c.cursor.x)*/ c.cursor.x = end; selectEnd = -1; select.x = -1; /*if (undo)*/ recordEnd(c); } void KateDocument::tagLineRange(int line, int x1, int x2) { int z; for (z = 0; z < (int) views.count(); z++) { views.at(z)->tagLines(line, line, x1, x2); } } void KateDocument::tagLines(int start, int end) { int z; for (z = 0; z < (int) views.count(); z++) { views.at(z)->tagLines(start, end, 0, 0xffffff); } } void KateDocument::tagAll() { int z; for (z = 0; z < (int) views.count(); z++) { views.at(z)->tagAll(); } } void KateDocument::updateLines(int startLine, int endLine, int flags, int cursorY) { TextLine::Ptr textLine; int line, last_line; int ctxNum, endCtx; // kdDebug(13020)<<"******************KateDocument::updateLines Checkpoint 1"<<endl; if (buffer->line(startLine)==0) {kdDebug(13020)<<"********************No buffer for line " << startLine << " found**************"<<endl; return;}; // kdDebug(13020)<<"KateDocument::updateLines Checkpoint 2"<<endl; last_line = lastLine(); // if (endLine >= last_line) endLine = last_line; line = startLine; ctxNum = 0; if (line > 0) ctxNum = getTextLine(line - 1)->getContext(); do { // kdDebug(13020)<<QString("**************Working on line: %1").arg(line)<<endl; textLine = getTextLine(line); if (textLine==0) kdDebug(13020)<<"****updateLines()>> error textLine==0"<<endl; if (line <= endLine && line != cursorY) { if (flags & KateView::cfRemoveSpaces) textLine->removeSpaces(); updateMaxLength(textLine); } endCtx = textLine->getContext(); // odebug << "DOHIGHLIGHT" << oendl; ctxNum = m_highlight->doHighlight(ctxNum,textLine); textLine->setContext(ctxNum); line++; } while ((buffer->line(line)!=0) && (line <= endLine || endCtx != ctxNum)); // kdDebug(13020)<<"updateLines :: while loop left"<<endl; tagLines(startLine, line - 1); } void KateDocument::updateMaxLength(TextLine::Ptr &textLine) { int len; len = textWidth(textLine,textLine->length()); if (len > maxLength) { longestLine = textLine; maxLength = len; newDocGeometry = true; } else { if (!longestLine || (textLine == longestLine && len <= maxLength*3/4)) { maxLength = -1; for (int i = 0; i < numLines();i++) { textLine = getTextLine(i); len = textWidth(textLine,textLine->length()); if (len > maxLength) { maxLength = len; longestLine = textLine; } } newDocGeometry = true; } } } void KateDocument::slotBufferChanged() { newDocGeometry = true; //updateLines();//JW updateViews(); } void KateDocument::slotBufferHighlight(long start,long stop) { kdDebug(13020)<<"KateDocument::slotBufferHighlight"<<QString("%1-%2").arg(start).arg(stop)<<endl; updateLines(start,stop); // buffer->startLoadTimer(); } void KateDocument::updateViews(KateView *exclude) { KateView *view; int flags; bool markState = hasMarkedText(); flags = (newDocGeometry) ? KateView::ufDocGeometry : 0; for (view = views.first(); view != 0L; view = views.next() ) { if (view != exclude) view->updateView(flags); // notify every view about the changed mark state.... if (oldMarkState != markState) emit view->newMarkStatus(); } oldMarkState = markState; newDocGeometry = false; } QColor &KateDocument::cursorCol(int x, int y) { int attr; Attribute *a; TextLine::Ptr textLine = getTextLine(y); attr = textLine->getRawAttr(x); a = &m_attribs[attr & taAttrMask]; if (attr & taSelected) return a->selCol; else return a->col; } void KateDocument::paintTextLine(QPainter &paint, int line, int xStart, int xEnd, bool showTabs) { paintTextLine (paint, line, 0, xStart, xEnd, showTabs); } void KateDocument::paintTextLine(QPainter &paint, int line, int y, int xStart, int xEnd, bool showTabs) { TextLine::Ptr textLine; int len; const QChar *s; int z, x; QChar ch; - Attribute *a = 0L; + Attribute *attrptr = 0L; int attr, nextAttr; int xs; int xc, zc; if (line > lastLine()) { paint.fillRect(0, y, xEnd - xStart,fontHeight, colors[0]); return; } textLine = getTextLine(line); len = textLine->length(); s = textLine->getText(); // skip to first visible character x = 0; z = 0; do { xc = x; zc = z; if (z == len) break; ch = s[z];//textLine->getChar(z); if (ch == '\t') { x += m_tabWidth - (x % m_tabWidth); } else { - a = &m_attribs[textLine->getAttr(z)]; + attrptr = &m_attribs[textLine->getAttr(z)]; - if (a->bold && a->italic) + if (attrptr->bold && attrptr->italic) x += myFontMetricsBI.width(ch); - else if (a->bold) + else if (attrptr->bold) x += myFontMetricsBold.width(ch); - else if (a->italic) + else if (attrptr->italic) x += myFontMetricsItalic.width(ch); else x += myFontMetrics.width(ch); } z++; } while (x <= xStart); // draw background xs = xStart; attr = textLine->getRawAttr(zc); while (x < xEnd) { nextAttr = textLine->getRawAttr(z); if ((nextAttr ^ attr) & taSelected) { if (attr & taSelected) paint.fillRect(xs - xStart, y, x - xs, fontHeight, colors[1]); else paint.fillRect(xs - xStart, y, x - xs, fontHeight, colors[0]); xs = x; attr = nextAttr; } if (z == len) break; ch = s[z];//textLine->getChar(z); if (ch == '\t') x += m_tabWidth - (x % m_tabWidth); else { - a = &m_attribs[textLine->getAttr(z)]; + attrptr = &m_attribs[textLine->getAttr(z)]; - if (a->bold && a->italic) + if (attrptr->bold && attrptr->italic) x += myFontMetricsBI.width(ch); - else if (a->bold) + else if (attrptr->bold) x += myFontMetricsBold.width(ch); - else if (a->italic) + else if (attrptr->italic) x += myFontMetricsItalic.width(ch); else x += myFontMetrics.width(ch); } z++; } if (attr & taSelected) paint.fillRect(xs - xStart, y, xEnd - xs, fontHeight, colors[1]); else paint.fillRect(xs - xStart, y, xEnd - xs, fontHeight, colors[0]); len = z; //reduce length to visible length // draw text x = xc; z = zc; y += fontAscent;// -1; attr = -1; while (z < len) { ch = s[z];//textLine->getChar(z); if (ch == '\t') { if (z > zc) { //this should cause no copy at all QConstString str((QChar *) &s[zc], z - zc /*+1*/); QString s = str.string(); paint.drawText(x - xStart, y, s); - if (a->bold && a->italic) + if (attrptr && attrptr->bold && attrptr->italic) x += myFontMetricsBI.width(s); - else if (a->bold) + else if (attrptr && attrptr->bold) x += myFontMetricsBold.width(s); - else if (a->italic) + else if (attrptr && attrptr->italic) x += myFontMetricsItalic.width(s); else x += myFontMetrics.width(s); } zc = z +1; if (showTabs) { nextAttr = textLine->getRawAttr(z); if (nextAttr != attr) { attr = nextAttr; - a = &m_attribs[attr & taAttrMask]; + attrptr = &m_attribs[attr & taAttrMask]; - if (attr & taSelected) paint.setPen(a->selCol); - else paint.setPen(a->col); + if (attr & taSelected) paint.setPen(attrptr->selCol); + else paint.setPen(attrptr->col); - if (a->bold && a->italic) + if (attrptr->bold && attrptr->italic) paint.setFont(myFontBI); - else if (a->bold) + else if (attrptr->bold) paint.setFont(myFontBold); - else if (a->italic) + else if (attrptr->italic) paint.setFont(myFontItalic); else paint.setFont(myFont); } -// paint.drawLine(x - xStart, y -2, x - xStart, y); -// paint.drawLine(x - xStart, y, x - xStart + 2, y); paint.drawPoint(x - xStart, y); paint.drawPoint(x - xStart +1, y); paint.drawPoint(x - xStart, y -1); } x += m_tabWidth - (x % m_tabWidth); } else { nextAttr = textLine->getRawAttr(z); if (nextAttr != attr) { if (z > zc) { QConstString str((QChar *) &s[zc], z - zc /*+1*/); QString s = str.string(); paint.drawText(x - xStart, y, s); - if (a->bold && a->italic) + if (attrptr->bold && attrptr->italic) x += myFontMetricsBI.width(s); - else if (a->bold) + else if (attrptr->bold) x += myFontMetricsBold.width(s); - else if (a->italic) + else if (attrptr->italic) x += myFontMetricsItalic.width(s); else x += myFontMetrics.width(s); zc = z; } attr = nextAttr; - a = &m_attribs[attr & taAttrMask]; + attrptr = &m_attribs[attr & taAttrMask]; - if (attr & taSelected) paint.setPen(a->selCol); - else paint.setPen(a->col); + if (attr & taSelected) paint.setPen(attrptr->selCol); + else paint.setPen(attrptr->col); - if (a->bold && a->italic) + if (attrptr->bold && attrptr->italic) paint.setFont(myFontBI); - else if (a->bold) + else if (attrptr->bold) paint.setFont(myFontBold); - else if (a->italic) + else if (attrptr->italic) paint.setFont(myFontItalic); else paint.setFont(myFont); } } z++; } if (z > zc) { QConstString str((QChar *) &s[zc], z - zc /*+1*/); paint.drawText(x - xStart, y, str.string()); } } // Applies the search context, and returns whether a match was found. If one is, // the length of the string matched is also returned. bool KateDocument::doSearch(SConfig &sc, const QString &searchFor) { int line, col; int searchEnd; int bufLen, tlen; QChar *t; TextLine::Ptr textLine; int pos, newPos; if (searchFor.isEmpty()) return false; bufLen = 0; t = 0L; line = sc.cursor.y; col = sc.cursor.x; if (!(sc.flags & KateView::sfBackward)) { //forward search if (sc.flags & KateView::sfSelected) { if (line < selectStart) { line = selectStart; col = 0; } searchEnd = selectEnd; } else searchEnd = lastLine(); while (line <= searchEnd) { textLine = getTextLine(line); tlen = textLine->length(); if (tlen > bufLen) { delete [] t; bufLen = (tlen + 255) & (~255); t = new QChar[bufLen]; - } + } else if (!t) + t = new QChar[bufLen]; + memcpy(t, textLine->getText(), tlen*sizeof(QChar)); if (sc.flags & KateView::sfSelected) { pos = 0; do { pos = textLine->findSelected(pos); newPos = textLine->findUnselected(pos); memset(&t[pos], 0, (newPos - pos)*sizeof(QChar)); pos = newPos; } while (pos < tlen); } QString text(t, tlen); if (sc.flags & KateView::sfWholeWords) { // Until the end of the line... while (col < tlen) { // ...find the next match. col = sc.search(text, col); if (col != -1) { // Is the match delimited correctly? if (((col == 0) || (!m_highlight->isInWord(t[col]))) && ((col + sc.matchedLength == tlen) || (!m_highlight->isInWord(t[col + sc.matchedLength])))) { goto found; } else { // Start again from the next character. col++; } } else { // No match. break; } } } else { // Non-whole-word search. col = sc.search(text, col); if (col != -1) goto found; } col = 0; line++; } } else { // backward search if (sc.flags & KateView::sfSelected) { if (line > selectEnd) { line = selectEnd; col = -1; } searchEnd = selectStart; } else searchEnd = 0; while (line >= searchEnd) { textLine = getTextLine(line); tlen = textLine->length(); if (tlen > bufLen) { delete [] t; bufLen = (tlen + 255) & (~255); t = new QChar[bufLen]; - } + } else if (!t) + t = new QChar[bufLen]; memcpy(t, textLine->getText(), tlen*sizeof(QChar)); if (sc.flags & KateView::sfSelected) { pos = 0; do { pos = textLine->findSelected(pos); newPos = textLine->findUnselected(pos); memset(&t[pos], 0, (newPos - pos)*sizeof(QChar)); pos = newPos; } while (pos < tlen); } if (col < 0 || col > tlen) col = tlen; QString text(t, tlen); if (sc.flags & KateView::sfWholeWords) { // Until the beginning of the line... while (col >= 0) { // ...find the next match. col = sc.search(text, col); if (col != -1) { // Is the match delimited correctly? if (((col == 0) || (!m_highlight->isInWord(t[col]))) && ((col + sc.matchedLength == tlen) || (!m_highlight->isInWord(t[col + sc.matchedLength])))) { goto found; } else { // Start again from the previous character. col--; } } else { // No match. break; } } } else { // Non-whole-word search. col = sc.search(text, col); if (col != -1) goto found; } col = -1; line--; } } sc.flags |= KateView::sfWrapped; return false; found: if (sc.flags & KateView::sfWrapped) { if ((line > sc.startCursor.y || (line == sc.startCursor.y && col >= sc.startCursor.x)) ^ ((sc.flags & KateView::sfBackward) != 0)) return false; } sc.cursor.x = col; sc.cursor.y = line; return true; } void KateDocument::tagLine(int line) { if (tagStart > line) tagStart = line; if (tagEnd < line) tagEnd = line; } void KateDocument::insLine(int line) { KateView *view; if (selectStart >= line) selectStart++; if (selectEnd >= line) selectEnd++; if (tagStart >= line) tagStart++; if (tagEnd >= line) tagEnd++; newDocGeometry = true; for (view = views.first(); view != 0L; view = views.next() ) { view->insLine(line); } } void KateDocument::delLine(int line) { KateView *view; if (selectStart >= line && selectStart > 0) selectStart--; if (selectEnd >= line) selectEnd--; if (tagStart >= line && tagStart > 0) tagStart--; if (tagEnd >= line) tagEnd--; newDocGeometry = true; for (view = views.first(); view != 0L; view = views.next() ) { view->delLine(line); } } void KateDocument::optimizeSelection() { TextLine::Ptr textLine; while (selectStart <= selectEnd) { textLine = getTextLine(selectStart); if (textLine->isSelected() || textLine->numSelected() > 0) break; selectStart++; } while (selectEnd >= selectStart) { textLine = getTextLine(selectEnd); if (textLine->isSelected() || textLine->numSelected() > 0) break; selectEnd--; } if (selectStart > selectEnd) { selectStart = 0xffffff; selectEnd = 0; } } void KateDocument::doAction(KateAction *a) { switch (a->action) { case KateAction::replace: doReplace(a); break; case KateAction::wordWrap: doWordWrap(a); break; case KateAction::wordUnWrap: doWordUnWrap(a); break; case KateAction::newLine: doNewLine(a); break; case KateAction::delLine: doDelLine(a); break; case KateAction::insLine: doInsLine(a); break; case KateAction::killLine: doKillLine(a); break; /* case KateAction::doubleLine: break; case KateAction::removeLine: break;*/ } } void KateDocument::doReplace(KateAction *a) { TextLine::Ptr textLine; int l; //exchange current text with stored text in KateAction *a textLine = getTextLine(a->cursor.y); l = textLine->length() - a->cursor.x; if (l > a->len) l = a->len; QString oldText(&textLine->getText()[a->cursor.x], (l < 0) ? 0 : l); textLine->replace(a->cursor.x, a->len, a->text.unicode(), a->text.length()); a->len = a->text.length(); a->text = oldText; buffer->changeLine(a->cursor.y); tagLine(a->cursor.y); } void KateDocument::doWordWrap(KateAction *a) { TextLine::Ptr textLine; textLine = getTextLine(a->cursor.y - 1); a->len = textLine->length() - a->cursor.x; textLine->wrap(getTextLine(a->cursor.y),a->len); buffer->changeLine(a->cursor.y - 1); buffer->changeLine(a->cursor.y); tagLine(a->cursor.y - 1); tagLine(a->cursor.y); if (selectEnd == a->cursor.y - 1) selectEnd++; a->action = KateAction::wordUnWrap; } void KateDocument::doWordUnWrap(KateAction *a) { TextLine::Ptr textLine; textLine = getTextLine(a->cursor.y - 1); // textLine->setLength(a->len); textLine->unWrap(a->len, getTextLine(a->cursor.y),a->cursor.x); buffer->changeLine(a->cursor.y - 1); buffer->changeLine(a->cursor.y); tagLine(a->cursor.y - 1); tagLine(a->cursor.y); a->action = KateAction::wordWrap; } void KateDocument::doNewLine(KateAction *a) { TextLine::Ptr textLine, newLine; textLine = getTextLine(a->cursor.y); newLine = new TextLine(textLine->getRawAttr(), textLine->getContext()); textLine->wrap(newLine,a->cursor.x); buffer->insertLine(a->cursor.y + 1, newLine); buffer->changeLine(a->cursor.y); insLine(a->cursor.y + 1); tagLine(a->cursor.y); tagLine(a->cursor.y + 1); if (selectEnd == a->cursor.y) selectEnd++;//addSelection(a->cursor.y + 1); a->action = KateAction::delLine; } void KateDocument::doDelLine(KateAction *a) { TextLine::Ptr textLine, nextLine; textLine = getTextLine(a->cursor.y); nextLine = getTextLine(a->cursor.y+1); // textLine->setLength(a->cursor.x); textLine->unWrap(a->cursor.x, nextLine,nextLine->length()); textLine->setContext(nextLine->getContext()); if (longestLine == nextLine) longestLine = 0L; buffer->changeLine(a->cursor.y); buffer->removeLine(a->cursor.y+1); tagLine(a->cursor.y); delLine(a->cursor.y + 1); a->action = KateAction::newLine; } void KateDocument::doInsLine(KateAction *a) { buffer->insertLine(a->cursor.y, new TextLine()); insLine(a->cursor.y); a->action = KateAction::killLine; } void KateDocument::doKillLine(KateAction *a) { TextLine::Ptr textLine = getTextLine(a->cursor.y); if (longestLine == textLine) longestLine = 0L; buffer->removeLine(a->cursor.y); delLine(a->cursor.y); tagLine(a->cursor.y); a->action = KateAction::insLine; } void KateDocument::newUndo() { KTextEditor::View *view; int state; state = 0; if (currentUndo > 0) state |= 1; if (currentUndo < (int) undoList.count()) state |= 2; undoState = state; for (view = m_views.first(); view != 0L; view = m_views.next() ) { emit static_cast<KateView *>( view )->newUndo(); } } void KateDocument::recordStart(VConfig &c, int newUndoType) { recordStart(c.view, c.cursor, c.flags, newUndoType); } void KateDocument::recordStart(KateView *, PointStruc &cursor, int flags, int newUndoType, bool keepModal, bool mergeUndo) { KateActionGroup *g; // if (newUndoType == KateActionGroup::ugNone) { // only a bug would cause this //why should someone do this? we can't prevent all programming errors :) (jochen whilhelmy) // debug("KateDocument::recordStart() called with no undo group type!"); // return; // } if (!keepModal) setPseudoModal(0L); //i optimized the group undo stuff a bit (jochen wilhelmy) // recordReset() is not needed any more g = undoList.getLast(); if (g != 0L && ((undoCount < 1024 && flags & KateView::cfGroupUndo && g->end.x == cursor.x && g->end.y == cursor.y) || mergeUndo)) { //undo grouping : same actions are put into one undo step //precondition : new action starts where old stops or mergeUndo flag if (g->undoType == newUndoType || (g->undoType == KateActionGroup::ugInsChar && newUndoType == KateActionGroup::ugInsLine) || (g->undoType == KateActionGroup::ugDelChar && newUndoType == KateActionGroup::ugDelLine)) { undoCount++; if (g->undoType != newUndoType) undoCount = 0xffffff; return; } } undoCount = 0; /* if (undoView != view) { // always kill the current undo group if the editing view changes recordReset(); undoType = newUndoType; } else if (newUndoType == undoType) { printf("bla!!!\n"); // same as current type, keep using it return; } else if ( (undoType == KateActionGroup::ugInsChar && newUndoType == KateActionGroup::ugInsLine) || (undoType == KateActionGroup::ugDelChar && newUndoType == KateActionGroup::ugDelLine) ) { // some type combinations can run together... undoType += 1000; return; } else { recordReset(); undoType = newUndoType; } undoView = view; */ while ((int) undoList.count() > currentUndo) undoList.removeLast(); while ((int) undoList.count() > undoSteps) { undoList.removeFirst(); currentUndo--; } g = new KateActionGroup(cursor, newUndoType); undoList.append(g); // currentUndo++; tagEnd = 0; tagStart = 0xffffff; } void KateDocument::recordAction(KateAction::Action action, PointStruc &cursor) { KateAction *a; a = new KateAction(action, cursor); doAction(a); undoList.getLast()->insertAction(a); } void KateDocument::recordInsert(VConfig &c, const QString &text) { recordReplace(c, 0, text); } void KateDocument::recordReplace(VConfig &c, int len, const QString &text) { if (c.cursor.x > 0 && !(c.flags & KateView::cfSpaceIndent)) { TextLine::Ptr textLine = getTextLine(c.cursor.y); if (textLine->length() == 0) { QString s = tabString(c.cursor.x, tabChars); int len = s.length(); s += text; c.cursor.x = 0; recordReplace(c.cursor, len, s); c.cursor.x = len; return; } } recordReplace(c.cursor, len, text); } void KateDocument::recordInsert(PointStruc &cursor, const QString &text) { recordReplace(cursor, 0, text); } void KateDocument::recordDelete(PointStruc &cursor, int len) { recordReplace(cursor, len, QString::null); } void KateDocument::recordReplace(PointStruc &cursor, int len, const QString &text) { KateAction *a; TextLine::Ptr textLine; int l; if (len == 0 && text.isEmpty()) return; //try to append to last replace action a = undoList.getLast()->action; if (a == 0L || a->action != KateAction::replace || a->cursor.x + a->len != cursor.x || a->cursor.y != cursor.y) { //if (a != 0L) printf("new %d %d\n", a->cursor.x + a->len, cursor.x); a = new KateAction(KateAction::replace, cursor); undoList.getLast()->insertAction(a); } //replace textLine = getTextLine(cursor.y); l = textLine->length() - cursor.x; if (l > len) l = len; a->text.insert(a->text.length(), &textLine->getText()[cursor.x], (l < 0) ? 0 : l); textLine->replace(cursor.x, len, text.unicode(), text.length()); a->len += text.length(); buffer->changeLine(a->cursor.y); updateMaxLength(textLine); tagLine(a->cursor.y); } void KateDocument::recordEnd(VConfig &c) { recordEnd(c.view, c.cursor, c.flags); } void KateDocument::recordEnd(KateView *view, PointStruc &cursor, int flags) { KateActionGroup *g; // clear selection if option "persistent selections" is off // if (!(flags & cfPersistent)) deselectAll(); g = undoList.getLast(); if (g->action == 0L) { // no action has been done: remove empty undo record undoList.removeLast(); return; } // store end cursor position for redo g->end = cursor; currentUndo = undoList.count(); if (tagStart <= tagEnd) { optimizeSelection(); updateLines(tagStart, tagEnd, flags, cursor.y); setModified(true); } view->updateCursor(cursor, flags); // newUndo(); /* undoCount++; // we limit the number of individual undo operations for sanity - is 1K reasonable? // this is also where we handle non-group undo preference // if the undo type is singlular, we always finish it now if ( undoType == KateActionGroup::ugPaste || undoType == KateActionGroup::ugDelBlock || undoType > 1000 || undoCount > 1024 || !(flags & cfGroupUndo) ) { printf("recordend %d %d\n", undoType, undoCount); recordReset(); } */ // this should keep the flood of signals down a little... if (undoCount == 0) newUndo(); emit textChanged(); } /* void KateDocument::recordReset() { if (pseudoModal) return; // forces the next call of recordStart() to begin a new undo group // not used in normal editing, but used by markFound(), etc. undoType = KateActionGroup::ugNone; undoCount = 0; undoView = NULL; undoReported = false; printf("recordreset\n"); } */ /* void KateDocument::recordDel(PointStruc &cursor, TextLine::Ptr &textLine, int l) { int len; len = textLine->length() - cursor.x; if (len > l) len = l; if (len > 0) { insertUndo(new KateAction(KateAction::replace,cursor,&textLine->getText()[cursor.x],len)); } } */ void KateDocument::doActionGroup(KateActionGroup *g, int flags, bool undo) { KateAction *a, *next; setPseudoModal(0L); if (!(flags & KateView::cfPersistent)) deselectAll(); tagEnd = 0; tagStart = 0xffffff; a = g->action; g->action = 0L; while (a) { doAction(a); next = a->next; g->insertAction(a); a = next; } optimizeSelection(); if (tagStart <= tagEnd) updateLines(tagStart, tagEnd, flags); // the undo/redo functions set undo to true, all others should leave it // alone (default) if (!undo) { setModified(true); newUndo(); } } int KateDocument::nextUndoType() { KateActionGroup *g; if (currentUndo <= 0) return KateActionGroup::ugNone; g = undoList.at(currentUndo - 1); return g->undoType; } int KateDocument::nextRedoType() { KateActionGroup *g; if (currentUndo >= (int) undoList.count()) return KateActionGroup::ugNone; g = undoList.at(currentUndo); // if (!g) return KateActionGroup::ugNone; return g->undoType; } void KateDocument::undoTypeList(QValueList<int> &lst) { lst.clear(); for (int i = currentUndo-1; i>=0 ;i--) lst.append(undoList.at(i)->undoType); } void KateDocument::redoTypeList(QValueList<int> &lst) { lst.clear(); for (int i = currentUndo+1; i<(int)undoList.count(); i++) lst.append(undoList.at(i)->undoType); } void KateDocument::undo(VConfig &c, int count) { KateActionGroup *g = 0L; int num; bool needUpdate = false; // don't update the cursor until completely done if (count <= 0) return; for (num = 0 ; num < count ; num++) { if (currentUndo <= 0) break; currentUndo--; g = undoList.at(currentUndo); doActionGroup(g, c.flags, true); // do not setModified() or newUndo() needUpdate = true; // if (num == 0) recordReset(); } if (needUpdate) { // since we told doActionGroup() not to do this stuff, we need to do it now c.view->updateCursor(g->start); setModified(true); newUndo(); } } void KateDocument::redo(VConfig &c, int count) { KateActionGroup *g = 0L; int num; bool needUpdate = false; // don't update the cursor until completely done if (count <= 0) return; for (num = 0 ; num < count ; num++) { if (currentUndo+1 > (int)undoList.count()) break; g = undoList.at(currentUndo); currentUndo++; doActionGroup(g, c.flags, true); // do not setModified() or newUndo() needUpdate = true; // if (num == 0) recordReset(); } if (needUpdate) { // since we told doActionGroup() not to do this stuff, we need to do it now c.view->updateCursor(g->end); setModified(true); newUndo(); } } void KateDocument::clearRedo() { // disable redos // this was added as an assist to the spell checker bool deleted = false; while ((int) undoList.count() > currentUndo) { deleted = true; undoList.removeLast(); } if (deleted) newUndo(); } void KateDocument::setUndoSteps(int steps) { if (steps < 5) steps = 5; undoSteps = steps; } void KateDocument::setPseudoModal(QWidget *w) { // QWidget *old = pseudoModal; // (glenebob) // this is a temporary hack to make the spell checker work a little // better - as kspell progresses, this sort of thing should become // obsolete or worked around more cleanly // this is relied upon *only* by the spell-check code if (pseudoModal && pseudoModal != (QWidget*)1L) delete pseudoModal; // pseudoModal = 0L; // if (old || w) recordReset(); pseudoModal = w; } void KateDocument::newBracketMark(PointStruc &cursor, BracketMark &bm) { TextLine::Ptr textLine; int x, line, count, attr; QChar bracket, opposite, ch; Attribute *a; bm.eXPos = -1; //mark bracked mark as invalid x = cursor.x -1; // -1 to look at left side of cursor if (x < 0) return; line = cursor.y; //current line count = 0; //bracket counter for nested brackets textLine = getTextLine(line); if (!textLine) return; bracket = textLine->getChar(x); attr = textLine->getAttr(x); if (bracket == '(' || bracket == '[' || bracket == '{') { //get opposite bracket opposite = ')'; if (bracket == '[') opposite = ']'; if (bracket == '{') opposite = '}'; //get attribute of bracket (opposite bracket must have the same attribute) x++; while (line - cursor.y < 40) { //go to next line on end of line while (x >= (int) textLine->length()) { line++; if (line > lastLine()) return; textLine = getTextLine(line); x = 0; } if (textLine->getAttr(x) == attr) { //try to find opposite bracked ch = textLine->getChar(x); if (ch == bracket) count++; //same bracket : increase counter if (ch == opposite) { count--; if (count < 0) goto found; } } x++; } } else if (bracket == ')' || bracket == ']' || bracket == '}') { opposite = '('; if (bracket == ']') opposite = '['; if (bracket == '}') opposite = '{'; x--; while (cursor.y - line < 20) { while (x < 0) { line--; if (line < 0) return; textLine = getTextLine(line); x = textLine->length() -1; } if (textLine->getAttr(x) == attr) { ch = textLine->getChar(x); if (ch == bracket) count++; if (ch == opposite) { count--; if (count < 0) goto found; } } x--; } } return; found: //cursor position of opposite bracket bm.cursor.x = x; bm.cursor.y = line; //x position (start and end) of related bracket bm.sXPos = textWidth(textLine, x); a = &m_attribs[attr]; if (a->bold && a->italic) bm.eXPos = bm.sXPos + myFontMetricsBI.width(bracket); else if (a->bold) bm.eXPos = bm.sXPos + myFontMetricsBold.width(bracket); else if (a->italic) bm.eXPos = bm.sXPos + myFontMetricsItalic.width(bracket); else bm.eXPos = bm.sXPos + myFontMetrics.width(bracket); } void KateDocument::clipboardChanged() { //slot //#if defined(_WS_X11_) if (m_singleSelection) { disconnect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(clipboardChanged())); deselectAll(); updateViews(); } //#endif } #if 0 void KateDocument::guiActivateEvent( KParts::GUIActivateEvent *ev ) { KParts::ReadWritePart::guiActivateEvent( ev ); if ( ev->activated() ) emit selectionChanged(); } #endif void KateDocument::setDocName (QString docName) { myDocName = docName; emit nameChanged (this); } void KateDocument::setDocFile (QString docFile) { m_file = docFile; emit fileNameChanged (); } void KateDocument::setMTime() { if (fileInfo && !fileInfo->fileName().isEmpty()) { fileInfo->refresh(); mTime = fileInfo->lastModified(); } } void KateDocument::isModOnHD(bool forceReload) { if (fileInfo && !fileInfo->fileName().isEmpty()) { fileInfo->refresh(); if (fileInfo->lastModified() > mTime) { if ( forceReload || (KMessageBox::warningContinueCancel(0, (i18n("The file %1 has changed on disk.\nDo you want to reload it?\n\nIf you cancel you will lose these changes next time you save this file")).arg(m_url), i18n("File has changed on Disk"), i18n("Yes") ) == KMessageBox::Continue) ) reloadFile(); else setMTime(); } } } void KateDocument::reloadFile() { #warning fixme #if 0 if (fileInfo && !fileInfo->fileName().isEmpty()) { KateDocument::openFile(); setMTime(); } #endif } void KateDocument::slotModChanged() { emit modStateChanged (this); } QList<Kate::Mark> KateDocument::marks () { QList<Kate::Mark> list; TextLine::Ptr line; for (int i=0; i < numLines(); i++) { line = getTextLine(i); if (line->mark() != 0) { Kate::Mark *mark=new Kate::Mark; mark->line = i; mark->type = line->mark(); list.append (mark); } } return list; } void KateDocument::flush () { if (isReadOnly()) return; m_url = QString::null; fileInfo->setFile (QString()); setMTime(); clear(); updateViews(); emit fileNameChanged (); } void KateDocument::open (const QString &name) { openURL (name); } void KateDocument::wrapText (uint col) { int line = 0; int z = 0; while(true) { TextLine::Ptr l = getTextLine(line); if (l->length() > col) { TextLine::Ptr tl = new TextLine(); buffer->insertLine(line+1,tl); const QChar *text = l->getText(); for (z=col; z>0; z--) { if (z < 1) break; if (text[z].isSpace()) break; } if (z < 1) z=col; l->wrap (tl, z); } line++; if (line >= numLines()) break; }; newDocGeometry=true; updateLines(); updateViews(); } void KateDocument::setWordWrap (bool on) { if (on != myWordWrap && on) wrapText (myWordWrapAt); myWordWrap = on; } void KateDocument::setWordWrapAt (uint col) { if (myWordWrapAt != col && myWordWrap) wrapText (myWordWrapAt); myWordWrapAt = col; } void KateDocument::applyWordWrap () { wrapText (myWordWrapAt); } diff --git a/noncore/settings/sysinfo/devicesinfo.cpp b/noncore/settings/sysinfo/devicesinfo.cpp index 164d608..428cfd4 100644 --- a/noncore/settings/sysinfo/devicesinfo.cpp +++ b/noncore/settings/sysinfo/devicesinfo.cpp @@ -1,433 +1,433 @@ /* This file is part of the Opie Project =. Copyright (C) 2005 Michael 'Mickey' Lauer <mickey@Vanille.de> .=l. Copyright (C) The Opie Team <opie-devel@handhelds.org> .>+-= _;:, .> :=|. This program is free software; you can .> <`_, > . <= redistribute it and/or modify it under :`=1 )Y*s>-.-- : the terms of the GNU General Public .="- .-=="i, .._ License as published by the Free Software - . .-<_> .<> Foundation; version 2 of the License. ._= =} : .%`+i> _;_. .i_,=:_. -<s. This program is distributed in the hope that + . -:. = it will be useful, but WITHOUT ANY WARRANTY; : .. .:, . . . without even the implied warranty of =_ + =;=|` MERCHANTABILITY or FITNESS FOR A _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU ..}^=.= = ; General Public License for more ++= -. .` .: details. : = ...= . :.=- -. .:....=;==+<; You should have received a copy of the GNU -_. . . )=. = General Public License along with -- :-=` this application; see the file LICENSE.GPL. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "devicesinfo.h" /* OPIE */ #include <opie2/odebug.h> #include <opie2/oinputsystem.h> #include <opie2/opcmciasystem.h> #include <opie2/olayout.h> #include <opie2/olistview.h> #include <qpe/qpeapplication.h> using namespace Opie::Core; using namespace Opie::Ui; /* QT */ #include <qobjectlist.h> #include <qlistview.h> #include <qcombobox.h> #include <qfile.h> #include <qpushbutton.h> #include <qstringlist.h> #include <qtextstream.h> #include <qtextview.h> #include <qtimer.h> #include <qwhatsthis.h> //================================================================================================= DevicesView::DevicesView( QWidget* parent, const char* name, WFlags fl ) :Opie::Ui::OListView( parent, name, fl ) { addColumn( tr( "My Computer" ) ); setAllColumnsShowFocus( true ); setRootIsDecorated( true ); QWhatsThis::add( this, tr( "This is a list of all the devices currently recognized on this device." ) ); DevicesView* root = this; ( new CpuCategory( root ) )->populate(); ( new InputCategory( root ) )->populate(); ( new CardsCategory( root ) )->populate(); ( new UsbCategory( root ) )->populate(); connect( this, SIGNAL(selectionChanged(QListViewItem*)), this, SLOT(selectionChanged(QListViewItem*)) ); } DevicesView::~DevicesView() { } void DevicesView::selectionChanged( QListViewItem* item ) { odebug << "DevicesView::selectionChanged to '" << item->text( 0 ) << "'" << oendl; if ( item->parent() ) { QWidget* details = ( static_cast<Device*>( item ) )->detailsWidget(); ( static_cast<DevicesInfo*>( parent() ) )->setDetailsWidget( details ); } else { odebug << "DevicesView::not a device node." << oendl; } } //================================================================================================= DevicesInfo::DevicesInfo( QWidget* parent, const char* name, WFlags fl ) :QWidget( parent, name, fl ), details( 0 ) { layout = new OAutoBoxLayout( this ); layout->setSpacing( 2 ); layout->setMargin( 2 ); view = new DevicesView( this ); layout->addWidget( view, 100 ); stack = new QWidgetStack( this ); layout->addWidget( stack, 80 ); } DevicesInfo::~DevicesInfo() { } void DevicesInfo::setDetailsWidget( QWidget* w ) { if ( details ) { qDebug( "hiding widget '%s' ('%s')", details->name(), details->className() ); stack->removeWidget( w ); } stack->addWidget( details = w, 40 ); stack->raiseWidget( details ); } //================================================================================================= Category::Category( DevicesView* parent, const QString& name ) :OListViewItem( parent, name ) { odebug << "Category '" << name << "' inserted. Scanning for devices..." << oendl; } Category::~Category() { } //================================================================================================= CpuCategory::CpuCategory( DevicesView* parent ) :Category( parent, "1. Central Processing Unit" ) { } CpuCategory::~CpuCategory() { } void CpuCategory::populate() { odebug << "CpuCategory::populate()" << oendl; QFile cpuinfofile( "/proc/cpuinfo" ); if ( !cpuinfofile.exists() || !cpuinfofile.open( IO_ReadOnly ) ) { new CpuDevice( this, "(no cpu found)" ); return; } QTextStream cpuinfo( &cpuinfofile ); int cpucount = 0; CpuDevice* dev = 0; while ( !cpuinfo.atEnd() ) { QString line = cpuinfo.readLine(); odebug << "got line '" << line << "'" << oendl; if ( line.lower().startsWith( "processor" ) ) { dev = new CpuDevice( this, QString( "CPU #%1" ).arg( cpucount++ ) ); dev->addInfo( line ); } else { if ( dev ) dev->addInfo( line ); } } } //================================================================================================= InputCategory::InputCategory( DevicesView* parent ) :Category( parent, "2. Input Subsystem" ) { } InputCategory::~InputCategory() { } void InputCategory::populate() { odebug << "InputCategory::populate()" << oendl; OInputSystem* sys = OInputSystem::instance(); OInputSystem::DeviceIterator it = sys->iterator(); while ( it.current() ) { InputDevice* dev = new InputDevice( this, it.current()->identity() ); dev->setInfo( it.current() ); ++it; } } //================================================================================================= CardsCategory::CardsCategory( DevicesView* parent ) :Category( parent, "3. Removable Cards" ) { } CardsCategory::~CardsCategory() { } void CardsCategory::populate() { odebug << "CardsCategory::populate()" << oendl; OPcmciaSystem* sys = OPcmciaSystem::instance(); OPcmciaSystem::CardIterator it = sys->iterator(); while ( it.current() ) { CardDevice *dev = new CardDevice( this, it.current()->identity() ); dev->setInfo( it.current() ); ++it; } } //================================================================================================= UsbCategory::UsbCategory( DevicesView* parent ) :Category( parent, "4. Universal Serial Bus" ) { } UsbCategory::~UsbCategory() { } void UsbCategory::populate() { odebug << "UsbCategory::populate()" << oendl; QFile usbinfofile( "/proc/bus/usb/devices" ); if ( !usbinfofile.exists() || !usbinfofile.open( IO_ReadOnly ) ) { new UsbDevice( this, "(no USB found)" ); return; } QTextStream usbinfo( &usbinfofile ); int _bus, _level, _parent, _port, _count, _device, _channels, _power; float _speed; QString _manufacturer, _product, _serial; int usbcount = 0; UsbDevice* lastDev = 0; UsbDevice* dev = 0; while ( !usbinfo.atEnd() ) { QString line = usbinfo.readLine(); odebug << "got line '" << line << "'" << oendl; if ( line.startsWith( "T:" ) ) { sscanf(line.local8Bit().data(), "T: Bus=%2d Lev=%2d Prnt=%2d Port=%d Cnt=%2d Dev#=%3d Spd=%3f MxCh=%2d", &_bus, &_level, &_parent, &_port, &_count, &_device, &_speed, &_channels); if ( !_level ) { odebug << "adding new bus" << oendl; dev = new UsbDevice( this, QString( "Generic USB Hub Device" ) ); lastDev = dev; } else { odebug << "adding new dev" << oendl; dev = new UsbDevice( lastDev, QString( "Generic USB Hub Device" ) ); lastDev = dev; } } - else if ( line.startsWith( "S: Product" ) ) + else if ( dev && line.startsWith( "S: Product" ) ) { int dp = line.find( '=' ); dev->setText( 0, dp != -1 ? line.right( line.length()-1-dp ) : "<unknown>" ); } else { continue; } } } //================================================================================================= Device::Device( Category* parent, const QString& name ) :OListViewItem( parent, name ) { devinfo = static_cast<QWidget*>( listView()->parent() ); } Device::Device( Device* parent, const QString& name ) :OListViewItem( parent, name ) { devinfo = static_cast<QWidget*>( listView()->parent() ); } Device::~Device() { } QWidget* Device::detailsWidget() { return details; } //================================================================================================= CpuDevice::CpuDevice( Category* parent, const QString& name ) :Device( parent, name ) { OListView* w = new OListView( devinfo ); details = w; w->addColumn( "Info" ); w->addColumn( "Value" ); w->hide(); } CpuDevice::~CpuDevice() { } void CpuDevice::addInfo( const QString& info ) { int dp = info.find( ':' ); if ( dp != -1 ) { new OListViewItem( (OListView*) details, info.left( dp ), info.right( info.length()-dp ) ); } } //================================================================================================= CardDevice::CardDevice( Category* parent, const QString& name ) :Device( parent, name ) { OListView* w = new OListView( devinfo ); details = w; w->addColumn( "Info" ); w->addColumn( "Value" ); w->hide(); } void CardDevice::setInfo( const OPcmciaSocket* card ) { QStringList vendorlst = card->productIdentityVector(); for( QStringList::Iterator it = vendorlst.begin(); it != vendorlst.end(); ++it ) { new OListViewItem( (OListView*) details, "VendorID", *it ); } new OListViewItem( (OListView*) details, "Manufacturer", card->manufacturerIdentity() ); new OListViewItem( (OListView*) details, "Function", card->function() ); QStringList text; OPcmciaSocket::OPcmciaSocketCardStatus status = card->status(); if ( status ) { if ( status & OPcmciaSocket::Occupied ) text += "Occupied"; if ( status & OPcmciaSocket::OccupiedCardBus ) text += "CardBus"; if ( status & OPcmciaSocket::WriteProtected ) text += "WriteProtected"; if ( status & OPcmciaSocket::BatteryLow ) text += "BatteryLow"; if ( status & OPcmciaSocket::BatteryDead ) text += "BatteryDead"; if ( status & OPcmciaSocket::Ready ) text += "Ready"; if ( status & OPcmciaSocket::Suspended ) text += "Suspended"; if ( status & OPcmciaSocket::Attention ) text += "Attention"; if ( status & OPcmciaSocket::InsertionInProgress ) text += "InsertionInProgress"; if ( status & OPcmciaSocket::RemovalInProgress ) text += "RemovalInProgress"; if ( status & OPcmciaSocket::ThreeVolts ) text += "3V"; if ( status & OPcmciaSocket::SupportsVoltage ) text += "SupportsVoltage"; } else { text += "<unknown>"; } new OListViewItem( (OListView*) details, "Status", text.join( ", " ) ); } CardDevice::~CardDevice() { } //================================================================================================= InputDevice::InputDevice( Category* parent, const QString& name ) :Device( parent, name ) { OListView* w = new OListView( devinfo ); details = w; w->addColumn( "Info" ); w->addColumn( "Value" ); w->hide(); } void InputDevice::setInfo( const OInputDevice* dev ) { new OListViewItem( (OListView*) details, "Identity", dev->identity() ); new OListViewItem( (OListView*) details, "Path", dev->path() ); new OListViewItem( (OListView*) details, "Unique", dev->uniq() ); QStringList text; if ( dev->hasFeature( OInputDevice::Synchronous ) ) text += "Synchronous"; if ( dev->hasFeature( OInputDevice::Keys ) ) text += "Keys"; if ( dev->hasFeature( OInputDevice::Relative ) ) text += "Relative"; if ( dev->hasFeature( OInputDevice::Absolute ) ) text += "Absolute"; if ( dev->hasFeature( OInputDevice::Miscellaneous ) ) text += "Miscellaneous"; if ( dev->hasFeature( OInputDevice::Switches ) ) text += "Switches"; if ( dev->hasFeature( OInputDevice::Leds ) ) text += "Leds"; if ( dev->hasFeature( OInputDevice::Sound ) ) text += "Sound"; if ( dev->hasFeature( OInputDevice::AutoRepeat ) ) text += "AutoRepeat"; if ( dev->hasFeature( OInputDevice::ForceFeedback ) ) text += "ForceFeedback"; if ( dev->hasFeature( OInputDevice::PowerManagement ) ) text += "PowerManagement"; if ( dev->hasFeature( OInputDevice::ForceFeedbackStatus ) ) text += "ForceFeedbackStatus"; new OListViewItem( (OListView*) details, "Features", text.join( ", " ) ); } InputDevice::~InputDevice() { } //================================================================================================= UsbDevice::UsbDevice( Category* parent, const QString& name ) :Device( parent, name ) { details = new QPushButton( name, devinfo ); details->hide(); } //================================================================================================= UsbDevice::UsbDevice( UsbDevice* parent, const QString& name ) :Device( parent, name ) { details = new QPushButton( name, devinfo ); details->hide(); } UsbDevice::~UsbDevice() { } diff --git a/noncore/todayplugins/stockticker/libstocks/http.c b/noncore/todayplugins/stockticker/libstocks/http.c index 2f38f8a..cc78ab7 100644 --- a/noncore/todayplugins/stockticker/libstocks/http.c +++ b/noncore/todayplugins/stockticker/libstocks/http.c @@ -1,303 +1,303 @@ /* libstocks - Library to get current stock quotes from Yahoo Finance * * Copyright (C) 2000 Eric Laeuffer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #define __HTTP_C__ #ifndef __UNIX__ #define __UNIX__ #endif #ifdef __UNIX__ #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <unistd.h> #elif __WINDOWS__ #include <winsock.h> #include <mbstring.h> #endif #include <sys/types.h> #include <ctype.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #include "http.h" #include "stocks.h" #define BUF_SIZE 1024 #define HEADER_MAXBUF 512 /* pointer to proxy server name or NULL */ char *http_proxy_server=NULL; /* proxy server port number or 0 */ int http_proxy_port=0; /*****************************************************************************/ /* Gets the file from http://http_server/http_file */ /* This function is used to get quotes csv file from yahoo. */ /* It allocates memory for the file and defines *pdata (the pointer of datas)*/ /*****************************************************************************/ libstocks_return_code http_get(char *http_file, char *http_server, char **pdata) { struct hostent *host; /* structs needed by socket */ struct sockaddr_in server; int s; /* socket descriptor */ char header[HEADER_MAXBUF]; /* request header */ int hlg; /* header length */ char buf[BUF_SIZE+1]; /* tempory buffer from socket read */ int r; /* number of bytes read by read function */ char *data=NULL; /* http server response */ int data_lgr; /* http server response length */ char *temp; /* pointer used to split header and csv */ int error_code; /* error code returned by http server */ char *csv_ptr; /* pointer to the csv content */ int header_founded; /* test if header is founded */ #ifdef DEBUG printf("*http_get\n"); #endif /* get host info by name :*/ if ((host = gethostbyname( http_proxy_server ? http_proxy_server : http_server))) { memset((char *) &server,0, sizeof(server)); memmove((char *) &server.sin_addr, host->h_addr, host->h_length); server.sin_family = host->h_addrtype; server.sin_port = (unsigned short) htons( http_proxy_server ? http_proxy_port : 80 ); } else { #ifdef DEBUG printf(" gethostbyname : NOK\n"); #endif return ERRHOST; } /* create socket */ if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { #ifdef DEBUG printf(" create socket : NOK\n"); #endif return ERRSOCK; } setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, 0, 0); /* connect to server */ if (connect(s, &server, sizeof(server)) < 0) { #ifdef DEBUG printf(" connect to server : NOK\n"); #endif #ifdef __UNIX__ close(s); #elif __WINDOWS__ closesocket(s); #endif return ERRCONN; } /* create header */ if (http_proxy_server) { sprintf(header,"GET http://%.128s:80%.256s HTTP/1.0\015\012\015\012", http_server, http_file); } else { sprintf(header,"GET %s HTTP/1.0\015\012\015\012",http_file); } hlg=strlen(header); /* send header */ #ifdef __UNIX__ if (write(s,header,hlg)!=hlg) #elif __WINDOWS__ if (send(s,header,hlg, 0)!=hlg) #endif { #ifdef DEBUG printf(" send header : NOK\n"); #endif return ERRWHEA; } data_lgr = 0; r=1; while(r) { /* Clear Buffer */ memset(buf,0,BUF_SIZE+1); #ifdef __UNIX__ r=read(s,buf,BUF_SIZE); #elif __WINDOWS__ r=recv(s,buf,BUF_SIZE,0); #endif if (r) { if(!data_lgr) { if((data = malloc(r+1))==NULL) { fprintf(stderr,"Memory allocating error (%s line %d)\n" ,__FILE__, __LINE__); exit(1); } memcpy(data,buf,r); data_lgr = r; data[r]=0; } else { if((temp = malloc(r+data_lgr+1))==NULL) { fprintf(stderr,"Memory allocating error (%s line %d)\n" ,__FILE__, __LINE__); exit(1); } memcpy(temp, data, data_lgr); memcpy(temp+data_lgr, buf, r); temp[r+data_lgr]=0; data_lgr += r; free(data); data = temp; } } } /* close socket */ #ifdef __UNIX__ close(s); #elif __WINDOWS__ closesocket(s); #endif #ifdef DEBUG printf("%s\n", data); #endif /* get headers to test status line */ /* and to split headers and content */ temp = data; header_founded = 0; while( !header_founded ) { - if (*temp==0) return ERRRHEA; + if (!temp || *temp==0) return ERRRHEA; if( *temp==0x0A ) { /* test if it is the header end */ temp ++; if (*temp == 0x0D) temp++; if (*temp == 0x0A) header_founded = 1; } else temp++; } *temp = 0; temp++; sscanf(data,"HTTP/1.%*d %03d",&error_code); if (error_code != 200) { #ifdef DEBUG printf(" HTTP error code : %d\n", error_code); #endif free(data); return ERRPAHD; } if ((csv_ptr = malloc(strlen(temp)+1))==NULL) { free(data); fprintf(stderr,"Memory allocating error (%s line %d)\n" ,__FILE__, __LINE__); exit(1); } memcpy(csv_ptr, temp, strlen(temp)+1); free(data); #ifdef DEBUG printf(" CSV\n"); printf("%s,\n", csv_ptr); #endif *pdata = csv_ptr; return 0; } /******************************************************************************/ /* Set the proxy server to use */ /******************************************************************************/ libstocks_return_code set_proxy(char *proxy) { char *ptr; char c; #ifdef DEBUG printf("*set_proxy\n"); #endif /* Parse the proxy URL - It must start with http:// */ #ifdef __UNIX__ if (strncasecmp("http://",proxy,7)) return ERRPROX; #elif __WINDOWS__ if (_mbsnbicmp("http://",proxy,7)) return ERRPROX; #endif proxy+=7; /* find ":" in the proxy url */ ptr = proxy; for (c=*ptr; (c && c!=':');) c=*ptr++; /* ptr points just after the ":" or at the end of proxy if : not founded */ *(ptr-1)=0; /* clear the ":" */ http_proxy_server=strdup(proxy); #ifdef DEBUG printf("http_proxy_server : %s\n", http_proxy_server); #endif /* get the port number of the url */ if (sscanf(ptr,"%d",&http_proxy_port)!=1) return ERRPROX; #ifdef DEBUG printf("http_proxy_port : %d\n", http_proxy_port); #endif return 0; } |