Files
libreoffice/sc/source/ui/collab/sendfunc.cxx
Kohei Yoshida a0bd814fb5 Speed up filling of random number generation over entire column.
Because nobody wants to wait forever...

Change-Id: Ie52bff944893b7e3fe9e7908be19d27c692fc1ea
2014-01-30 11:57:00 -05:00

472 lines
14 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "sendfunc.hxx"
#include "formulacell.hxx"
#include "docsh.hxx"
#include "docfunc.hxx"
#include "sccollaboration.hxx"
#include <editeng/editeng.hxx>
#include <editeng/editobj.hxx>
#include <tubes/manager.hxx>
namespace {
OUString formulaCellToString( ScFormulaCell *pCell )
{
(void)pCell; // FIXME: implement me
return OUString();
}
OUString editToString( const EditTextObject& /*rEditText*/ )
{
// FIXME: implement me.
return OUString();
}
EditTextObject stringToEdit( const OUString& /* rStr */ )
{
// FIXME: implement me.
// The code here only serves to make this file compilable.
EditEngine aEditEngine(0);
return *aEditEngine.CreateTextObject();
}
ScFormulaCell* stringToFormulaCell( const OUString &rString )
{
(void)rString; // FIXME: implement me
return NULL;
}
struct ProtocolError {
const char *message;
};
class ScChangeOpReader {
std::vector< OUString > maArgs;
public:
ScChangeOpReader( const OUString &rString)
{
// will need to handle escaping etc.
// Surely someone else wrote this before ! [!?]
enum {
IN_TEXT, CHECK_QUOTE, FIND_LAST_QUOTE, SKIP_SEMI
} eState = CHECK_QUOTE;
sal_Int32 nStart = 0;
for (sal_Int32 n = 0; n < rString.getLength(); n++)
{
if (rString[n] == '\\')
{
n++; // skip next char
continue;
}
switch (eState) {
case CHECK_QUOTE:
if (rString[n] == '"')
{
nStart = n + 1;
eState = FIND_LAST_QUOTE;
break;
}
// else drop through
case IN_TEXT:
if (rString[n] == ';')
{
maArgs.push_back( rString.copy( nStart, n - nStart ) );
nStart = n + 1;
eState = CHECK_QUOTE;
}
break;
case FIND_LAST_QUOTE:
if (rString[n] == '"')
{
maArgs.push_back( rString.copy( nStart, n - nStart ) );
eState = SKIP_SEMI;
break;
}
break;
case SKIP_SEMI:
if (rString[n] == ';')
{
nStart = n + 1;
eState = CHECK_QUOTE;
}
break;
}
}
if ( nStart < rString.getLength())
maArgs.push_back( rString.copy( nStart, rString.getLength() - nStart ) );
}
~ScChangeOpReader() {}
OUString getMethod()
{
return maArgs[0];
}
size_t getArgCount() { return maArgs.size(); }
OUString getString( sal_Int32 n )
{
if (n > 0 && (size_t)n < getArgCount() )
{
OUString aUStr( maArgs[ n ] );
ScGlobal::EraseQuotes( aUStr );
return aUStr;
} else
return OUString();
}
ScAddress getAddress( sal_Int32 n )
{
ScAddress aAddr;
OUString aToken( getString( n ) );
aAddr.Parse( aToken );
return aAddr;
}
sal_Int32 getInt( sal_Int32 n )
{
return getString( n ).toInt32();
}
bool getBool( sal_Int32 n )
{
return getString( n ).equalsIgnoreAsciiCase( "true" );
}
ScFormulaCell* getFormulaCell( sal_Int32 n )
{
return stringToFormulaCell( getString( n ) );
}
double getDouble( sal_Int32 n )
{
return getString(n).toDouble();
}
EditTextObject getEdit( sal_Int32 n )
{
return stringToEdit(getString(n));
}
};
} // anonymous namespace
// Ye noddy mangling - needs improvement ...
// method name ';' then arguments ; separated
class ScChangeOpWriter
{
OUStringBuffer aMessage;
void appendSeparator()
{
aMessage.append( ';' );
}
public:
ScChangeOpWriter( const char *pName )
{
aMessage.appendAscii( pName );
appendSeparator();
}
void appendString( const OUString &rStr )
{
if ( rStr.indexOf( '"' ) >= 0 ||
rStr.indexOf( ';' ) >= 0 )
{
OUString aQuoted( rStr );
ScGlobal::AddQuotes( aQuoted, '"' );
aMessage.append( aQuoted );
}
else
aMessage.append( rStr );
appendSeparator();
}
void appendAddress( const ScAddress &rPos )
{
aMessage.append( rPos.Format( SCA_VALID ) );
appendSeparator();
}
void appendInt( sal_Int32 i )
{
aMessage.append( i );
appendSeparator();
}
void appendBool( sal_Bool b )
{
aMessage.appendAscii( b ? "true" : "false" );
appendSeparator();
}
void appendFormulaCell( ScFormulaCell *pCell )
{
appendString( formulaCellToString( pCell ) );
}
void appendEditText( const EditTextObject& rStr )
{
appendString( editToString(rStr) );
}
void appendDouble( double fVal )
{
aMessage.append(fVal);
appendSeparator();
}
OString toString()
{
return OUStringToOString( aMessage.toString(), RTL_TEXTENCODING_UTF8 );
}
};
void ScDocFuncSend::RecvMessage( const OString &rString )
{
try {
ScChangeOpReader aReader( OUString( rString.getStr(),
rString.getLength(),
RTL_TEXTENCODING_UTF8 ) );
// FIXME: have some hash to enumeration mapping here
if ( aReader.getMethod() == "setNormalString" )
{
bool bNumFmtSet = false;
mpDirect->SetNormalString( bNumFmtSet, aReader.getAddress( 1 ), aReader.getString( 2 ),
aReader.getBool( 3 ) );
}
else if (aReader.getMethod() == "setValueCell")
{
mpDirect->SetValueCell(
aReader.getAddress(1), aReader.getDouble(2), aReader.getBool(3));
}
else if (aReader.getMethod() == "setStringCell")
{
mpDirect->SetStringCell(
aReader.getAddress(1), aReader.getString(2), aReader.getBool(3));
}
else if (aReader.getMethod() == "setEditCell")
{
mpDirect->SetEditCell(
aReader.getAddress(1), aReader.getEdit(2), aReader.getBool(3));
}
else if (aReader.getMethod() == "setFormulaCell")
{
mpDirect->SetFormulaCell(
aReader.getAddress(1), aReader.getFormulaCell(2), aReader.getBool(3));
}
else if ( aReader.getMethod() == "enterListAction" )
mpDirect->EnterListAction( aReader.getInt( 1 ) );
else if ( aReader.getMethod() == "endListAction" )
mpDirect->EndListAction();
else if ( aReader.getMethod() == "showNote" )
mpDirect->ShowNote( aReader.getAddress( 1 ), aReader.getBool( 2 ) );
else if ( aReader.getMethod() == "setNoteText" )
mpDirect->SetNoteText( aReader.getAddress( 1 ), aReader.getString( 2 ),
aReader.getBool( 3 ) );
else if ( aReader.getMethod() == "renameTable" )
mpDirect->RenameTable( aReader.getInt( 1 ), aReader.getString( 2 ),
aReader.getBool( 3 ), aReader.getBool( 4 ) );
else
SAL_WARN( "sc.tubes", "Error: unknown message '" << rString.getStr()
<< "' (" << aReader.getArgCount() << ")" );
} catch (const ProtocolError &e) {
SAL_WARN( "sc.tubes", "Error: protocol twisting: " << e.message );
}
}
void ScDocFuncSend::SendMessage( ScChangeOpWriter &rOp )
{
mpCollaboration->SendPacket( rOp.toString() );
}
// FIXME: really ScDocFunc should be an abstract base, so
// we don't need the rDocSh hack/pointer
ScDocFuncSend::ScDocFuncSend( ScDocShell& rDocSh, ScDocFuncDirect *pDirect, ScCollaboration* pCollaboration )
: ScDocFunc( rDocSh ),
mpDirect( pDirect ),
mpCollaboration( pCollaboration )
{
}
ScDocFuncSend::~ScDocFuncSend()
{
delete mpDirect;
}
void ScDocFuncSend::EnterListAction( sal_uInt16 nNameResId )
{
// Want to group these operations for the other side ...
OUString aUndo( ScGlobal::GetRscString( nNameResId ) );
ScChangeOpWriter aOp( "enterListAction" );
aOp.appendInt( nNameResId ); // nasty but translate-able ...
SendMessage( aOp );
}
void ScDocFuncSend::EndListAction()
{
ScChangeOpWriter aOp( "endListAction" );
SendMessage( aOp );
}
sal_Bool ScDocFuncSend::SetNormalString( bool& o_rbNumFmtSet, const ScAddress& rPos, const OUString& rText, sal_Bool bApi )
{
ScChangeOpWriter aOp( "setNormalString" );
aOp.appendAddress( rPos );
aOp.appendString( rText );
aOp.appendBool( bApi );
SendMessage( aOp );
o_rbNumFmtSet = false;
if ( OUString( rText ) == "saveme" )
mpCollaboration->SaveAndSendFile( NULL );
if ( OUString( rText ) == "contacts" )
mpCollaboration->DisplayContacts();
return true; // needs some code auditing action
}
bool ScDocFuncSend::SetValueCell( const ScAddress& rPos, double fVal, bool bInteraction )
{
ScChangeOpWriter aOp("setValueCell");
aOp.appendAddress( rPos );
aOp.appendDouble( fVal );
aOp.appendBool( bInteraction );
SendMessage( aOp );
return true; // needs some code auditing action
}
bool ScDocFuncSend::SetValueCells(
const ScAddress& /*rPos*/, const std::vector<double>& /*aVals*/, bool /*bInteraction*/ )
{
// TODO : Implement this.
return true;
}
bool ScDocFuncSend::SetStringCell( const ScAddress& rPos, const OUString& rStr, bool bInteraction )
{
ScChangeOpWriter aOp("setStringCell");
aOp.appendAddress( rPos );
aOp.appendString( rStr );
aOp.appendBool( bInteraction );
SendMessage( aOp );
return true; // needs some code auditing action
}
bool ScDocFuncSend::SetEditCell( const ScAddress& rPos, const EditTextObject& rStr, bool bInteraction )
{
ScChangeOpWriter aOp("setEditCell");
aOp.appendAddress( rPos );
aOp.appendEditText( rStr );
aOp.appendBool( bInteraction );
SendMessage( aOp );
return true; // needs some code auditing action
}
bool ScDocFuncSend::SetFormulaCell( const ScAddress& rPos, ScFormulaCell* pCell, bool bInteraction )
{
ScChangeOpWriter aOp("setFormulaCell");
aOp.appendAddress( rPos );
aOp.appendFormulaCell( pCell );
aOp.appendBool( bInteraction );
SendMessage( aOp );
delete pCell;
return true; // needs some code auditing action
}
bool ScDocFuncSend::PutData( const ScAddress& rPos, ScEditEngineDefaulter& rEngine, bool bApi )
{
SAL_INFO( "sc.tubes", "PutData not implemented!" );
return ScDocFunc::PutData( rPos, rEngine, bApi );
}
bool ScDocFuncSend::SetCellText(
const ScAddress& rPos, const OUString& rText, bool bInterpret, bool bEnglish, bool bApi,
const formula::FormulaGrammar::Grammar eGrammar )
{
SAL_INFO( "sc.tubes", "SetCellText not implemented!" );
return ScDocFunc::SetCellText( rPos, rText, bInterpret, bEnglish, bApi, eGrammar );
}
bool ScDocFuncSend::ShowNote( const ScAddress& rPos, bool bShow )
{
ScChangeOpWriter aOp( "showNote" );
aOp.appendAddress( rPos );
aOp.appendBool( bShow );
SendMessage( aOp );
return true; // needs some code auditing action
}
bool ScDocFuncSend::SetNoteText( const ScAddress& rPos, const OUString& rNoteText, sal_Bool bApi )
{
ScChangeOpWriter aOp( "setNoteText" );
aOp.appendAddress( rPos );
aOp.appendString( rNoteText );
aOp.appendBool( bApi );
SendMessage( aOp );
return true; // needs some code auditing action
}
sal_Bool ScDocFuncSend::RenameTable( SCTAB nTab, const OUString& rName,
sal_Bool bRecord, sal_Bool bApi )
{
ScChangeOpWriter aOp( "renameTable" );
aOp.appendInt( nTab );
aOp.appendString( rName );
aOp.appendBool( bRecord );
aOp.appendBool( bApi );
SendMessage( aOp );
return true; // needs some code auditing action
}
sal_Bool ScDocFuncSend::ApplyAttributes( const ScMarkData& rMark, const ScPatternAttr& rPattern,
sal_Bool bRecord, sal_Bool bApi )
{
SAL_INFO( "sc.tubes", "ApplyAttributes not implemented!" );
return ScDocFunc::ApplyAttributes( rMark, rPattern, bRecord, bApi );
}
sal_Bool ScDocFuncSend::ApplyStyle( const ScMarkData& rMark, const OUString& rStyleName,
sal_Bool bRecord, sal_Bool bApi )
{
SAL_INFO( "sc.tubes", "ApplyStyle not implemented!" );
return ScDocFunc::ApplyStyle( rMark, rStyleName, bRecord, bApi );
}
sal_Bool ScDocFuncSend::MergeCells( const ScCellMergeOption& rOption, sal_Bool bContents,
sal_Bool bRecord, sal_Bool bApi )
{
SAL_INFO( "sc.tubes", "MergeCells not implemented!" );
return ScDocFunc::MergeCells( rOption, bContents, bRecord, bApi );
}
ScDocFunc *ScDocShell::CreateDocFunc()
{
if (TeleManager::hasWaitingConference())
{
TeleConference* pConference = TeleManager::getConference();
if (pConference)
{
mpCollaboration->SetConference( pConference );
return new ScDocFuncSend( *this, new ScDocFuncDirect( *this ), mpCollaboration );
}
}
return new ScDocFuncDirect( *this );
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */