author | erik <erik> | 2007-01-22 23:01:41 (UTC) |
---|---|---|
committer | erik <erik> | 2007-01-22 23:01:41 (UTC) |
commit | adcf6075db477909dd8170a74862a6ef91a5127f (patch) (side-by-side diff) | |
tree | da0a1e35c5d392271bce29e84d3af5c30a864f56 /noncore | |
parent | 9b4871054d01a47b4c546952a0948553413840d6 (diff) | |
download | opie-adcf6075db477909dd8170a74862a6ef91a5127f.zip opie-adcf6075db477909dd8170a74862a6ef91a5127f.tar.gz opie-adcf6075db477909dd8170a74862a6ef91a5127f.tar.bz2 |
Each file in this commit had a problem where a function might return
a null value for a pointer and that null value was not checked.
-rw-r--r-- | noncore/games/minesweep/minefield.cpp | 4 | ||||
-rw-r--r-- | noncore/net/opieirc/ircsession.cpp | 8 | ||||
-rw-r--r-- | noncore/todayplugins/stockticker/libstocks/csv.c | 3 |
3 files changed, 10 insertions, 5 deletions
diff --git a/noncore/games/minesweep/minefield.cpp b/noncore/games/minesweep/minefield.cpp index 72c05b0..1987ea5 100644 --- a/noncore/games/minesweep/minefield.cpp +++ b/noncore/games/minesweep/minefield.cpp @@ -1,747 +1,749 @@ /********************************************************************** ** 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. ** **********************************************************************/ #include "minefield.h" #include <qtopia/config.h> #include <qtopia/qpeapplication.h> #include <qtimer.h> #include <stdlib.h> static const char *pix_flag[]={ "13 13 3 1", "# c #000000", "x c #ff0000", ". c None", ".............", ".............", ".....#xxxxxx.", ".....#xxxxxx.", ".....#xxxxxx.", ".....#xxxxxx.", ".....#.......", ".....#.......", ".....#.......", ".....#.......", "...#####.....", "..#######....", "............."}; static const char *pix_mine[]={ "13 13 3 1", "# c #000000", ". c None", "a c #ffffff", "......#......", "......#......", "..#.#####.#..", "...#######...", "..##aa#####..", "..##aa#####..", "#############", "..#########..", "..#########..", "...#######...", "..#.#####.#..", "......#......", "......#......"}; static const int maxGrid = 28; static const int minGrid = 12; class Mine : public Qt { public: enum MineState { Hidden = 0, Empty, Mined, Flagged, #ifdef MARK_UNSURE Unsure, #endif Exploded, Wrong }; Mine( MineField* ); void paint( QPainter * p, const QColorGroup & cg, const QRect & cr ); QSize sizeHint() const { return QSize( maxGrid, maxGrid ); } void activate( bool sure = TRUE ); void setHint( int ); void setState( MineState ); MineState state() const { return st; } bool isMined() const { return mined; } void setMined( bool m ) { mined = m; } static void paletteChange(); private: bool mined; int hint; MineState st; MineField *field; static QPixmap* knownField; static QPixmap* unknownField; static QPixmap* flag_pix; static QPixmap* mine_pix; }; QPixmap* Mine::knownField = 0; QPixmap* Mine::unknownField = 0; QPixmap* Mine::flag_pix = 0; QPixmap* Mine::mine_pix = 0; Mine::Mine( MineField *f ) { mined = FALSE; st = Hidden; hint = 0; field = f; } void Mine::activate( bool sure ) { if ( !sure ) { switch ( st ) { case Hidden: setState( Flagged ); break; case Flagged: #ifdef MARK_UNSURE setState( Unsure ); break; case Unsure: #endif setState( Hidden ); default: break; } } else if ( st == Flagged ) { return; } else { if ( mined ) { setState( Exploded ); } else { setState( Empty ); } } } void Mine::setState( MineState s ) { st = s; } void Mine::setHint( int h ) { hint = h; } void Mine::paletteChange() { delete knownField; knownField = 0; delete unknownField; unknownField = 0; delete mine_pix; mine_pix = 0; delete flag_pix; flag_pix = 0; } void Mine::paint( QPainter* p, const QColorGroup &cg, const QRect& cr ) { int x = cr.x(); int y = cr.y(); if ( !knownField || knownField->width() != cr.width() || knownField->height() != cr.height() ) { delete knownField; knownField = new QPixmap( cr.width(), cr.height() ); QPainter pp( knownField ); QBrush br( cg.button().dark(115) ); qDrawWinButton( &pp, QRect( 0, 0, cr.width(), cr.height() ), cg, TRUE, &br ); } const int pmmarg=cr.width()/5; if ( !unknownField || unknownField->width() != cr.width() || unknownField->height() != cr.height() ) { delete unknownField; unknownField = new QPixmap( cr.width(), cr.height() ); QPainter pp( unknownField ); QBrush br( cg.button() ); qDrawWinButton( &pp, QRect( 0, 0, cr.width(), cr.height() ), cg, FALSE, &br ); } if ( !flag_pix || flag_pix->width() != cr.width()-pmmarg*2 || flag_pix->height() != cr.height()-pmmarg*2 ) { delete flag_pix; flag_pix = new QPixmap( cr.width()-pmmarg*2, cr.height()-pmmarg*2 ); flag_pix->convertFromImage( QImage(pix_flag).smoothScale(cr.width()-pmmarg*2, cr.height()-pmmarg*2) ); } if ( !mine_pix || mine_pix->width() != cr.width()-pmmarg*2 || mine_pix->height() != cr.height()-pmmarg*2 ) { delete mine_pix; mine_pix = new QPixmap( cr.width()-pmmarg*2, cr.height()-pmmarg*2 ); mine_pix->convertFromImage( QImage(pix_mine).smoothScale(cr.width()-pmmarg*2, cr.height()-pmmarg*2) ); } p->save(); switch(st) { case Hidden: p->drawPixmap( x, y, *unknownField ); break; case Empty: p->drawPixmap( x, y, *knownField ); if ( hint > 0 ) { switch( hint ) { case 1: p->setPen( blue ); break; case 2: p->setPen( green.dark() ); break; case 3: p->setPen( red ); break; case 4: p->setPen( darkYellow.dark() ); break; case 5: p->setPen( darkMagenta ); break; case 6: p->setPen( darkRed ); break; default: p->setPen( black ); break; } p->drawText( cr, AlignHCenter | AlignVCenter, QString::number( hint ) ); } break; case Mined: p->drawPixmap( x, y, *knownField ); p->drawPixmap( x+pmmarg, y+pmmarg, *mine_pix ); break; case Exploded: p->drawPixmap( x, y, *knownField ); p->drawPixmap( x+pmmarg, y+pmmarg, *mine_pix ); p->setPen( red ); p->drawText( cr, AlignHCenter | AlignVCenter, "X" ); break; case Flagged: p->drawPixmap( x, y, *unknownField ); p->drawPixmap( x+pmmarg, y+pmmarg, *flag_pix ); break; #ifdef MARK_UNSURE case Unsure: p->drawPixmap( x, y, *unknownField ); p->drawText( cr, AlignHCenter | AlignVCenter, "?" ); break; #endif case Wrong: p->drawPixmap( x, y, *unknownField ); p->drawPixmap( x+pmmarg, y+pmmarg, *flag_pix ); p->setPen( red ); p->drawText( cr, AlignHCenter | AlignVCenter, "X" ); break; } p->restore(); } /* MineField implementation */ MineField::MineField( QWidget* parent, const char* name ) : QScrollView( parent, name ) { viewport()->setBackgroundMode( NoBackground ); setState( GameOver ); setSizePolicy( QSizePolicy( QSizePolicy::Maximum, QSizePolicy::Maximum ) ); setFocusPolicy( QWidget::NoFocus ); holdTimer = new QTimer( this ); connect( holdTimer, SIGNAL( timeout() ), this, SLOT( held() ) ); flagAction = NoAction; ignoreClick = FALSE; currRow = currCol = -1; minecount=0; mineguess=0; nonminecount=0; cellSize = -1; numRows = numCols = 0; mines = NULL; } MineField::~MineField() { for ( int i = 0; i < numCols*numRows; i++ ) delete mines[i]; delete[] mines; } void MineField::setState( State st ) { stat = st; } void MineField::setup( int level ) { lev = level; setState( Waiting ); //viewport()->setUpdatesEnabled( FALSE ); int i; for ( i = 0; i < numCols*numRows; i++ ) delete mines[i]; delete[] mines; switch( lev ) { case 1: numRows = 9 ; numCols = 9 ; minecount = 12; break; case 2: numRows = 13; numCols = 13; minecount = 33; break; case 3: numCols = 18; numRows = 18; minecount = 66 ; break; } mines = new Mine* [numRows*numCols]; for ( i = 0; i < numCols*numRows; i++ ) mines[i] = new Mine( this ); nonminecount = numRows*numCols - minecount; mineguess = minecount; emit mineCount( mineguess ); Mine::paletteChange(); if ( availableRect.isValid() ) setCellSize(findCellSize()); // viewport()->setUpdatesEnabled( TRUE ); //viewport()->repaint( TRUE ); updateContents( 0, 0, numCols*cellSize, numRows*cellSize ); updateGeometry(); } void MineField::drawContents( QPainter * p, int clipx, int clipy, int clipw, int cliph ) { int c1 = clipx / cellSize; int c2 = ( clipx + clipw - 1 ) / cellSize; int r1 = clipy / cellSize; int r2 = ( clipy + cliph - 1 ) / cellSize; for ( int c = c1; c <= c2 ; c++ ) { for ( int r = r1; r <= r2 ; r++ ) { int x = c * cellSize; int y = r * cellSize; Mine *m = mine( r, c ); if ( m ) m->paint( p, colorGroup(), QRect(x, y, cellSize, cellSize ) ); } } } // Chicken and egg problem: We need to know how big the parent is // before we can decide how big to make the table. void MineField::setAvailableRect( const QRect &r ) { availableRect = r; int newCellSize = findCellSize(); if ( newCellSize == cellSize ) { setCellSize( cellSize ); } else { viewport()->setUpdatesEnabled( FALSE ); setCellSize( newCellSize ); viewport()->setUpdatesEnabled( TRUE ); viewport()->repaint( TRUE ); } } int MineField::findCellSize() { int w = availableRect.width() - 2; int h = availableRect.height() - 2; int cellsize; cellsize = QMIN( w/numCols, h/numRows ); cellsize = QMIN( QMAX( cellsize, minGrid ), maxGrid ); return cellsize; } void MineField::setCellSize( int cellsize ) { int b = 2; int w2 = cellsize*numCols; int h2 = cellsize*numRows; int w = QMIN( availableRect.width(), w2+b ); int h = QMIN( availableRect.height(), h2+b ); // // Don't rely on the change in cellsize to force a resize, // as it's possible to have the same size cells when going // from a large play area to a small one. // resizeContents(w2, h2); if ( availableRect.height() < h2 && availableRect.width() - w > style().scrollBarExtent().width() ) { w += style().scrollBarExtent().width(); } setGeometry( availableRect.x() + (availableRect.width()-w)/2, availableRect.y() + (availableRect.height()-h)/2, w, h ); cellSize = cellsize; } void MineField::placeMines() { int mines = minecount; while ( mines ) { int col = int((double(rand()) / double(RAND_MAX)) * numCols); int row = int((double(rand()) / double(RAND_MAX)) * numRows); Mine* m = mine( row, col ); if ( m && !m->isMined() && m->state() == Mine::Hidden ) { m->setMined( TRUE ); mines--; } } } void MineField::updateCell( int r, int c ) { updateContents( c*cellSize, r*cellSize, cellSize, cellSize ); } void MineField::contentsMousePressEvent( QMouseEvent* e ) { int c = e->pos().x() / cellSize; int r = e->pos().y() / cellSize; if ( onBoard( r, c ) ) cellPressed( r, c ); else currCol = currRow = -1; } void MineField::contentsMouseReleaseEvent( QMouseEvent* e ) { int c = e->pos().x() / cellSize; int r = e->pos().y() / cellSize; if ( onBoard( r, c ) && c == currCol && r == currRow ) cellClicked( r, c ); if ( flagAction == FlagNext ) { flagAction = NoAction; } } /* state == Waiting means no "hold" */ void MineField::cellPressed( int row, int col ) { if ( state() == GameOver ) return; currRow = row; currCol = col; if ( state() == Playing ) holdTimer->start( 150, TRUE ); } void MineField::held() { flagAction = FlagNext; updateMine( currRow, currCol ); ignoreClick = TRUE; } void MineField::keyPressEvent( QKeyEvent* e ) { #if defined(Q_WS_QWS) || defined(_WS_QWS_) flagAction = ( e->key() == Key_Up ) ? FlagOn : NoAction; #else flagAction = ( ( e->state() & ShiftButton ) == ShiftButton ) ? FlagOn : NoAction; #endif } void MineField::keyReleaseEvent( QKeyEvent* ) { flagAction = NoAction; } int MineField::getHint( int row, int col ) { int hint = 0; for ( int c = col-1; c <= col+1; c++ ) for ( int r = row-1; r <= row+1; r++ ) { Mine* m = mine( r, c ); if ( m && m->isMined() ) hint++; } return hint; } void MineField::setHint( int row, int col ) { Mine *m = mine( row, col ); if ( !m ) return; int hint = getHint( row, col ); if ( !hint ) { for ( int c = col-1; c <= col+1; c++ ) for ( int r = row-1; r <= row+1; r++ ) { Mine* m = mine( r, c ); if ( m && m->state() == Mine::Hidden ) { m->activate( TRUE ); nonminecount--; setHint( r, c ); updateCell( r, c ); } } } m->setHint( hint ); updateCell( row, col ); } /* Only place mines after first click, since it is pointless to kill the player before the game has started. */ void MineField::cellClicked( int row, int col ) { if ( state() == GameOver ) return; if ( state() == Waiting ) { Mine* m = mine( row, col ); if ( !m ) return; m->setState( Mine::Empty ); nonminecount--; placeMines(); setState( Playing ); emit gameStarted(); updateMine( row, col ); } else { // state() == Playing holdTimer->stop(); if ( ignoreClick ) ignoreClick = FALSE; else updateMine( row, col ); } } void MineField::updateMine( int row, int col ) { Mine* m = mine( row, col ); if ( !m ) return; bool wasFlagged = m->state() == Mine::Flagged; bool wasEmpty = m->state() == Mine::Empty; m->activate( flagAction == NoAction ); if ( m->state() == Mine::Exploded ) { emit gameOver( FALSE ); setState( GameOver ); return; } else if ( m->state() == Mine::Empty ) { setHint( row, col ); if ( !wasEmpty ) nonminecount--; } if ( flagAction != NoAction ) { if ( m->state() == Mine::Flagged ) { if (mineguess > 0) { --mineguess; emit mineCount( mineguess ); if ( m->isMined() ) --minecount; } else { m->setState(Mine::Hidden); } } else if ( wasFlagged ) { ++mineguess; emit mineCount( mineguess ); if ( m->isMined() ) ++minecount; } } updateCell( row, col ); if ( !minecount && !mineguess || !nonminecount ) { emit gameOver( TRUE ); setState( GameOver ); } } void MineField::showMines() { for ( int c = 0; c < numCols; c++ ) for ( int r = 0; r < numRows; r++ ) { Mine* m = mine( r, c ); if ( !m ) continue; if ( m->isMined() && m->state() == Mine::Hidden ) m->setState( Mine::Mined ); if ( !m->isMined() && m->state() == Mine::Flagged ) m->setState( Mine::Wrong ); updateCell( r, c ); } } void MineField::paletteChange( const QPalette &o ) { Mine::paletteChange(); QScrollView::paletteChange( o ); } void MineField::writeConfig(Config& cfg) const { cfg.setGroup("Field"); cfg.writeEntry("Level",lev); QString grid=""; if ( stat == Playing ) { for ( int x = 0; x < numCols; x++ ) for ( int y = 0; y < numRows; y++ ) { char code='A'+(x*17+y*101)%21; // Reduce the urge to cheat const Mine* m = mine( y, x ); int st = (int)m->state(); if ( m->isMined() ) st+=5; grid += code + st; } } cfg.writeEntry("Grid",grid); } void MineField::readConfig(Config& cfg) { cfg.setGroup("Field"); lev = cfg.readNumEntry("Level",1); setup(lev); flagAction = NoAction; ignoreClick = FALSE; currRow = currCol = 0; QString grid = cfg.readEntry("Grid"); int x; if ( !grid.isEmpty() ) { int i=0; minecount=0; mineguess=0; for ( x = 0; x < numCols; x++ ) { for ( int y = 0; y < numRows; y++ ) { char code='A'+(x*17+y*101)%21; // Reduce the urge to cheat int st = (char)(QChar)grid[i++]-code; Mine* m = mine( y, x ); + if (!m) + continue; if ( st >= 5 ) { st-=5; m->setMined(TRUE); minecount++; mineguess++; } m->setState((Mine::MineState)st); switch ( m->state() ) { case Mine::Flagged: if (m->isMined()) minecount--; mineguess--; break; case Mine::Empty: --nonminecount; break; default: break; } } } for ( x = 0; x < numCols; x++ ) { for ( int y = 0; y < numRows; y++ ) { Mine* m = mine( y, x ); - if ( m->state() == Mine::Empty ) + if ( m && m->state() == Mine::Empty ) m->setHint(getHint(y,x)); } } } setState( Playing ); emit mineCount( mineguess ); } QSize MineField::sizeHint() const { if ( qApp->desktop()->width() >= 240 ) return QSize(200,200); else return QSize(160, 160); } diff --git a/noncore/net/opieirc/ircsession.cpp b/noncore/net/opieirc/ircsession.cpp index c8d7869..d87ff80 100644 --- a/noncore/net/opieirc/ircsession.cpp +++ b/noncore/net/opieirc/ircsession.cpp @@ -1,216 +1,218 @@ #include "ircsession.h" #include "ircmessageparser.h" #include "ircchannelperson.h" #include "ircversion.h" IRCSession::IRCSession(QObject *parent, IRCServer *server) : QObject(parent) { m_server = server; m_connection = new IRCConnection(m_server); m_parser = new IRCMessageParser(this); connect(m_connection, SIGNAL(messageArrived(IRCMessage*)), this, SLOT(handleMessage(IRCMessage*))); connect(m_parser, SIGNAL(outputReady(IRCOutput)), this, SIGNAL(outputReady(IRCOutput))); connect(m_connection, SIGNAL(outputReady(IRCOutput)), this, SIGNAL(outputReady(IRCOutput))); } IRCSession::~IRCSession() { /* We want this to get deleted automatically */ m_channels.setAutoDelete(TRUE); m_people.setAutoDelete(TRUE); delete m_parser; delete m_connection; } void IRCSession::beginSession() { m_connection->doConnect(); } void IRCSession::join(QString channelname) { m_connection->sendLine("JOIN " + channelname); } void IRCSession::quit(){ m_connection->sendLine("QUIT :[OI] I'm too good to need a reason"); } void IRCSession::quit(QString message){ m_connection->sendLine("QUIT :" + message); } void IRCSession::topic(IRCChannel *channel, QString message){ m_connection->sendLine("TOPIC :" + channel->channelname() + " " + message); } void IRCSession::mode(IRCChannel *channel, QString message){ m_connection->sendLine("MODE " + channel->channelname() + " " + message); } void IRCSession::mode(IRCPerson *person, QString message){ m_connection->sendLine("MODE " + person->nick() + " " + message); } void IRCSession::mode(QString message){ m_connection->sendLine("MODE " + message); } void IRCSession::raw(QString message){ m_connection->sendLine(message); } void IRCSession::kick(IRCChannel *channel, IRCPerson *person) { m_connection->sendLine("KICK " + channel->channelname() + " " + person->nick() +" :0wn3d - no reason"); } void IRCSession::op(IRCChannel *channel, IRCPerson *person) { m_connection->sendLine("MODE " + channel->channelname() + " +ooo " + person->nick()); } void IRCSession::kick(IRCChannel *channel, IRCPerson *person, QString message) { m_connection->sendLine("KICK " + channel->channelname() + " " + person->nick() +" :" + message); } void IRCSession::sendMessage(IRCPerson *person, QString message) { m_connection->sendLine("PRIVMSG " + person->nick() + " :" + message); } void IRCSession::sendMessage(IRCChannel *channel, QString message) { m_connection->sendLine("PRIVMSG " + channel->channelname() + " :" + message); } void IRCSession::sendAction(IRCChannel *channel, QString message) { m_connection->sendLine("PRIVMSG " + channel->channelname() + " :\001ACTION " + message + "\001"); } void IRCSession::sendAction(IRCPerson *person, QString message) { m_connection->sendLine("PRIVMSG " + person->nick() + " :\001ACTION " + message + "\001"); } bool IRCSession::isSessionActive() { return m_connection->isConnected(); } bool IRCSession::isLoggedIn() { return m_connection->isLoggedIn(); } void IRCSession::endSession() { if (m_connection->isLoggedIn()) quit(APP_VERSION); else m_connection->close(); } void IRCSession::part(IRCChannel *channel) { m_connection->sendLine("PART " + channel->channelname() + " :" + APP_VERSION); } void IRCSession::setValidUsermodes(const QString &modes) { m_validUsermodes = modes; } void IRCSession::setValidChannelmodes(const QString &modes) { m_validChannelmodes = modes; } void IRCSession::updateNickname(const QString &oldNickname, const QString &newNickname) { QList<IRCChannel> channels; IRCOutput output; if (oldNickname == m_server->nick()) { m_server->setNick(newNickname); output = IRCOutput(OUTPUT_NICKCHANGE, tr("You are now known as %1").arg(newNickname)); channels = m_channels; } else { IRCPerson *person = getPerson(oldNickname); if(!person) { emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Nickname change of an unknown person"))); return; } getChannelsByPerson(person, channels); output = IRCOutput(OUTPUT_NICKCHANGE, tr("%1 is now known as %2").arg(oldNickname).arg(newNickname)); } QListIterator<IRCChannel> it(channels); for (;it.current(); ++it) { IRCChannelPerson *chanperson = it.current()->getPerson(oldNickname); - it.current()->removePerson(chanperson); - chanperson->setNick(newNickname); - it.current()->addPerson(chanperson); + if (chanperson) { + it.current()->removePerson(chanperson); + chanperson->setNick(newNickname); + it.current()->addPerson(chanperson); + } } emit updateChannels(); output.addParam(new QString(newNickname)); emit outputReady(output); } IRCChannel *IRCSession::getChannel(QString channelname) { QListIterator<IRCChannel> it(m_channels); for (; it.current(); ++it) { if (it.current()->channelname() == channelname) { return it.current(); } } return 0; } IRCPerson *IRCSession::getPerson(QString nickname) { QListIterator<IRCPerson> it(m_people); for (; it.current(); ++it) { if (it.current()->nick() == nickname) { return it.current(); } } return 0; } void IRCSession::getChannelsByPerson(IRCPerson *person, QList<IRCChannel> &channels) { QListIterator<IRCChannel> it(m_channels); for (; it.current(); ++it) { if (it.current()->getPerson(person->nick()) != 0) { channels.append(it.current()); } } } void IRCSession::addPerson(IRCPerson *person) { m_people.append(person); } void IRCSession::addChannel(IRCChannel *channel) { m_channels.append(channel); } void IRCSession::removeChannel(IRCChannel *channel) { m_channels.remove(channel); } void IRCSession::removePerson(IRCPerson *person) { m_people.remove(person); } void IRCSession::handleMessage(IRCMessage *message) { m_parser->parse(message); } void IRCSession::whois(const QString &nickname) { m_connection->whois(nickname); } void IRCSession::sendCTCPPing(const QString &nickname) { m_connection->sendCTCPPing(nickname); } void IRCSession::sendCTCPRequest(const QString &nickname, const QString &type, const QString &args) { m_connection->sendCTCPRequest(nickname, type, args); } void IRCSession::sendCTCPReply(const QString &nickname, const QString &type, const QString &args) { m_connection->sendCTCPReply(nickname, type, args); } diff --git a/noncore/todayplugins/stockticker/libstocks/csv.c b/noncore/todayplugins/stockticker/libstocks/csv.c index 6170bed..86d8607 100644 --- a/noncore/todayplugins/stockticker/libstocks/csv.c +++ b/noncore/todayplugins/stockticker/libstocks/csv.c @@ -1,405 +1,406 @@ /* 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 __CSV_C__ #ifndef __UNIX__ #define __UNIX__ #endif #include <string.h> #include <stdlib.h> #include <stdio.h> #ifdef __WINDOWS__ #include <mbstring.h> #endif #include "csv.h" #include "stocks.h" #include "lists.h" #define DATE_LENGTH 7 /*YYMMDD*/ const char *months[12]= { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; /*****************************************************************************/ /* Replacement of the strtok function. This one forgets "delim" when it is */ /* between two commas. */ /* Thanks to Julio Lucas who has told me the bug and has proposed me a patch */ /*****************************************************************************/ char *csv_strtok(char *s, char *delim) { static char *next=NULL; char *temp, *first; int comma=0; if (s!=NULL) first=s; else first=next; temp=first; if (*temp=='\0') return NULL; while (*temp!='\0' && ((*temp!=*delim) || comma)) { if (*temp=='"') comma ^= 1; temp++; } if (*temp=='\0') next=temp; else { *temp='\0'; next=temp+1; } return first; } /*****************************************************************************/ /* Parses the csv file and return a list of stocks structure. */ /* *csv points on the csv file in memory */ /* count defines the country, because csv depends on the country */ /*****************************************************************************/ stock *parse_csv_file(char *csv) { char *line; char *end_line; char *ptr; char *date; char *time; char *name; char *symbol; stock *StockPtr=NULL; stock *LastStockPtr=NULL; /* Used to return the pointer to the list */ stock *FirstStockPtr=NULL; /* used to see if symbol is valid */ int valid; char *test; line = csv; end_line = csv; while ((end_line = strstr(line, "\n"))) { *end_line = 0; /* Check if symbol valid */ /* if 1 "N/A" then ok because Indices have N/A for volume */ /* if 4 "N/A" then ok because Mutual funds have */ /* if 5 "N/A" then ok because currencies have */ /* So if >5 then stock not valid */ test = line; valid = 0; while ( (test = strstr(test, "N/A")) ) { valid ++; test = test +3; } if (valid < 6) { /* This Symbol is valid */ StockPtr = malloc_stock(); ptr = csv_strtok(line, ","); if (!ptr) return 0; symbol = (char *)malloc(strlen(ptr)+1); if (symbol==NULL) { fprintf(stderr,"Memory allocating error (%s line %d)\n" ,__FILE__, __LINE__); exit(1); } strcpy((char *)(symbol), ptr); StockPtr->Symbol = symbol; ptr = csv_strtok(NULL, ","); if (!ptr) return 0; name = (char *)malloc(strlen(ptr)+1); if (name==NULL) { fprintf(stderr,"Memory allocating error (%s line %d)\n" ,__FILE__, __LINE__); exit(1); } strcpy((char *)(name), ptr); StockPtr->Name = name; ptr = csv_strtok(NULL, ","); if (!ptr) return 0; sscanf(ptr,"%f",&(StockPtr->CurrentPrice)); ptr = csv_strtok(NULL, ","); if (!ptr) return 0; date = (char *)malloc(strlen(ptr)+1); if (date==NULL) { fprintf(stderr,"Memory allocating error (%s line %d)\n" ,__FILE__, __LINE__); exit(1); } strcpy((char *)(date), ptr); StockPtr->Date = date; ptr = csv_strtok(NULL, ","); if (!ptr) return 0; time = (char *)malloc(strlen(ptr)+1); if (time==NULL) { fprintf(stderr,"Memory allocating error (%s line %d)\n" ,__FILE__, __LINE__); exit(1); } strcpy((char *)(time), ptr); StockPtr->Time = time; ptr = csv_strtok(NULL, ","); if (!ptr) return 0; sscanf(ptr,"%f",&(StockPtr->Variation)); StockPtr->Pourcentage = 100 * StockPtr->Variation / (StockPtr->CurrentPrice - StockPtr->Variation); StockPtr->LastPrice = StockPtr->CurrentPrice - StockPtr->Variation; ptr = csv_strtok(NULL, ","); if (!ptr) return 0; sscanf(ptr,"%f",&(StockPtr->OpenPrice)); ptr = csv_strtok(NULL, ","); if (!ptr) return 0; sscanf(ptr,"%f",&(StockPtr->MaxPrice)); ptr = csv_strtok(NULL, ","); if (!ptr) return 0; sscanf(ptr,"%f",&(StockPtr->MinPrice)); ptr = csv_strtok(NULL, ","); if (!ptr) return 0; StockPtr->Volume = atoi(ptr); if( !FirstStockPtr ) { FirstStockPtr = StockPtr; StockPtr->PreviousStock = 0; } StockPtr->NextStock = 0; if (LastStockPtr) { LastStockPtr->NextStock = StockPtr; StockPtr->PreviousStock = LastStockPtr; } LastStockPtr = StockPtr; } else { /* this symbol is not valid */ /* Set the stock struct just with Symbol, all other are NULL */ /* This can be used to see if the symbol has been reached are not */ StockPtr = malloc_stock(); ptr = csv_strtok(line, ","); if (!ptr) return 0; symbol = (char *)malloc(strlen(ptr)+1); if (symbol==NULL) { fprintf(stderr,"Memory allocating error (%s line %d)\n" ,__FILE__, __LINE__); exit(1); } strcpy((char *)(symbol), ptr); StockPtr->Symbol = symbol; if( !FirstStockPtr ) { FirstStockPtr = StockPtr; StockPtr->PreviousStock = 0; } StockPtr->NextStock = 0; if (LastStockPtr) { LastStockPtr->NextStock = StockPtr; StockPtr->PreviousStock = LastStockPtr; } LastStockPtr = StockPtr; } end_line++; line = end_line; } return (FirstStockPtr); } /*****************************************************************************/ /* Parses the history quotes file and return a stock structure list. */ /*****************************************************************************/ stock *parse_csv_history_file(char *csv_file) { char *line; char *end_line; char *ptr; int day; char smonth[10]; int month; int year; char *date; int i; int test; stock *StockPtr=NULL; stock *LastStockPtr=NULL; /* Used to return the pointer to the list */ stock *FirstStockPtr=NULL; line = csv_file; end_line = csv_file; /* do not use the first line */ - end_line = strstr(line, "\n"); + if (!(end_line = strstr(line, "\n"))) + return 0; *end_line = 0; end_line++; line = end_line; while ((end_line = strstr(line, "\n"))) { *end_line = 0; StockPtr = malloc_stock(); /* Date */ ptr = strtok(line, ","); if (!ptr) return 0; sscanf(ptr,"%d-%3s-%d",&day,smonth,&year); i=0; #ifdef __UNIX__ while((test=strcasecmp(months[i], smonth))) i++; #elif __WINDOWS__ while(test=_mbsnbicmp(months[i], smonth, strlen(months[i]))) i++; #endif month = i+1; date = (char *)malloc(DATE_LENGTH); if (date==NULL) { fprintf(stderr,"Memory allocating error (%s line %d)\n" ,__FILE__, __LINE__); exit(1); } sprintf(date,"%.2d%.2d%.2d", year, month, day); StockPtr->Date = date; /* Open */ ptr = strtok(NULL, ","); if (!ptr) return 0; sscanf(ptr,"%f",&(StockPtr->OpenPrice)); /* High */ ptr = strtok(NULL, ","); if (!ptr) return 0; sscanf(ptr,"%f",&(StockPtr->MaxPrice)); /* Low */ ptr = strtok(NULL, ","); if (!ptr) return 0; sscanf(ptr,"%f",&(StockPtr->MinPrice)); /* Close */ ptr = strtok(NULL, ","); if (!ptr) return 0; sscanf(ptr,"%f",&(StockPtr->LastPrice)); /* Volume */ ptr = strtok(NULL, ","); if (!ptr) /* It seems to be an indice */ /* No volume for indices */ StockPtr->Volume = 0; else StockPtr->Volume = atoi(ptr); if( !FirstStockPtr ) { FirstStockPtr = StockPtr; StockPtr->PreviousStock = 0; } StockPtr->NextStock = 0; if (LastStockPtr) { LastStockPtr->NextStock = StockPtr; StockPtr->PreviousStock = LastStockPtr; } LastStockPtr = StockPtr; end_line++; line = end_line; } return (FirstStockPtr); } |